Skip to main content

ide/
goto_definition.rs

1use std::{iter, mem::discriminant};
2
3use crate::Analysis;
4use crate::{
5    FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult,
6    doc_links::token_as_doc_comment,
7    navigation_target::{self, ToNav},
8};
9use hir::{
10    AsAssocItem, AssocItem, CallableKind, FileRange, HasCrate, InFile, ModuleDef, Semantics, sym,
11};
12use ide_db::ra_fixture::{RaFixtureConfig, UpmapFromRaFixture};
13use ide_db::{
14    RootDatabase, SymbolKind,
15    base_db::{AnchoredPath, SourceDatabase},
16    defs::{Definition, IdentClass},
17    famous_defs::FamousDefs,
18    helpers::pick_best_token,
19    syntax_helpers::node_ext::find_loops,
20};
21use itertools::Itertools;
22use span::FileId;
23use syntax::{
24    AstNode, AstToken, SyntaxKind::*, SyntaxNode, SyntaxToken, T, TextRange, ast, match_ast,
25};
26
27#[derive(Debug)]
28pub struct GotoDefinitionConfig<'a> {
29    pub ra_fixture: RaFixtureConfig<'a>,
30}
31
32// Feature: Go to Definition
33//
34// Navigates to the definition of an identifier.
35//
36// For outline modules, this will navigate to the source file of the module.
37//
38// | Editor  | Shortcut |
39// |---------|----------|
40// | VS Code | <kbd>F12</kbd> |
41//
42// ![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif)
43pub(crate) fn goto_definition(
44    db: &RootDatabase,
45    FilePosition { file_id, offset }: FilePosition,
46    config: &GotoDefinitionConfig<'_>,
47) -> Option<RangeInfo<Vec<NavigationTarget>>> {
48    let sema = &Semantics::new(db);
49    let file = sema.parse_guess_edition(file_id).syntax().clone();
50    let edition = sema.attach_first_edition(file_id).edition(db);
51    let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
52        IDENT
53        | INT_NUMBER
54        | LIFETIME_IDENT
55        | T![self]
56        | T![super]
57        | T![crate]
58        | T![Self]
59        | COMMENT => 4,
60        // index and prefix ops
61        T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
62        kind if kind.is_keyword(edition) => 2,
63        T!['('] | T![')'] => 2,
64        kind if kind.is_trivia() => 0,
65        _ => 1,
66    })?;
67    if let Some(doc_comment) = token_as_doc_comment(&original_token) {
68        return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, link_range| {
69            let nav = def.try_to_nav(sema)?;
70            Some(RangeInfo::new(link_range, nav.collect()))
71        });
72    }
73
74    if let Some((range, _, _, resolution)) =
75        sema.check_for_format_args_template(original_token.clone(), offset)
76    {
77        return Some(RangeInfo::new(
78            range,
79            match resolution {
80                Some(res) => def_to_nav(sema, Definition::from(res)),
81                None => vec![],
82            },
83        ));
84    }
85
86    if let Some(navs) = handle_control_flow_keywords(sema, &original_token) {
87        return Some(RangeInfo::new(original_token.text_range(), navs));
88    }
89
90    let tokens = sema.descend_into_macros_no_opaque(original_token.clone(), false);
91    let mut navs = Vec::new();
92    for token in tokens {
93        if let Some(n) = find_definition_for_known_blanket_dual_impls(sema, &token.value) {
94            navs.extend(n);
95            continue;
96        }
97
98        if let Some(n) = find_definition_for_comparison_operators(sema, &token.value) {
99            navs.extend(n);
100            continue;
101        }
102
103        let parent = token.value.parent()?;
104
105        if let Some(question_mark_conversion) = goto_question_mark_conversions(sema, &parent) {
106            navs.extend(def_to_nav(sema, question_mark_conversion.into()));
107            continue;
108        }
109
110        if let Some(token) = ast::String::cast(token.value.clone())
111            && let Some(original_token) = ast::String::cast(original_token.clone())
112            && let Some((analysis, fixture_analysis)) =
113                Analysis::from_ra_fixture(sema, original_token, &token, &config.ra_fixture)
114            && let Some((virtual_file_id, file_offset)) = fixture_analysis.map_offset_down(offset)
115        {
116            return hir::attach_db_allow_change(&analysis.db, || {
117                goto_definition(
118                    &analysis.db,
119                    FilePosition { file_id: virtual_file_id, offset: file_offset },
120                    config,
121                )
122            })
123            .and_then(|navs| {
124                navs.upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id).ok()
125            });
126        }
127
128        let token_file_id = token.file_id;
129        if let Some(token) = ast::String::cast(token.value.clone())
130            && let Some(x) =
131                try_lookup_include_path(sema, InFile::new(token_file_id, token), file_id)
132        {
133            navs.push(x);
134            continue;
135        }
136
137        if ast::TokenTree::can_cast(parent.kind())
138            && let Some(x) = try_lookup_macro_def_in_macro_use(sema, token.value)
139        {
140            navs.push(x);
141            continue;
142        }
143
144        let Some(ident_class) = IdentClass::classify_node(sema, &parent) else { continue };
145        navs.extend(ident_class.definitions().into_iter().flat_map(|(def, _)| {
146            if let Definition::ExternCrateDecl(crate_def) = def {
147                return crate_def
148                    .resolved_crate(db)
149                    .map(|it| it.root_module(db).to_nav(db))
150                    .into_iter()
151                    .flatten()
152                    .collect();
153            }
154            try_filter_trait_item_definition(sema, &def).unwrap_or_else(|| def_to_nav(sema, def))
155        }));
156    }
157    let navs = navs.into_iter().unique().collect();
158
159    Some(RangeInfo::new(original_token.text_range(), navs))
160}
161
162/// When the `?` operator is used on `Result`, go to the `From` impl if it exists as this provides more value.
163fn goto_question_mark_conversions(
164    sema: &Semantics<'_, RootDatabase>,
165    node: &SyntaxNode,
166) -> Option<hir::Function> {
167    let node = ast::TryExpr::cast(node.clone())?;
168    let try_expr_ty = sema.type_of_expr(&node.expr()?)?.adjusted();
169
170    let fd = FamousDefs(sema, try_expr_ty.krate(sema.db));
171    let result_enum = fd.core_result_Result()?.into();
172
173    let (try_expr_ty_adt, try_expr_ty_args) = try_expr_ty.as_adt_with_args()?;
174    if try_expr_ty_adt != result_enum {
175        // FIXME: Support `Poll<Result>`.
176        return None;
177    }
178    let original_err_ty = try_expr_ty_args.get(1)?.clone()?;
179
180    let returned_ty = sema.try_expr_returned_type(&node)?;
181    let (returned_adt, returned_ty_args) = returned_ty.as_adt_with_args()?;
182    if returned_adt != result_enum {
183        return None;
184    }
185    let returned_err_ty = returned_ty_args.get(1)?.clone()?;
186
187    if returned_err_ty.could_unify_with_deeply(sema.db, &original_err_ty) {
188        return None;
189    }
190
191    let from_trait = fd.core_convert_From()?;
192    let from_fn = from_trait.function(sema.db, sym::from)?;
193    sema.resolve_trait_impl_method(
194        returned_err_ty.clone(),
195        from_trait,
196        from_fn,
197        [returned_err_ty, original_err_ty],
198    )
199}
200
201// If the token is into(), try_into(), search the definition of From, TryFrom.
202fn find_definition_for_known_blanket_dual_impls(
203    sema: &Semantics<'_, RootDatabase>,
204    original_token: &SyntaxToken,
205) -> Option<Vec<NavigationTarget>> {
206    let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
207    let callable = sema.resolve_method_call_as_callable(&method_call)?;
208    let CallableKind::Function(f) = callable.kind() else { return None };
209    let assoc = f.as_assoc_item(sema.db)?;
210
211    let return_type = callable.return_type();
212    let fd = FamousDefs(sema, return_type.krate(sema.db));
213
214    let t = match assoc.container(sema.db) {
215        hir::AssocItemContainer::Trait(t) => t,
216        hir::AssocItemContainer::Impl(impl_)
217            if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>
218        {
219            let t = fd.core_convert_FromStr()?;
220            let t_f = t.function(sema.db, &sym::from_str)?;
221            return sema
222                .resolve_trait_impl_method(
223                    return_type.clone(),
224                    t,
225                    t_f,
226                    [return_type.type_arguments().next()?],
227                )
228                .map(|f| def_to_nav(sema, f.into()));
229        }
230        hir::AssocItemContainer::Impl(_) => return None,
231    };
232
233    let fn_name = f.name(sema.db);
234    let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) {
235        let dual = fd.core_convert_From()?;
236        let dual_f = dual.function(sema.db, &sym::from)?;
237        sema.resolve_trait_impl_method(
238            return_type.clone(),
239            dual,
240            dual_f,
241            [return_type, callable.receiver_param(sema.db)?.1],
242        )?
243    } else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) {
244        let dual = fd.core_convert_TryFrom()?;
245        let dual_f = dual.function(sema.db, &sym::try_from)?;
246        sema.resolve_trait_impl_method(
247            return_type.clone(),
248            dual,
249            dual_f,
250            // Extract the `T` from `Result<T, ..>`
251            [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1],
252        )?
253    } else if fn_name == sym::to_string && fd.alloc_string_ToString() == Some(t) {
254        let dual = fd.core_fmt_Display()?;
255        let dual_f = dual.function(sema.db, &sym::fmt)?;
256        sema.resolve_trait_impl_method(
257            return_type.clone(),
258            dual,
259            dual_f,
260            [callable.receiver_param(sema.db)?.1.strip_reference()],
261        )?
262    } else {
263        return None;
264    };
265    // Assert that we got a trait impl function, if we are back in a trait definition we didn't
266    // succeed
267    let _t = f.as_assoc_item(sema.db)?.implemented_trait(sema.db)?;
268    let def = Definition::from(f);
269    Some(def_to_nav(sema, def))
270}
271
272// If the token is a comparison operator (!=, <, <=, >, >=) that resolves to a default trait method, navigate to the corresponding primary method (eq for ne, partial_cmp for the others).
273fn find_definition_for_comparison_operators(
274    sema: &Semantics<'_, RootDatabase>,
275    original_token: &SyntaxToken,
276) -> Option<Vec<NavigationTarget>> {
277    let bin_expr = ast::BinExpr::cast(original_token.parent()?)?;
278
279    let f = sema.resolve_bin_expr(&bin_expr)?;
280    let assoc = f.as_assoc_item(sema.db)?;
281
282    let lhs_type = sema.type_of_expr(&bin_expr.lhs()?)?.original;
283    let rhs_type = sema.type_of_expr(&bin_expr.rhs()?)?.original;
284
285    let t = match assoc.container(sema.db) {
286        hir::AssocItemContainer::Trait(t) => t,
287        hir::AssocItemContainer::Impl(_) => return None, // Already implemented by the type
288    };
289
290    let fn_name = f.name(sema.db);
291    let fn_name_str = fn_name.as_str();
292
293    let trait_name = t.name(sema.db);
294    let trait_name_str = trait_name.as_str();
295
296    let (target_fn_name, expected_trait) = match fn_name_str {
297        "ne" => ("eq", "PartialEq"),
298        "lt" | "le" | "gt" | "ge" => ("partial_cmp", "PartialOrd"),
299        _ => return None,
300    };
301
302    if trait_name_str != expected_trait {
303        return None;
304    }
305
306    let primary_f = t.items(sema.db).into_iter().find_map(|item| {
307        if let hir::AssocItem::Function(func) = item
308            && func.name(sema.db).as_str() == target_fn_name
309        {
310            return Some(func);
311        }
312        None
313    })?;
314
315    // Chalk requires ALL trait substitutions, including `Self`!
316    // We must pass [Self, Rhs]
317    let resolved_f = sema.resolve_trait_impl_method(
318        lhs_type.clone(),
319        t,
320        primary_f,
321        [lhs_type.clone(), rhs_type.clone()],
322    )?;
323
324    let def = Definition::from(resolved_f);
325
326    Some(def_to_nav(sema, def))
327}
328fn try_lookup_include_path(
329    sema: &Semantics<'_, RootDatabase>,
330    token: InFile<ast::String>,
331    file_id: FileId,
332) -> Option<NavigationTarget> {
333    let file = token.file_id.macro_file()?;
334
335    // Check that we are in the eager argument expansion of an include macro
336    // that is we are the string input of it
337    if !iter::successors(Some(file), |file| file.parent(sema.db).macro_file())
338        .any(|file| file.is_include_like_macro(sema.db) && file.eager_arg(sema.db).is_none())
339    {
340        return None;
341    }
342    let path = token.value.value().ok()?;
343
344    let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;
345    let size = sema.db.file_text(file_id).text(sema.db).len().try_into().ok()?;
346    Some(NavigationTarget {
347        file_id,
348        full_range: TextRange::new(0.into(), size),
349        name: hir::Symbol::intern(&path),
350        alias: None,
351        focus_range: None,
352        kind: None,
353        container_name: None,
354        description: None,
355        docs: None,
356    })
357}
358
359fn try_lookup_macro_def_in_macro_use(
360    sema: &Semantics<'_, RootDatabase>,
361    token: SyntaxToken,
362) -> Option<NavigationTarget> {
363    let extern_crate = token.parent()?.ancestors().find_map(ast::ExternCrate::cast)?;
364    let extern_crate = sema.to_def(&extern_crate)?;
365    let krate = extern_crate.resolved_crate(sema.db)?;
366
367    for mod_def in krate.root_module(sema.db).declarations(sema.db) {
368        if let ModuleDef::Macro(mac) = mod_def
369            && mac.name(sema.db).as_str() == token.text()
370            && let Some(nav) = mac.try_to_nav(sema)
371        {
372            return Some(nav.call_site);
373        }
374    }
375
376    None
377}
378
379/// finds the trait definition of an impl'd item, except function
380/// e.g.
381/// ```rust
382/// trait A { type a; }
383/// struct S;
384/// impl A for S { type a = i32; } // <-- on this associate type, will get the location of a in the trait
385/// ```
386fn try_filter_trait_item_definition(
387    sema: &Semantics<'_, RootDatabase>,
388    def: &Definition,
389) -> Option<Vec<NavigationTarget>> {
390    let db = sema.db;
391    let assoc = def.as_assoc_item(db)?;
392    match assoc {
393        AssocItem::Function(..) => None,
394        AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
395            let trait_ = assoc.implemented_trait(db)?;
396            let name = def.name(db)?;
397            let discriminant_value = discriminant(&assoc);
398            trait_
399                .items(db)
400                .iter()
401                .filter(|itm| discriminant(*itm) == discriminant_value)
402                .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(sema)).flatten())
403                .map(|it| it.collect())
404        }
405    }
406}
407
408fn handle_control_flow_keywords(
409    sema: &Semantics<'_, RootDatabase>,
410    token: &SyntaxToken,
411) -> Option<Vec<NavigationTarget>> {
412    match token.kind() {
413        // For `fn` / `loop` / `while` / `for` / `async` / `match`, return the keyword it self,
414        // so that VSCode will find the references when using `ctrl + click`
415        T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),
416        T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),
417        T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
418            nav_for_break_points(sema, token)
419        }
420        T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),
421        _ => None,
422    }
423}
424
425pub(crate) fn find_fn_or_blocks(
426    sema: &Semantics<'_, RootDatabase>,
427    token: &SyntaxToken,
428) -> Vec<SyntaxNode> {
429    let find_ancestors = |token: SyntaxToken| {
430        let token_kind = token.kind();
431
432        for anc in sema.token_ancestors_with_macros(token) {
433            let node = match_ast! {
434                match anc {
435                    ast::Fn(fn_) => fn_.syntax().clone(),
436                    ast::ClosureExpr(c) => c.syntax().clone(),
437                    ast::BlockExpr(blk) => {
438                        match blk.modifier() {
439                            Some(ast::BlockModifier::Async(_)) => blk.syntax().clone(),
440                            Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => blk.syntax().clone(),
441                            _ => continue,
442                        }
443                    },
444                    _ => continue,
445                }
446            };
447
448            return Some(node);
449        }
450        None
451    };
452
453    sema.descend_into_macros(token.clone()).into_iter().filter_map(find_ancestors).collect_vec()
454}
455
456fn nav_for_exit_points(
457    sema: &Semantics<'_, RootDatabase>,
458    token: &SyntaxToken,
459) -> Option<Vec<NavigationTarget>> {
460    let db = sema.db;
461    let token_kind = token.kind();
462
463    let navs = find_fn_or_blocks(sema, token)
464        .into_iter()
465        .filter_map(|node| {
466            let file_id = sema.hir_file_for(&node);
467
468            match_ast! {
469                match node {
470                    ast::Fn(fn_) => {
471                        let mut nav = sema.to_def(&fn_)?.try_to_nav(sema)?;
472                        // For async token, we navigate to itself, which triggers
473                        // VSCode to find the references
474                        let focus_token = if matches!(token_kind, T![async]) {
475                            fn_.async_token()?
476                        } else {
477                            fn_.fn_token()?
478                        };
479
480                        let focus_frange = InFile::new(file_id, focus_token.text_range())
481                            .original_node_file_range_opt(db)
482                            .map(|(frange, _)| frange);
483
484                        if let Some(FileRange { file_id, range }) = focus_frange {
485                            let contains_frange = |nav: &NavigationTarget| {
486                                nav.file_id == file_id.file_id(db) && nav.full_range.contains_range(range)
487                            };
488
489                            if let Some(def_site) = nav.def_site.as_mut() {
490                                if contains_frange(def_site) {
491                                    def_site.focus_range = Some(range);
492                                }
493                            } else if contains_frange(&nav.call_site) {
494                                nav.call_site.focus_range = Some(range);
495                            }
496                        }
497
498                        Some(nav)
499                    },
500                    ast::ClosureExpr(c) => {
501                        let pipe_tok = c.param_list().and_then(|it| it.pipe_token())?.text_range();
502                        let closure_in_file = InFile::new(file_id, c.into());
503                        Some(expr_to_nav(db, closure_in_file, Some(pipe_tok)))
504                    },
505                    ast::BlockExpr(blk) => {
506                        match blk.modifier() {
507                            Some(ast::BlockModifier::Async(_)) => {
508                                let async_tok = blk.async_token()?.text_range();
509                                let blk_in_file = InFile::new(file_id, blk.into());
510                                Some(expr_to_nav(db, blk_in_file, Some(async_tok)))
511                            },
512                            Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => {
513                                let try_tok = blk.try_block_modifier()?.try_token()?.text_range();
514                                let blk_in_file = InFile::new(file_id, blk.into());
515                                Some(expr_to_nav(db, blk_in_file, Some(try_tok)))
516                            },
517                            _ => None,
518                        }
519                    },
520                    _ => None,
521                }
522            }
523        })
524        .flatten()
525        .collect_vec();
526
527    Some(navs)
528}
529
530pub(crate) fn find_branch_root(
531    sema: &Semantics<'_, RootDatabase>,
532    token: &SyntaxToken,
533) -> Vec<SyntaxNode> {
534    let find_nodes = |node_filter: fn(SyntaxNode) -> Option<SyntaxNode>| {
535        sema.descend_into_macros(token.clone())
536            .into_iter()
537            .filter_map(|token| node_filter(token.parent()?))
538            .collect_vec()
539    };
540
541    match token.kind() {
542        T![match] => find_nodes(|node| Some(ast::MatchExpr::cast(node)?.syntax().clone())),
543        T![=>] => find_nodes(|node| Some(ast::MatchArm::cast(node)?.syntax().clone())),
544        T![if] => find_nodes(|node| {
545            let if_expr = ast::IfExpr::cast(node)?;
546
547            let root_if = iter::successors(Some(if_expr.clone()), |if_expr| {
548                let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
549                let ast::ElseBranch::IfExpr(else_branch) = parent_if.else_branch()? else {
550                    return None;
551                };
552
553                (else_branch.syntax() == if_expr.syntax()).then_some(parent_if)
554            })
555            .last()?;
556
557            Some(root_if.syntax().clone())
558        }),
559        _ => vec![],
560    }
561}
562
563fn nav_for_branch_exit_points(
564    sema: &Semantics<'_, RootDatabase>,
565    token: &SyntaxToken,
566) -> Option<Vec<NavigationTarget>> {
567    let db = sema.db;
568
569    let navs = match token.kind() {
570        T![match] => find_branch_root(sema, token)
571            .into_iter()
572            .filter_map(|node| {
573                let file_id = sema.hir_file_for(&node);
574                let match_expr = ast::MatchExpr::cast(node)?;
575                let focus_range = match_expr.match_token()?.text_range();
576                let match_expr_in_file = InFile::new(file_id, match_expr.into());
577                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
578            })
579            .flatten()
580            .collect_vec(),
581
582        T![=>] => find_branch_root(sema, token)
583            .into_iter()
584            .filter_map(|node| {
585                let match_arm = ast::MatchArm::cast(node)?;
586                let match_expr = sema
587                    .ancestors_with_macros(match_arm.syntax().clone())
588                    .find_map(ast::MatchExpr::cast)?;
589                let file_id = sema.hir_file_for(match_expr.syntax());
590                let focus_range = match_arm.fat_arrow_token()?.text_range();
591                let match_expr_in_file = InFile::new(file_id, match_expr.into());
592                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
593            })
594            .flatten()
595            .collect_vec(),
596
597        T![if] => find_branch_root(sema, token)
598            .into_iter()
599            .filter_map(|node| {
600                let file_id = sema.hir_file_for(&node);
601                let if_expr = ast::IfExpr::cast(node)?;
602                let focus_range = if_expr.if_token()?.text_range();
603                let if_expr_in_file = InFile::new(file_id, if_expr.into());
604                Some(expr_to_nav(db, if_expr_in_file, Some(focus_range)))
605            })
606            .flatten()
607            .collect_vec(),
608
609        _ => return Some(Vec::new()),
610    };
611
612    Some(navs)
613}
614
615fn nav_for_break_points(
616    sema: &Semantics<'_, RootDatabase>,
617    token: &SyntaxToken,
618) -> Option<Vec<NavigationTarget>> {
619    let db = sema.db;
620
621    let navs = find_loops(sema, token)?
622        .filter_map(|expr| {
623            let file_id = sema.hir_file_for(expr.syntax());
624            let expr_in_file = InFile::new(file_id, expr.clone());
625            let focus_range = match expr {
626                ast::Expr::LoopExpr(loop_) => loop_.loop_token()?.text_range(),
627                ast::Expr::WhileExpr(while_) => while_.while_token()?.text_range(),
628                ast::Expr::ForExpr(for_) => for_.for_token()?.text_range(),
629                // We guarantee that the label exists
630                ast::Expr::BlockExpr(blk) => blk.label().unwrap().syntax().text_range(),
631                _ => return None,
632            };
633            let nav = expr_to_nav(db, expr_in_file, Some(focus_range));
634            Some(nav)
635        })
636        .flatten()
637        .collect_vec();
638
639    Some(navs)
640}
641
642fn def_to_nav(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Vec<NavigationTarget> {
643    def.try_to_nav(sema).map(|it| it.collect()).unwrap_or_default()
644}
645
646fn expr_to_nav(
647    db: &RootDatabase,
648    InFile { file_id, value }: InFile<ast::Expr>,
649    focus_range: Option<TextRange>,
650) -> UpmappingResult<NavigationTarget> {
651    let kind = SymbolKind::Label;
652
653    let value_range = value.syntax().text_range();
654    let navs = navigation_target::orig_range_with_focus_r(db, file_id, value_range, focus_range);
655    navs.map(|(hir::FileRangeWrapper { file_id, range }, focus_range)| {
656        NavigationTarget::from_syntax(
657            file_id,
658            hir::Symbol::intern("<expr>"),
659            focus_range,
660            range,
661            kind,
662        )
663    })
664}
665
666#[cfg(test)]
667mod tests {
668    use crate::{GotoDefinitionConfig, fixture};
669    use ide_db::{FileRange, ra_fixture::RaFixtureConfig};
670    use itertools::Itertools;
671
672    const TEST_CONFIG: GotoDefinitionConfig<'_> =
673        GotoDefinitionConfig { ra_fixture: RaFixtureConfig::default() };
674
675    #[track_caller]
676    fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
677        let (analysis, position, expected) = fixture::annotations(ra_fixture);
678        let navs = analysis
679            .goto_definition(position, &TEST_CONFIG)
680            .unwrap()
681            .expect("no definition found")
682            .info;
683
684        let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());
685        let navs = navs
686            .into_iter()
687            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
688            .sorted_by_key(cmp)
689            .collect::<Vec<_>>();
690        let expected = expected
691            .into_iter()
692            .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range })
693            .sorted_by_key(cmp)
694            .collect::<Vec<_>>();
695
696        assert_eq!(expected, navs);
697    }
698
699    fn check_unresolved(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
700        let (analysis, position) = fixture::position(ra_fixture);
701        let navs = analysis
702            .goto_definition(position, &TEST_CONFIG)
703            .unwrap()
704            .expect("no definition found")
705            .info;
706
707        assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}")
708    }
709
710    fn check_name(expected_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) {
711        let (analysis, position, _) = fixture::annotations(ra_fixture);
712        let navs = analysis
713            .goto_definition(position, &TEST_CONFIG)
714            .unwrap()
715            .expect("no definition found")
716            .info;
717        assert!(navs.len() < 2, "expected single navigation target but encountered {}", navs.len());
718        let Some(target) = navs.into_iter().next() else {
719            panic!("expected single navigation target but encountered none");
720        };
721        assert_eq!(target.name, hir::Symbol::intern(expected_name));
722    }
723
724    #[test]
725    fn goto_def_pat_range_to_inclusive() {
726        check_name(
727            "RangeToInclusive",
728            r#"
729//- minicore: range
730fn f(ch: char) -> bool {
731    match ch {
732        ..$0='z' => true,
733        _ => false
734    }
735}
736"#,
737        );
738    }
739
740    #[test]
741    fn goto_def_pat_range_to() {
742        check_name(
743            "RangeTo",
744            r#"
745//- minicore: range
746fn f(ch: char) -> bool {
747    match ch {
748        .$0.'z' => true,
749        _ => false
750    }
751}
752"#,
753        );
754    }
755
756    #[test]
757    fn goto_def_pat_range() {
758        check_name(
759            "Range",
760            r#"
761//- minicore: range
762fn f(ch: char) -> bool {
763    match ch {
764        'a'.$0.'z' => true,
765        _ => false
766    }
767}
768"#,
769        );
770    }
771
772    #[test]
773    fn goto_def_pat_range_inclusive() {
774        check_name(
775            "RangeInclusive",
776            r#"
777//- minicore: range
778fn f(ch: char) -> bool {
779    match ch {
780        'a'..$0='z' => true,
781        _ => false
782    }
783}
784"#,
785        );
786    }
787
788    #[test]
789    fn goto_def_pat_range_from() {
790        check_name(
791            "RangeFrom",
792            r#"
793//- minicore: range
794fn f(ch: char) -> bool {
795    match ch {
796        'a'..$0 => true,
797        _ => false
798    }
799}
800"#,
801        );
802    }
803
804    #[test]
805    fn goto_def_expr_range() {
806        check_name(
807            "Range",
808            r#"
809//- minicore: range
810let x = 0.$0.1;
811"#,
812        );
813    }
814
815    #[test]
816    fn goto_def_expr_range_from() {
817        check_name(
818            "RangeFrom",
819            r#"
820//- minicore: range
821fn f(arr: &[i32]) -> &[i32] {
822    &arr[0.$0.]
823}
824"#,
825        );
826    }
827
828    #[test]
829    fn goto_def_expr_range_inclusive() {
830        check_name(
831            "RangeInclusive",
832            r#"
833//- minicore: range
834let x = 0.$0.=1;
835"#,
836        );
837    }
838
839    #[test]
840    fn goto_def_expr_range_full() {
841        check_name(
842            "RangeFull",
843            r#"
844//- minicore: range
845fn f(arr: &[i32]) -> &[i32] {
846    &arr[.$0.]
847}
848"#,
849        );
850    }
851
852    #[test]
853    fn goto_def_expr_range_to() {
854        check_name(
855            "RangeTo",
856            r#"
857//- minicore: range
858fn f(arr: &[i32]) -> &[i32] {
859    &arr[.$0.10]
860}
861"#,
862        );
863    }
864
865    #[test]
866    fn goto_def_expr_range_to_inclusive() {
867        check_name(
868            "RangeToInclusive",
869            r#"
870//- minicore: range
871fn f(arr: &[i32]) -> &[i32] {
872    &arr[.$0.=10]
873}
874"#,
875        );
876    }
877
878    #[test]
879    fn goto_def_in_included_file() {
880        check(
881            r#"
882//- minicore:include
883//- /main.rs
884
885include!("a.rs");
886
887fn main() {
888    foo();
889}
890
891//- /a.rs
892fn func_in_include() {
893 //^^^^^^^^^^^^^^^
894}
895
896fn foo() {
897    func_in_include$0();
898}
899"#,
900        );
901    }
902
903    #[test]
904    fn goto_def_in_included_file_nested() {
905        check(
906            r#"
907//- minicore:include
908//- /main.rs
909
910macro_rules! passthrough {
911    ($($tt:tt)*) => { $($tt)* }
912}
913
914passthrough!(include!("a.rs"));
915
916fn main() {
917    foo();
918}
919
920//- /a.rs
921fn func_in_include() {
922 //^^^^^^^^^^^^^^^
923}
924
925fn foo() {
926    func_in_include$0();
927}
928"#,
929        );
930    }
931
932    #[test]
933    fn goto_def_in_included_file_inside_mod() {
934        check(
935            r#"
936//- minicore:include
937//- /main.rs
938mod a {
939    include!("b.rs");
940}
941//- /b.rs
942fn func_in_include() {
943 //^^^^^^^^^^^^^^^
944}
945fn foo() {
946    func_in_include$0();
947}
948"#,
949        );
950
951        check(
952            r#"
953//- minicore:include
954//- /main.rs
955mod a {
956    include!("a.rs");
957}
958//- /a.rs
959fn func_in_include() {
960 //^^^^^^^^^^^^^^^
961}
962
963fn foo() {
964    func_in_include$0();
965}
966"#,
967        );
968    }
969
970    #[test]
971    fn goto_def_if_items_same_name() {
972        check(
973            r#"
974trait Trait {
975    type A;
976    const A: i32;
977        //^
978}
979
980struct T;
981impl Trait for T {
982    type A = i32;
983    const A$0: i32 = -9;
984}"#,
985        );
986    }
987    #[test]
988    fn goto_def_in_mac_call_in_attr_invoc() {
989        check(
990            r#"
991//- proc_macros: identity
992pub struct Struct {
993        // ^^^^^^
994    field: i32,
995}
996
997macro_rules! identity {
998    ($($tt:tt)*) => {$($tt)*};
999}
1000
1001#[proc_macros::identity]
1002fn function() {
1003    identity!(Struct$0 { field: 0 });
1004}
1005
1006"#,
1007        )
1008    }
1009
1010    #[test]
1011    fn goto_def_for_extern_crate() {
1012        check(
1013            r#"
1014//- /main.rs crate:main deps:std
1015extern crate std$0;
1016//- /std/lib.rs crate:std
1017// empty
1018//^file
1019"#,
1020        )
1021    }
1022
1023    #[test]
1024    fn goto_def_for_renamed_extern_crate() {
1025        check(
1026            r#"
1027//- /main.rs crate:main deps:std
1028extern crate std as abc$0;
1029//- /std/lib.rs crate:std
1030// empty
1031//^file
1032"#,
1033        )
1034    }
1035
1036    #[test]
1037    fn goto_def_in_items() {
1038        check(
1039            r#"
1040struct Foo;
1041     //^^^
1042enum E { X(Foo$0) }
1043"#,
1044        );
1045    }
1046
1047    #[test]
1048    fn goto_def_at_start_of_item() {
1049        check(
1050            r#"
1051struct Foo;
1052     //^^^
1053enum E { X($0Foo) }
1054"#,
1055        );
1056    }
1057
1058    #[test]
1059    fn goto_definition_resolves_correct_name() {
1060        check(
1061            r#"
1062//- /lib.rs
1063use a::Foo;
1064mod a;
1065mod b;
1066enum E { X(Foo$0) }
1067
1068//- /a.rs
1069pub struct Foo;
1070         //^^^
1071//- /b.rs
1072pub struct Foo;
1073"#,
1074        );
1075    }
1076
1077    #[test]
1078    fn goto_def_for_module_declaration() {
1079        check(
1080            r#"
1081//- /lib.rs
1082mod $0foo;
1083
1084//- /foo.rs
1085// empty
1086//^file
1087"#,
1088        );
1089
1090        check(
1091            r#"
1092//- /lib.rs
1093mod $0foo;
1094
1095//- /foo/mod.rs
1096// empty
1097//^file
1098"#,
1099        );
1100    }
1101
1102    #[test]
1103    fn goto_def_for_macros() {
1104        check(
1105            r#"
1106macro_rules! foo { () => { () } }
1107           //^^^
1108fn bar() {
1109    $0foo!();
1110}
1111"#,
1112        );
1113    }
1114
1115    #[test]
1116    fn goto_def_for_macros_from_other_crates() {
1117        check(
1118            r#"
1119//- /lib.rs crate:main deps:foo
1120use foo::foo;
1121fn bar() {
1122    $0foo!();
1123}
1124
1125//- /foo/lib.rs crate:foo
1126#[macro_export]
1127macro_rules! foo { () => { () } }
1128           //^^^
1129"#,
1130        );
1131    }
1132
1133    #[test]
1134    fn goto_def_for_macros_in_use_tree() {
1135        check(
1136            r#"
1137//- /lib.rs crate:main deps:foo
1138use foo::foo$0;
1139
1140//- /foo/lib.rs crate:foo
1141#[macro_export]
1142macro_rules! foo { () => { () } }
1143           //^^^
1144"#,
1145        );
1146    }
1147
1148    #[test]
1149    fn goto_def_for_macro_defined_fn_with_arg() {
1150        check(
1151            r#"
1152//- /lib.rs
1153macro_rules! define_fn {
1154    ($name:ident) => (fn $name() {})
1155}
1156
1157define_fn!(foo);
1158         //^^^
1159
1160fn bar() {
1161   $0foo();
1162}
1163"#,
1164        );
1165    }
1166
1167    #[test]
1168    fn goto_def_for_macro_defined_fn_no_arg() {
1169        check(
1170            r#"
1171//- /lib.rs
1172macro_rules! define_fn {
1173    () => (fn foo() {})
1174            //^^^
1175}
1176
1177  define_fn!();
1178//^^^^^^^^^^
1179fn bar() {
1180   $0foo();
1181}
1182"#,
1183        );
1184    }
1185
1186    #[test]
1187    fn goto_definition_works_for_macro_inside_pattern() {
1188        check(
1189            r#"
1190//- /lib.rs
1191macro_rules! foo {() => {0}}
1192           //^^^
1193
1194fn bar() {
1195    match (0,1) {
1196        ($0foo!(), _) => {}
1197    }
1198}
1199"#,
1200        );
1201    }
1202
1203    #[test]
1204    fn goto_definition_works_for_macro_inside_match_arm_lhs() {
1205        check(
1206            r#"
1207//- /lib.rs
1208macro_rules! foo {() => {0}}
1209           //^^^
1210fn bar() {
1211    match 0 {
1212        $0foo!() => {}
1213    }
1214}
1215"#,
1216        );
1217    }
1218
1219    #[test]
1220    fn goto_definition_works_for_consts_inside_range_pattern() {
1221        check(
1222            r#"
1223//- /lib.rs
1224const A: u32 = 0;
1225    //^
1226
1227fn bar(v: u32) {
1228    match v {
1229        0..=$0A => {}
1230        _ => {}
1231    }
1232}
1233"#,
1234        );
1235    }
1236
1237    #[test]
1238    fn goto_def_for_use_alias() {
1239        check(
1240            r#"
1241//- /lib.rs crate:main deps:foo
1242use foo as bar$0;
1243
1244//- /foo/lib.rs crate:foo
1245// empty
1246//^file
1247"#,
1248        );
1249    }
1250
1251    #[test]
1252    fn goto_def_for_use_alias_foo_macro() {
1253        check(
1254            r#"
1255//- /lib.rs crate:main deps:foo
1256use foo::foo as bar$0;
1257
1258//- /foo/lib.rs crate:foo
1259#[macro_export]
1260macro_rules! foo { () => { () } }
1261           //^^^
1262"#,
1263        );
1264    }
1265
1266    #[test]
1267    fn goto_def_for_methods() {
1268        check(
1269            r#"
1270struct Foo;
1271impl Foo {
1272    fn frobnicate(&self) { }
1273     //^^^^^^^^^^
1274}
1275
1276fn bar(foo: &Foo) {
1277    foo.frobnicate$0();
1278}
1279"#,
1280        );
1281    }
1282
1283    #[test]
1284    fn goto_def_for_fields() {
1285        check(
1286            r#"
1287struct Foo {
1288    spam: u32,
1289} //^^^^
1290
1291fn bar(foo: &Foo) {
1292    foo.spam$0;
1293}
1294"#,
1295        );
1296    }
1297
1298    #[test]
1299    fn goto_def_for_record_fields() {
1300        check(
1301            r#"
1302//- /lib.rs
1303struct Foo {
1304    spam: u32,
1305} //^^^^
1306
1307fn bar() -> Foo {
1308    Foo {
1309        spam$0: 0,
1310    }
1311}
1312"#,
1313        );
1314    }
1315
1316    #[test]
1317    fn goto_def_for_record_pat_fields() {
1318        check(
1319            r#"
1320//- /lib.rs
1321struct Foo {
1322    spam: u32,
1323} //^^^^
1324
1325fn bar(foo: Foo) -> Foo {
1326    let Foo { spam$0: _, } = foo
1327}
1328"#,
1329        );
1330    }
1331
1332    #[test]
1333    fn goto_def_for_record_fields_macros() {
1334        check(
1335            r"
1336macro_rules! m { () => { 92 };}
1337struct Foo { spam: u32 }
1338           //^^^^
1339
1340fn bar() -> Foo {
1341    Foo { spam$0: m!() }
1342}
1343",
1344        );
1345    }
1346
1347    #[test]
1348    fn goto_for_tuple_fields() {
1349        check(
1350            r#"
1351struct Foo(u32);
1352         //^^^
1353
1354fn bar() {
1355    let foo = Foo(0);
1356    foo.$00;
1357}
1358"#,
1359        );
1360    }
1361
1362    #[test]
1363    fn goto_def_for_ufcs_inherent_methods() {
1364        check(
1365            r#"
1366struct Foo;
1367impl Foo {
1368    fn frobnicate() { }
1369}    //^^^^^^^^^^
1370
1371fn bar(foo: &Foo) {
1372    Foo::frobnicate$0();
1373}
1374"#,
1375        );
1376    }
1377
1378    #[test]
1379    fn goto_def_for_ufcs_trait_methods_through_traits() {
1380        check(
1381            r#"
1382trait Foo {
1383    fn frobnicate();
1384}    //^^^^^^^^^^
1385
1386fn bar() {
1387    Foo::frobnicate$0();
1388}
1389"#,
1390        );
1391    }
1392
1393    #[test]
1394    fn goto_def_for_ufcs_trait_methods_through_self() {
1395        check(
1396            r#"
1397struct Foo;
1398trait Trait {
1399    fn frobnicate();
1400}    //^^^^^^^^^^
1401impl Trait for Foo {}
1402
1403fn bar() {
1404    Foo::frobnicate$0();
1405}
1406"#,
1407        );
1408    }
1409
1410    #[test]
1411    fn goto_definition_on_self() {
1412        check(
1413            r#"
1414struct Foo;
1415impl Foo {
1416   //^^^
1417    pub fn new() -> Self {
1418        Self$0 {}
1419    }
1420}
1421"#,
1422        );
1423        check(
1424            r#"
1425struct Foo;
1426impl Foo {
1427   //^^^
1428    pub fn new() -> Self$0 {
1429        Self {}
1430    }
1431}
1432"#,
1433        );
1434
1435        check(
1436            r#"
1437enum Foo { A }
1438impl Foo {
1439   //^^^
1440    pub fn new() -> Self$0 {
1441        Foo::A
1442    }
1443}
1444"#,
1445        );
1446
1447        check(
1448            r#"
1449enum Foo { A }
1450impl Foo {
1451   //^^^
1452    pub fn thing(a: &Self$0) {
1453    }
1454}
1455"#,
1456        );
1457    }
1458
1459    #[test]
1460    fn goto_definition_on_self_in_trait_impl() {
1461        check(
1462            r#"
1463struct Foo;
1464trait Make {
1465    fn new() -> Self;
1466}
1467impl Make for Foo {
1468            //^^^
1469    fn new() -> Self {
1470        Self$0 {}
1471    }
1472}
1473"#,
1474        );
1475
1476        check(
1477            r#"
1478struct Foo;
1479trait Make {
1480    fn new() -> Self;
1481}
1482impl Make for Foo {
1483            //^^^
1484    fn new() -> Self$0 {
1485        Self {}
1486    }
1487}
1488"#,
1489        );
1490    }
1491
1492    #[test]
1493    fn goto_def_when_used_on_definition_name_itself() {
1494        check(
1495            r#"
1496struct Foo$0 { value: u32 }
1497     //^^^
1498            "#,
1499        );
1500
1501        check(
1502            r#"
1503struct Foo {
1504    field$0: string,
1505} //^^^^^
1506"#,
1507        );
1508
1509        check(
1510            r#"
1511fn foo_test$0() { }
1512 //^^^^^^^^
1513"#,
1514        );
1515
1516        check(
1517            r#"
1518enum Foo$0 { Variant }
1519   //^^^
1520"#,
1521        );
1522
1523        check(
1524            r#"
1525enum Foo {
1526    Variant1,
1527    Variant2$0,
1528  //^^^^^^^^
1529    Variant3,
1530}
1531"#,
1532        );
1533
1534        check(
1535            r#"
1536static INNER$0: &str = "";
1537     //^^^^^
1538"#,
1539        );
1540
1541        check(
1542            r#"
1543const INNER$0: &str = "";
1544    //^^^^^
1545"#,
1546        );
1547
1548        check(
1549            r#"
1550type Thing$0 = Option<()>;
1551   //^^^^^
1552"#,
1553        );
1554
1555        check(
1556            r#"
1557trait Foo$0 { }
1558    //^^^
1559"#,
1560        );
1561
1562        check(
1563            r#"
1564trait Foo$0 = ;
1565    //^^^
1566"#,
1567        );
1568
1569        check(
1570            r#"
1571mod bar$0 { }
1572  //^^^
1573"#,
1574        );
1575    }
1576
1577    #[test]
1578    fn goto_from_macro() {
1579        check(
1580            r#"
1581macro_rules! id {
1582    ($($tt:tt)*) => { $($tt)* }
1583}
1584fn foo() {}
1585 //^^^
1586id! {
1587    fn bar() {
1588        fo$0o();
1589    }
1590}
1591mod confuse_index { fn foo(); }
1592"#,
1593        );
1594    }
1595
1596    #[test]
1597    fn goto_through_format() {
1598        check(
1599            r#"
1600//- minicore: fmt
1601#[macro_export]
1602macro_rules! format {
1603    ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
1604}
1605pub mod __export {
1606    pub use core::format_args;
1607    fn foo() {} // for index confusion
1608}
1609fn foo() -> i8 {}
1610 //^^^
1611fn test() {
1612    format!("{}", fo$0o())
1613}
1614"#,
1615        );
1616    }
1617
1618    #[test]
1619    fn goto_through_included_file() {
1620        check(
1621            r#"
1622//- /main.rs
1623#[rustc_builtin_macro]
1624macro_rules! include {}
1625
1626include!("foo.rs");
1627
1628fn f() {
1629    foo$0();
1630}
1631
1632mod confuse_index {
1633    pub fn foo() {}
1634}
1635
1636//- /foo.rs
1637fn foo() {}
1638 //^^^
1639        "#,
1640        );
1641    }
1642
1643    #[test]
1644    fn goto_through_included_file_struct_with_doc_comment() {
1645        check(
1646            r#"
1647//- /main.rs
1648#[rustc_builtin_macro]
1649macro_rules! include {}
1650
1651include!("foo.rs");
1652
1653fn f() {
1654    let x = Foo$0;
1655}
1656
1657mod confuse_index {
1658    pub struct Foo;
1659}
1660
1661//- /foo.rs
1662/// This is a doc comment
1663pub struct Foo;
1664         //^^^
1665        "#,
1666        );
1667    }
1668
1669    #[test]
1670    fn goto_for_type_param() {
1671        check(
1672            r#"
1673struct Foo<T: Clone> { t: $0T }
1674         //^
1675"#,
1676        );
1677    }
1678
1679    #[test]
1680    fn goto_within_macro() {
1681        check(
1682            r#"
1683macro_rules! id {
1684    ($($tt:tt)*) => ($($tt)*)
1685}
1686
1687fn foo() {
1688    let x = 1;
1689      //^
1690    id!({
1691        let y = $0x;
1692        let z = y;
1693    });
1694}
1695"#,
1696        );
1697
1698        check(
1699            r#"
1700macro_rules! id {
1701    ($($tt:tt)*) => ($($tt)*)
1702}
1703
1704fn foo() {
1705    let x = 1;
1706    id!({
1707        let y = x;
1708          //^
1709        let z = $0y;
1710    });
1711}
1712"#,
1713        );
1714    }
1715
1716    #[test]
1717    fn goto_def_in_local_fn() {
1718        check(
1719            r#"
1720fn main() {
1721    fn foo() {
1722        let x = 92;
1723          //^
1724        $0x;
1725    }
1726}
1727"#,
1728        );
1729    }
1730
1731    #[test]
1732    fn goto_def_in_local_macro() {
1733        check(
1734            r#"
1735fn bar() {
1736    macro_rules! foo { () => { () } }
1737               //^^^
1738    $0foo!();
1739}
1740"#,
1741        );
1742    }
1743
1744    #[test]
1745    fn goto_def_for_field_init_shorthand() {
1746        check(
1747            r#"
1748struct Foo { x: i32 }
1749           //^
1750fn main() {
1751    let x = 92;
1752      //^
1753    Foo { x$0 };
1754}
1755"#,
1756        )
1757    }
1758
1759    #[test]
1760    fn goto_def_for_enum_variant_field() {
1761        check(
1762            r#"
1763enum Foo {
1764    Bar { x: i32 }
1765        //^
1766}
1767fn baz(foo: Foo) {
1768    match foo {
1769        Foo::Bar { x$0 } => x
1770                 //^
1771    };
1772}
1773"#,
1774        );
1775    }
1776
1777    #[test]
1778    fn goto_def_for_enum_variant_self_pattern_const() {
1779        check(
1780            r#"
1781enum Foo { Bar }
1782         //^^^
1783impl Foo {
1784    fn baz(self) {
1785        match self { Self::Bar$0 => {} }
1786    }
1787}
1788"#,
1789        );
1790    }
1791
1792    #[test]
1793    fn goto_def_for_enum_variant_self_pattern_record() {
1794        check(
1795            r#"
1796enum Foo { Bar { val: i32 } }
1797         //^^^
1798impl Foo {
1799    fn baz(self) -> i32 {
1800        match self { Self::Bar$0 { val } => {} }
1801    }
1802}
1803"#,
1804        );
1805    }
1806
1807    #[test]
1808    fn goto_def_for_enum_variant_self_expr_const() {
1809        check(
1810            r#"
1811enum Foo { Bar }
1812         //^^^
1813impl Foo {
1814    fn baz(self) { Self::Bar$0; }
1815}
1816"#,
1817        );
1818    }
1819
1820    #[test]
1821    fn goto_def_for_enum_variant_self_expr_record() {
1822        check(
1823            r#"
1824enum Foo { Bar { val: i32 } }
1825         //^^^
1826impl Foo {
1827    fn baz(self) { Self::Bar$0 {val: 4}; }
1828}
1829"#,
1830        );
1831    }
1832
1833    #[test]
1834    fn goto_def_for_type_alias_generic_parameter() {
1835        check(
1836            r#"
1837type Alias<T> = T$0;
1838         //^
1839"#,
1840        )
1841    }
1842
1843    #[test]
1844    fn goto_def_for_macro_container() {
1845        check(
1846            r#"
1847//- /lib.rs crate:main deps:foo
1848foo::module$0::mac!();
1849
1850//- /foo/lib.rs crate:foo
1851pub mod module {
1852      //^^^^^^
1853    #[macro_export]
1854    macro_rules! _mac { () => { () } }
1855    pub use crate::_mac as mac;
1856}
1857"#,
1858        );
1859    }
1860
1861    #[test]
1862    fn goto_def_for_assoc_ty_in_path() {
1863        check(
1864            r#"
1865trait Iterator {
1866    type Item;
1867       //^^^^
1868}
1869
1870fn f() -> impl Iterator<Item$0 = u8> {}
1871"#,
1872        );
1873    }
1874
1875    #[test]
1876    fn goto_def_for_super_assoc_ty_in_path() {
1877        check(
1878            r#"
1879trait Super {
1880    type Item;
1881       //^^^^
1882}
1883
1884trait Sub: Super {}
1885
1886fn f() -> impl Sub<Item$0 = u8> {}
1887"#,
1888        );
1889    }
1890
1891    #[test]
1892    fn goto_def_for_module_declaration_in_path_if_types_and_values_same_name() {
1893        check(
1894            r#"
1895mod bar {
1896    pub struct Foo {}
1897             //^^^
1898    pub fn Foo() {}
1899}
1900
1901fn baz() {
1902    let _foo_enum: bar::Foo$0 = bar::Foo {};
1903}
1904        "#,
1905        )
1906    }
1907
1908    #[test]
1909    fn unknown_assoc_ty() {
1910        check_unresolved(
1911            r#"
1912trait Iterator { type Item; }
1913fn f() -> impl Iterator<Invalid$0 = u8> {}
1914"#,
1915        )
1916    }
1917
1918    #[test]
1919    fn goto_def_for_assoc_ty_in_path_multiple() {
1920        check(
1921            r#"
1922trait Iterator {
1923    type A;
1924       //^
1925    type B;
1926}
1927
1928fn f() -> impl Iterator<A$0 = u8, B = ()> {}
1929"#,
1930        );
1931        check(
1932            r#"
1933trait Iterator {
1934    type A;
1935    type B;
1936       //^
1937}
1938
1939fn f() -> impl Iterator<A = u8, B$0 = ()> {}
1940"#,
1941        );
1942    }
1943
1944    #[test]
1945    fn goto_def_for_assoc_ty_ufcs() {
1946        check(
1947            r#"
1948trait Iterator {
1949    type Item;
1950       //^^^^
1951}
1952
1953fn g() -> <() as Iterator<Item$0 = ()>>::Item {}
1954"#,
1955        );
1956    }
1957
1958    #[test]
1959    fn goto_def_for_assoc_ty_ufcs_multiple() {
1960        check(
1961            r#"
1962trait Iterator {
1963    type A;
1964       //^
1965    type B;
1966}
1967
1968fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {}
1969"#,
1970        );
1971        check(
1972            r#"
1973trait Iterator {
1974    type A;
1975    type B;
1976       //^
1977}
1978
1979fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {}
1980"#,
1981        );
1982    }
1983
1984    #[test]
1985    fn goto_self_param_ty_specified() {
1986        check(
1987            r#"
1988struct Foo {}
1989
1990impl Foo {
1991    fn bar(self: &Foo) {
1992         //^^^^
1993        let foo = sel$0f;
1994    }
1995}"#,
1996        )
1997    }
1998
1999    #[test]
2000    fn goto_self_param_on_decl() {
2001        check(
2002            r#"
2003struct Foo {}
2004
2005impl Foo {
2006    fn bar(&self$0) {
2007          //^^^^
2008    }
2009}"#,
2010        )
2011    }
2012
2013    #[test]
2014    fn goto_lifetime_param_on_decl() {
2015        check(
2016            r#"
2017fn foo<'foobar$0>(_: &'foobar ()) {
2018     //^^^^^^^
2019}"#,
2020        )
2021    }
2022
2023    #[test]
2024    fn goto_lifetime_param_decl() {
2025        check(
2026            r#"
2027fn foo<'foobar>(_: &'foobar$0 ()) {
2028     //^^^^^^^
2029}"#,
2030        )
2031    }
2032
2033    #[test]
2034    fn goto_lifetime_param_decl_nested() {
2035        check(
2036            r#"
2037fn foo<'foobar>(_: &'foobar ()) {
2038    fn foo<'foobar>(_: &'foobar$0 ()) {}
2039         //^^^^^^^
2040}"#,
2041        )
2042    }
2043
2044    #[test]
2045    fn goto_lifetime_hrtb() {
2046        // FIXME: requires the HIR to somehow track these hrtb lifetimes
2047        check_unresolved(
2048            r#"
2049trait Foo<T> {}
2050fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {}
2051                    //^^
2052"#,
2053        );
2054        check_unresolved(
2055            r#"
2056trait Foo<T> {}
2057fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}
2058                    //^^
2059"#,
2060        );
2061    }
2062
2063    #[test]
2064    fn goto_lifetime_hrtb_for_type() {
2065        // FIXME: requires ForTypes to be implemented
2066        check_unresolved(
2067            r#"trait Foo<T> {}
2068fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {}
2069                       //^^
2070"#,
2071        );
2072    }
2073
2074    #[test]
2075    fn goto_label() {
2076        check(
2077            r#"
2078fn foo<'foo>(_: &'foo ()) {
2079    'foo: {
2080  //^^^^
2081        'bar: loop {
2082            break 'foo$0;
2083        }
2084    }
2085}"#,
2086        )
2087    }
2088
2089    #[test]
2090    fn goto_def_for_intra_doc_link_same_file() {
2091        check(
2092            r#"
2093/// Blah, [`bar`](bar) .. [`foo`](foo$0) has [`bar`](bar)
2094pub fn bar() { }
2095
2096/// You might want to see [`std::fs::read()`] too.
2097pub fn foo() { }
2098     //^^^
2099
2100}"#,
2101        )
2102    }
2103
2104    #[test]
2105    fn goto_def_for_intra_doc_link_outer_same_file() {
2106        check(
2107            r#"
2108/// [`S$0`]
2109mod m {
2110    //! [`super::S`]
2111}
2112struct S;
2113     //^
2114            "#,
2115        );
2116
2117        check(
2118            r#"
2119/// [`S$0`]
2120mod m {}
2121struct S;
2122     //^
2123            "#,
2124        );
2125
2126        check(
2127            r#"
2128/// [`S$0`]
2129fn f() {
2130    //! [`S`]
2131}
2132struct S;
2133     //^
2134            "#,
2135        );
2136    }
2137
2138    #[test]
2139    fn goto_def_for_intra_doc_link_inner_same_file() {
2140        check(
2141            r#"
2142/// [`S`]
2143mod m {
2144    //! [`super::S$0`]
2145}
2146struct S;
2147     //^
2148            "#,
2149        );
2150
2151        check(
2152            r#"
2153mod m {
2154    //! [`super::S$0`]
2155}
2156struct S;
2157     //^
2158            "#,
2159        );
2160
2161        check(
2162            r#"
2163fn f() {
2164    //! [`S$0`]
2165}
2166struct S;
2167     //^
2168            "#,
2169        );
2170    }
2171
2172    #[test]
2173    fn goto_def_for_intra_doc_link_inner() {
2174        check(
2175            r#"
2176//- /main.rs
2177mod m;
2178struct S;
2179     //^
2180
2181//- /m.rs
2182//! [`super::S$0`]
2183"#,
2184        )
2185    }
2186
2187    #[test]
2188    fn goto_incomplete_field() {
2189        check(
2190            r#"
2191struct A { a: u32 }
2192         //^
2193fn foo() { A { a$0: }; }
2194"#,
2195        )
2196    }
2197
2198    #[test]
2199    fn goto_proc_macro() {
2200        check(
2201            r#"
2202//- /main.rs crate:main deps:mac
2203use mac::fn_macro;
2204
2205fn_macro$0!();
2206
2207//- /mac.rs crate:mac
2208#![crate_type="proc-macro"]
2209#[proc_macro]
2210fn fn_macro() {}
2211 //^^^^^^^^
2212            "#,
2213        )
2214    }
2215
2216    #[test]
2217    fn goto_intra_doc_links() {
2218        check(
2219            r#"
2220
2221pub mod theitem {
2222    /// This is the item. Cool!
2223    pub struct TheItem;
2224             //^^^^^^^
2225}
2226
2227/// Gives you a [`TheItem$0`].
2228///
2229/// [`TheItem`]: theitem::TheItem
2230pub fn gimme() -> theitem::TheItem {
2231    theitem::TheItem
2232}
2233"#,
2234        );
2235    }
2236
2237    #[test]
2238    fn goto_ident_from_pat_macro() {
2239        check(
2240            r#"
2241macro_rules! pat {
2242    ($name:ident) => { Enum::Variant1($name) }
2243}
2244
2245enum Enum {
2246    Variant1(u8),
2247    Variant2,
2248}
2249
2250fn f(e: Enum) {
2251    match e {
2252        pat!(bind) => {
2253           //^^^^
2254            bind$0
2255        }
2256        Enum::Variant2 => {}
2257    }
2258}
2259"#,
2260        );
2261    }
2262
2263    #[test]
2264    fn goto_include() {
2265        check(
2266            r#"
2267//- /main.rs
2268
2269#[rustc_builtin_macro]
2270macro_rules! include_str {}
2271
2272fn main() {
2273    let str = include_str!("foo.txt$0");
2274}
2275//- /foo.txt
2276// empty
2277//^file
2278"#,
2279        );
2280    }
2281
2282    #[test]
2283    fn goto_include_has_eager_input() {
2284        check(
2285            r#"
2286//- /main.rs
2287#[rustc_builtin_macro]
2288macro_rules! include_str {}
2289#[rustc_builtin_macro]
2290macro_rules! concat {}
2291
2292fn main() {
2293    let str = include_str!(concat!("foo", ".tx$0t"));
2294}
2295//- /foo.txt
2296// empty
2297//^file
2298"#,
2299        );
2300    }
2301
2302    // macros in this position are not yet supported
2303    #[test]
2304    // FIXME
2305    #[should_panic]
2306    fn goto_doc_include_str() {
2307        check(
2308            r#"
2309//- /main.rs
2310#[rustc_builtin_macro]
2311macro_rules! include_str {}
2312
2313#[doc = include_str!("docs.md$0")]
2314struct Item;
2315
2316//- /docs.md
2317// docs
2318//^file
2319"#,
2320        );
2321    }
2322
2323    #[test]
2324    fn goto_shadow_include() {
2325        check(
2326            r#"
2327//- /main.rs
2328macro_rules! include {
2329    ("included.rs") => {}
2330}
2331
2332include!("included.rs$0");
2333
2334//- /included.rs
2335// empty
2336"#,
2337        );
2338    }
2339
2340    mod goto_impl_of_trait_fn {
2341        use super::check;
2342        #[test]
2343        fn cursor_on_impl() {
2344            check(
2345                r#"
2346trait Twait {
2347    fn a();
2348}
2349
2350struct Stwuct;
2351
2352impl Twait for Stwuct {
2353    fn a$0();
2354     //^
2355}
2356        "#,
2357            );
2358        }
2359        #[test]
2360        fn method_call() {
2361            check(
2362                r#"
2363trait Twait {
2364    fn a(&self);
2365}
2366
2367struct Stwuct;
2368
2369impl Twait for Stwuct {
2370    fn a(&self){};
2371     //^
2372}
2373fn f() {
2374    let s = Stwuct;
2375    s.a$0();
2376}
2377        "#,
2378            );
2379        }
2380        #[test]
2381        fn method_call_inside_block() {
2382            check(
2383                r#"
2384trait Twait {
2385    fn a(&self);
2386}
2387
2388fn outer() {
2389    struct Stwuct;
2390
2391    impl Twait for Stwuct {
2392        fn a(&self){}
2393         //^
2394    }
2395    fn f() {
2396        let s = Stwuct;
2397        s.a$0();
2398    }
2399}
2400        "#,
2401            );
2402        }
2403        #[test]
2404        fn path_call() {
2405            check(
2406                r#"
2407trait Twait {
2408    fn a(&self);
2409}
2410
2411struct Stwuct;
2412
2413impl Twait for Stwuct {
2414    fn a(&self){};
2415     //^
2416}
2417fn f() {
2418    let s = Stwuct;
2419    Stwuct::a$0(&s);
2420}
2421        "#,
2422            );
2423        }
2424        #[test]
2425        fn where_clause_can_work() {
2426            check(
2427                r#"
2428trait G {
2429    fn g(&self);
2430}
2431trait Bound{}
2432trait EA{}
2433struct Gen<T>(T);
2434impl <T:EA> G for Gen<T> {
2435    fn g(&self) {
2436    }
2437}
2438impl <T> G for Gen<T>
2439where T : Bound
2440{
2441    fn g(&self){
2442     //^
2443    }
2444}
2445struct A;
2446impl Bound for A{}
2447fn f() {
2448    let g = Gen::<A>(A);
2449    g.g$0();
2450}
2451                "#,
2452            );
2453        }
2454        #[test]
2455        fn wc_case_is_ok() {
2456            check(
2457                r#"
2458trait G {
2459    fn g(&self);
2460}
2461trait BParent{}
2462trait Bound: BParent{}
2463struct Gen<T>(T);
2464impl <T> G for Gen<T>
2465where T : Bound
2466{
2467    fn g(&self){
2468     //^
2469    }
2470}
2471struct A;
2472impl Bound for A{}
2473fn f() {
2474    let g = Gen::<A>(A);
2475    g.g$0();
2476}
2477"#,
2478            );
2479        }
2480
2481        #[test]
2482        fn method_call_defaulted() {
2483            check(
2484                r#"
2485trait Twait {
2486    fn a(&self) {}
2487     //^
2488}
2489
2490struct Stwuct;
2491
2492impl Twait for Stwuct {
2493}
2494fn f() {
2495    let s = Stwuct;
2496    s.a$0();
2497}
2498        "#,
2499            );
2500        }
2501
2502        #[test]
2503        fn method_call_on_generic() {
2504            check(
2505                r#"
2506trait Twait {
2507    fn a(&self) {}
2508     //^
2509}
2510
2511fn f<T: Twait>(s: T) {
2512    s.a$0();
2513}
2514        "#,
2515            );
2516        }
2517    }
2518
2519    #[test]
2520    fn goto_def_of_trait_impl_const() {
2521        check(
2522            r#"
2523trait Twait {
2524    const NOMS: bool;
2525       // ^^^^
2526}
2527
2528struct Stwuct;
2529
2530impl Twait for Stwuct {
2531    const NOMS$0: bool = true;
2532}
2533"#,
2534        );
2535    }
2536
2537    #[test]
2538    fn goto_def_of_trait_impl_type_alias() {
2539        check(
2540            r#"
2541trait Twait {
2542    type IsBad;
2543      // ^^^^^
2544}
2545
2546struct Stwuct;
2547
2548impl Twait for Stwuct {
2549    type IsBad$0 = !;
2550}
2551"#,
2552        );
2553    }
2554
2555    #[test]
2556    fn goto_def_derive_input() {
2557        check(
2558            r#"
2559        //- minicore:derive
2560        #[rustc_builtin_macro]
2561        pub macro Copy {}
2562               // ^^^^
2563        #[derive(Copy$0)]
2564        struct Foo;
2565                    "#,
2566        );
2567        check(
2568            r#"
2569//- minicore:derive
2570#[rustc_builtin_macro]
2571pub macro Copy {}
2572       // ^^^^
2573#[cfg_attr(feature = "false", derive)]
2574#[derive(Copy$0)]
2575struct Foo;
2576            "#,
2577        );
2578        check(
2579            r#"
2580//- minicore:derive
2581mod foo {
2582    #[rustc_builtin_macro]
2583    pub macro Copy {}
2584           // ^^^^
2585}
2586#[derive(foo::Copy$0)]
2587struct Foo;
2588            "#,
2589        );
2590        check(
2591            r#"
2592//- minicore:derive
2593mod foo {
2594 // ^^^
2595    #[rustc_builtin_macro]
2596    pub macro Copy {}
2597}
2598#[derive(foo$0::Copy)]
2599struct Foo;
2600            "#,
2601        );
2602    }
2603
2604    #[test]
2605    fn goto_def_in_macro_multi() {
2606        check(
2607            r#"
2608struct Foo {
2609    foo: ()
2610  //^^^
2611}
2612macro_rules! foo {
2613    ($ident:ident) => {
2614        fn $ident(Foo { $ident }: Foo) {}
2615    }
2616}
2617  foo!(foo$0);
2618     //^^^
2619     //^^^
2620"#,
2621        );
2622        check(
2623            r#"
2624fn bar() {}
2625 //^^^
2626struct bar;
2627     //^^^
2628macro_rules! foo {
2629    ($ident:ident) => {
2630        fn foo() {
2631            let _: $ident = $ident;
2632        }
2633    }
2634}
2635
2636foo!(bar$0);
2637"#,
2638        );
2639    }
2640
2641    #[test]
2642    fn goto_await_poll() {
2643        check(
2644            r#"
2645//- minicore: future
2646
2647struct MyFut;
2648
2649impl core::future::Future for MyFut {
2650    type Output = ();
2651
2652    fn poll(
2653     //^^^^
2654        self: std::pin::Pin<&mut Self>,
2655        cx: &mut std::task::Context<'_>
2656    ) -> std::task::Poll<Self::Output>
2657    {
2658        ()
2659    }
2660}
2661
2662fn f() {
2663    MyFut.await$0;
2664}
2665"#,
2666        );
2667    }
2668
2669    #[test]
2670    fn goto_await_into_future_poll() {
2671        check(
2672            r#"
2673//- minicore: future
2674
2675struct Futurable;
2676
2677impl core::future::IntoFuture for Futurable {
2678    type IntoFuture = MyFut;
2679}
2680
2681struct MyFut;
2682
2683impl core::future::Future for MyFut {
2684    type Output = ();
2685
2686    fn poll(
2687     //^^^^
2688        self: std::pin::Pin<&mut Self>,
2689        cx: &mut std::task::Context<'_>
2690    ) -> std::task::Poll<Self::Output>
2691    {
2692        ()
2693    }
2694}
2695
2696fn f() {
2697    Futurable.await$0;
2698}
2699"#,
2700        );
2701    }
2702
2703    #[test]
2704    fn goto_try_op() {
2705        check(
2706            r#"
2707//- minicore: try
2708
2709struct Struct;
2710
2711impl core::ops::Try for Struct {
2712    fn branch(
2713     //^^^^^^
2714        self
2715    ) {}
2716}
2717
2718fn f() {
2719    Struct?$0;
2720}
2721"#,
2722        );
2723    }
2724
2725    #[test]
2726    fn goto_index_op() {
2727        check(
2728            r#"
2729//- minicore: index
2730
2731struct Struct;
2732
2733impl core::ops::Index<usize> for Struct {
2734    fn index(
2735     //^^^^^
2736        self
2737    ) {}
2738}
2739
2740fn f() {
2741    Struct[0]$0;
2742}
2743"#,
2744        );
2745    }
2746
2747    #[test]
2748    fn goto_index_mut_op() {
2749        check(
2750            r#"
2751//- minicore: index
2752
2753struct Foo;
2754struct Bar;
2755
2756impl core::ops::Index<usize> for Foo {
2757    type Output = Bar;
2758
2759    fn index(&self, index: usize) -> &Self::Output {}
2760}
2761
2762impl core::ops::IndexMut<usize> for Foo {
2763    fn index_mut(&mut self, index: usize) -> &mut Self::Output {}
2764     //^^^^^^^^^
2765}
2766
2767fn f() {
2768    let mut foo = Foo;
2769    foo[0]$0 = Bar;
2770}
2771"#,
2772        );
2773    }
2774
2775    #[test]
2776    fn goto_prefix_op() {
2777        check(
2778            r#"
2779//- minicore: deref
2780
2781struct Struct;
2782
2783impl core::ops::Deref for Struct {
2784    fn deref(
2785     //^^^^^
2786        self
2787    ) {}
2788}
2789
2790fn f() {
2791    $0*Struct;
2792}
2793"#,
2794        );
2795    }
2796
2797    #[test]
2798    fn goto_deref_mut() {
2799        check(
2800            r#"
2801//- minicore: deref, deref_mut
2802
2803struct Foo;
2804struct Bar;
2805
2806impl core::ops::Deref for Foo {
2807    type Target = Bar;
2808    fn deref(&self) -> &Self::Target {}
2809}
2810
2811impl core::ops::DerefMut for Foo {
2812    fn deref_mut(&mut self) -> &mut Self::Target {}
2813     //^^^^^^^^^
2814}
2815
2816fn f() {
2817    let a = Foo;
2818    $0*a = Bar;
2819}
2820"#,
2821        );
2822    }
2823
2824    #[test]
2825    fn goto_bin_op() {
2826        check(
2827            r#"
2828//- minicore: add
2829
2830struct Struct;
2831
2832impl core::ops::Add for Struct {
2833    fn add(
2834     //^^^
2835        self
2836    ) {}
2837}
2838
2839fn f() {
2840    Struct +$0 Struct;
2841}
2842"#,
2843        );
2844    }
2845
2846    #[test]
2847    fn goto_bin_op_multiple_impl() {
2848        check(
2849            r#"
2850//- minicore: add
2851struct S;
2852impl core::ops::Add for S {
2853    fn add(
2854     //^^^
2855    ) {}
2856}
2857impl core::ops::Add<usize> for S {
2858    fn add(
2859    ) {}
2860}
2861
2862fn f() {
2863    S +$0 S
2864}
2865"#,
2866        );
2867
2868        check(
2869            r#"
2870//- minicore: add
2871struct S;
2872impl core::ops::Add for S {
2873    fn add(
2874    ) {}
2875}
2876impl core::ops::Add<usize> for S {
2877    fn add(
2878     //^^^
2879    ) {}
2880}
2881
2882fn f() {
2883    S +$0 0usize
2884}
2885"#,
2886        );
2887    }
2888
2889    #[test]
2890    fn path_call_multiple_trait_impl() {
2891        check(
2892            r#"
2893trait Trait<T> {
2894    fn f(_: T);
2895}
2896impl Trait<i32> for usize {
2897    fn f(_: i32) {}
2898     //^
2899}
2900impl Trait<i64> for usize {
2901    fn f(_: i64) {}
2902}
2903fn main() {
2904    usize::f$0(0i32);
2905}
2906"#,
2907        );
2908
2909        check(
2910            r#"
2911trait Trait<T> {
2912    fn f(_: T);
2913}
2914impl Trait<i32> for usize {
2915    fn f(_: i32) {}
2916}
2917impl Trait<i64> for usize {
2918    fn f(_: i64) {}
2919     //^
2920}
2921fn main() {
2922    usize::f$0(0i64);
2923}
2924"#,
2925        )
2926    }
2927
2928    #[test]
2929    fn query_impls_in_nearest_block() {
2930        check(
2931            r#"
2932struct S1;
2933impl S1 {
2934    fn e() -> () {}
2935}
2936fn f1() {
2937    struct S1;
2938    impl S1 {
2939        fn e() -> () {}
2940         //^
2941    }
2942    fn f2() {
2943        fn f3() {
2944            S1::e$0();
2945        }
2946    }
2947}
2948"#,
2949        );
2950
2951        check(
2952            r#"
2953struct S1;
2954impl S1 {
2955    fn e() -> () {}
2956}
2957fn f1() {
2958    struct S1;
2959    impl S1 {
2960        fn e() -> () {}
2961         //^
2962    }
2963    fn f2() {
2964        struct S2;
2965        S1::e$0();
2966    }
2967}
2968fn f12() {
2969    struct S1;
2970    impl S1 {
2971        fn e() -> () {}
2972    }
2973}
2974"#,
2975        );
2976
2977        check(
2978            r#"
2979struct S1;
2980impl S1 {
2981    fn e() -> () {}
2982     //^
2983}
2984fn f2() {
2985    struct S2;
2986    S1::e$0();
2987}
2988"#,
2989        );
2990    }
2991
2992    #[test]
2993    fn implicit_format_args() {
2994        check(
2995            r#"
2996//- minicore: fmt
2997fn test() {
2998    let a = "world";
2999     // ^
3000    format_args!("hello {a$0}");
3001}
3002"#,
3003        );
3004    }
3005
3006    #[test]
3007    fn goto_macro_def_from_macro_use() {
3008        check(
3009            r#"
3010//- /main.rs crate:main deps:mac
3011#[macro_use(foo$0)]
3012extern crate mac;
3013
3014//- /mac.rs crate:mac
3015#[macro_export]
3016macro_rules! foo {
3017           //^^^
3018    () => {};
3019}
3020            "#,
3021        );
3022
3023        check(
3024            r#"
3025//- /main.rs crate:main deps:mac
3026#[macro_use(foo, bar$0, baz)]
3027extern crate mac;
3028
3029//- /mac.rs crate:mac
3030#[macro_export]
3031macro_rules! foo {
3032    () => {};
3033}
3034
3035#[macro_export]
3036macro_rules! bar {
3037           //^^^
3038    () => {};
3039}
3040
3041#[macro_export]
3042macro_rules! baz {
3043    () => {};
3044}
3045            "#,
3046        );
3047    }
3048
3049    #[test]
3050    fn goto_shadowed_preludes_in_block_module() {
3051        check(
3052            r#"
3053//- /main.rs crate:main edition:2021 deps:core
3054pub struct S;
3055         //^
3056
3057fn main() {
3058    fn f() -> S$0 {
3059        fn inner() {} // forces a block def map
3060        return S;
3061    }
3062}
3063//- /core.rs crate:core
3064pub mod prelude {
3065    pub mod rust_2021 {
3066        pub enum S;
3067    }
3068}
3069        "#,
3070        );
3071    }
3072
3073    #[test]
3074    fn goto_def_on_return_kw() {
3075        check(
3076            r#"
3077macro_rules! N {
3078    ($i:ident, $x:expr, $blk:expr) => {
3079        for $i in 0..$x {
3080            $blk
3081        }
3082    };
3083}
3084
3085fn main() {
3086    fn f() {
3087 // ^^
3088        N!(i, 5, {
3089            println!("{}", i);
3090            return$0;
3091        });
3092
3093        for i in 1..5 {
3094            return;
3095        }
3096       (|| {
3097            return;
3098        })();
3099    }
3100}
3101"#,
3102        )
3103    }
3104
3105    #[test]
3106    fn goto_def_on_return_kw_in_closure() {
3107        check(
3108            r#"
3109macro_rules! N {
3110    ($i:ident, $x:expr, $blk:expr) => {
3111        for $i in 0..$x {
3112            $blk
3113        }
3114    };
3115}
3116
3117fn main() {
3118    fn f() {
3119        N!(i, 5, {
3120            println!("{}", i);
3121            return;
3122        });
3123
3124        for i in 1..5 {
3125            return;
3126        }
3127       (|| {
3128     // ^
3129            return$0;
3130        })();
3131    }
3132}
3133"#,
3134        )
3135    }
3136
3137    #[test]
3138    fn goto_def_on_break_kw() {
3139        check(
3140            r#"
3141fn main() {
3142    for i in 1..5 {
3143 // ^^^
3144        break$0;
3145    }
3146}
3147"#,
3148        )
3149    }
3150
3151    #[test]
3152    fn goto_def_on_continue_kw() {
3153        check(
3154            r#"
3155fn main() {
3156    for i in 1..5 {
3157 // ^^^
3158        continue$0;
3159    }
3160}
3161"#,
3162        )
3163    }
3164
3165    #[test]
3166    fn goto_def_on_break_kw_for_block() {
3167        check(
3168            r#"
3169fn main() {
3170    'a:{
3171 // ^^^
3172        break$0 'a;
3173    }
3174}
3175"#,
3176        )
3177    }
3178
3179    #[test]
3180    fn goto_def_on_break_with_label() {
3181        check(
3182            r#"
3183fn foo() {
3184    'outer: loop {
3185         // ^^^^
3186         'inner: loop {
3187            'innermost: loop {
3188            }
3189            break$0 'outer;
3190        }
3191    }
3192}
3193"#,
3194        );
3195    }
3196
3197    #[test]
3198    fn label_inside_macro() {
3199        check(
3200            r#"
3201macro_rules! m {
3202    ($s:stmt) => { $s };
3203}
3204
3205fn foo() {
3206    'label: loop {
3207 // ^^^^^^
3208        m!(continue 'label$0);
3209    }
3210}
3211"#,
3212        );
3213    }
3214
3215    #[test]
3216    fn goto_def_on_return_in_try() {
3217        check(
3218            r#"
3219fn main() {
3220    fn f() {
3221 // ^^
3222        try {
3223            return$0;
3224        }
3225
3226        return;
3227    }
3228}
3229"#,
3230        )
3231    }
3232
3233    #[test]
3234    fn goto_def_on_break_in_try() {
3235        check(
3236            r#"
3237fn main() {
3238    for i in 1..100 {
3239 // ^^^
3240        let x: Result<(), ()> = try {
3241            break$0;
3242        };
3243    }
3244}
3245"#,
3246        )
3247    }
3248
3249    #[test]
3250    fn goto_def_on_return_in_async_block() {
3251        check(
3252            r#"
3253fn main() {
3254    async {
3255 // ^^^^^
3256        return$0;
3257    }
3258}
3259"#,
3260        )
3261    }
3262
3263    #[test]
3264    fn goto_def_on_for_kw() {
3265        check(
3266            r#"
3267fn main() {
3268    for$0 i in 1..5 {}
3269 // ^^^
3270}
3271"#,
3272        )
3273    }
3274
3275    #[test]
3276    fn goto_def_on_fn_kw() {
3277        check(
3278            r#"
3279fn main() {
3280    fn$0 foo() {}
3281 // ^^
3282}
3283"#,
3284        )
3285    }
3286
3287    #[test]
3288    fn shadow_builtin_macro() {
3289        check(
3290            r#"
3291//- minicore: column
3292//- /a.rs crate:a
3293#[macro_export]
3294macro_rules! column { () => {} }
3295          // ^^^^^^
3296
3297//- /b.rs crate:b deps:a
3298use a::column;
3299fn foo() {
3300    $0column!();
3301}
3302        "#,
3303        );
3304    }
3305
3306    #[test]
3307    fn issue_18138() {
3308        check(
3309            r#"
3310mod foo {
3311    macro_rules! x {
3312        () => {
3313            pub struct Foo;
3314                    // ^^^
3315        };
3316    }
3317    pub(crate) use x as m;
3318}
3319
3320mod bar {
3321    use crate::m;
3322
3323    m!();
3324 // ^^
3325
3326    fn qux() {
3327        Foo$0;
3328    }
3329}
3330
3331mod m {}
3332
3333use foo::m;
3334"#,
3335        );
3336    }
3337
3338    #[test]
3339    fn macro_label_hygiene() {
3340        check(
3341            r#"
3342macro_rules! m {
3343    ($x:stmt) => {
3344        'bar: loop { $x }
3345    };
3346}
3347
3348fn foo() {
3349    'bar: loop {
3350 // ^^^^
3351        m!(continue 'bar$0);
3352    }
3353}
3354"#,
3355        );
3356    }
3357    #[test]
3358    fn into_call_to_from_definition() {
3359        check(
3360            r#"
3361//- minicore: from
3362struct A;
3363
3364struct B;
3365
3366impl From<A> for B {
3367    fn from(value: A) -> Self {
3368     //^^^^
3369        B
3370    }
3371}
3372
3373fn f() {
3374    let a = A;
3375    let b: B = a.into$0();
3376}
3377        "#,
3378        );
3379    }
3380
3381    #[test]
3382    fn into_call_to_from_definition_within_macro() {
3383        check(
3384            r#"
3385//- proc_macros: identity
3386//- minicore: from
3387struct A;
3388
3389struct B;
3390
3391impl From<A> for B {
3392    fn from(value: A) -> Self {
3393     //^^^^
3394        B
3395    }
3396}
3397
3398#[proc_macros::identity]
3399fn f() {
3400    let a = A;
3401    let b: B = a.into$0();
3402}
3403        "#,
3404        );
3405    }
3406
3407    #[test]
3408    fn into_call_to_from_definition_with_trait_bounds() {
3409        check(
3410            r#"
3411//- minicore: from, iterator
3412struct A;
3413
3414impl<T> From<T> for A
3415where
3416    T: IntoIterator<Item = i64>,
3417{
3418    fn from(value: T) -> Self {
3419     //^^^^
3420        A
3421    }
3422}
3423
3424fn f() {
3425    let a: A = [1, 2, 3].into$0();
3426}
3427        "#,
3428        );
3429    }
3430
3431    #[test]
3432    fn goto_into_definition_if_exists() {
3433        check(
3434            r#"
3435//- minicore: from
3436struct A;
3437
3438struct B;
3439
3440impl Into<B> for A {
3441    fn into(self) -> B {
3442     //^^^^
3443        B
3444    }
3445}
3446
3447fn f() {
3448    let a = A;
3449    let b: B = a.into$0();
3450}
3451        "#,
3452        );
3453    }
3454
3455    #[test]
3456    fn try_into_call_to_try_from_definition() {
3457        check(
3458            r#"
3459//- minicore: from
3460struct A;
3461
3462struct B;
3463
3464impl TryFrom<A> for B {
3465    type Error = String;
3466
3467    fn try_from(value: A) -> Result<Self, Self::Error> {
3468     //^^^^^^^^
3469        Ok(B)
3470    }
3471}
3472
3473fn f() {
3474    let a = A;
3475    let b: Result<B, _> = a.try_into$0();
3476}
3477        "#,
3478        );
3479    }
3480
3481    #[test]
3482    fn goto_try_into_definition_if_exists() {
3483        check(
3484            r#"
3485//- minicore: from
3486struct A;
3487
3488struct B;
3489
3490impl TryInto<B> for A {
3491    type Error = String;
3492
3493    fn try_into(self) -> Result<B, Self::Error> {
3494     //^^^^^^^^
3495        Ok(B)
3496    }
3497}
3498
3499fn f() {
3500    let a = A;
3501    let b: Result<B, _> = a.try_into$0();
3502}
3503        "#,
3504        );
3505    }
3506
3507    #[test]
3508    fn parse_call_to_from_str_definition() {
3509        check(
3510            r#"
3511//- minicore: from, str
3512struct A;
3513impl FromStr for A {
3514    type Error = String;
3515    fn from_str(value: &str) -> Result<Self, Self::Error> {
3516     //^^^^^^^^
3517        Ok(A)
3518    }
3519}
3520fn f() {
3521    let a: Result<A, _> = "aaaaaa".parse$0();
3522}
3523        "#,
3524        );
3525    }
3526
3527    #[test]
3528    fn to_string_call_to_display_definition() {
3529        check(
3530            r#"
3531//- minicore:fmt
3532//- /alloc.rs crate:alloc
3533pub mod string {
3534    pub struct String;
3535    pub trait ToString {
3536        fn to_string(&self) -> String;
3537    }
3538
3539    impl<T: core::fmt::Display> ToString for T {
3540        fn to_string(&self) -> String { String }
3541    }
3542}
3543//- /lib.rs crate:lib deps:alloc
3544use alloc::string::ToString;
3545struct A;
3546impl core::fmt::Display for A {
3547    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {}
3548    // ^^^
3549}
3550fn f() {
3551    A.to_string$0();
3552}
3553        "#,
3554        );
3555    }
3556
3557    #[test]
3558    fn use_inside_body() {
3559        check(
3560            r#"
3561fn main() {
3562    mod nice_module {
3563        pub(super) struct NiceStruct;
3564                       // ^^^^^^^^^^
3565    }
3566
3567    use nice_module::NiceStruct$0;
3568
3569    let _ = NiceStruct;
3570}
3571    "#,
3572        );
3573    }
3574
3575    #[test]
3576    fn shadow_builtin_type_by_module() {
3577        check(
3578            r#"
3579mod Foo{
3580pub mod str {
3581     // ^^^
3582    pub fn foo() {}
3583}
3584}
3585
3586fn main() {
3587    use Foo::str;
3588    let s = st$0r::foo();
3589}
3590"#,
3591        );
3592    }
3593
3594    #[test]
3595    fn not_goto_module_because_str_is_builtin_type() {
3596        check(
3597            r#"
3598mod str {
3599pub fn foo() {}
3600}
3601
3602fn main() {
3603    let s = st$0r::f();
3604}
3605"#,
3606        );
3607    }
3608
3609    #[test]
3610    fn struct_shadow_by_module() {
3611        check(
3612            r#"
3613mod foo {
3614    pub mod bar {
3615         // ^^^
3616        pub type baz = usize;
3617    }
3618}
3619struct bar;
3620fn main() {
3621    use foo::bar;
3622    let x: ba$0r::baz = 5;
3623
3624}
3625"#,
3626        );
3627    }
3628
3629    #[test]
3630    fn type_alias_shadow_by_module() {
3631        check(
3632            r#"
3633mod foo {
3634    pub mod bar {
3635         // ^^^
3636        pub fn baz() {}
3637    }
3638}
3639
3640trait Qux {}
3641
3642fn item<bar: Qux>() {
3643    use foo::bar;
3644    ba$0r::baz();
3645}
3646}
3647"#,
3648        );
3649
3650        check(
3651            r#"
3652mod foo {
3653    pub mod bar {
3654         // ^^^
3655        pub fn baz() {}
3656    }
3657}
3658
3659fn item<bar>(x: bar) {
3660    use foo::bar;
3661    let x: bar$0 = x;
3662}
3663"#,
3664        );
3665    }
3666
3667    #[test]
3668    fn trait_shadow_by_module() {
3669        check(
3670            r#"
3671pub mod foo {
3672    pub mod Bar {}
3673         // ^^^
3674}
3675
3676trait Bar {}
3677
3678fn main() {
3679    use foo::Bar;
3680    fn f<Qux: B$0ar>() {}
3681}
3682            "#,
3683        );
3684    }
3685
3686    #[test]
3687    fn const_shadow_by_module() {
3688        check(
3689            r#"
3690pub mod foo {
3691    pub struct u8 {}
3692    pub mod bar {
3693        pub mod u8 {}
3694    }
3695}
3696
3697fn main() {
3698    use foo::u8;
3699    {
3700        use foo::bar::u8;
3701
3702        fn f1<const N: u$08>() {}
3703    }
3704    fn f2<const N: u8>() {}
3705}
3706"#,
3707        );
3708
3709        check(
3710            r#"
3711pub mod foo {
3712    pub struct u8 {}
3713            // ^^
3714    pub mod bar {
3715        pub mod u8 {}
3716    }
3717}
3718
3719fn main() {
3720    use foo::u8;
3721    {
3722        use foo::bar::u8;
3723
3724        fn f1<const N: u8>() {}
3725    }
3726    fn f2<const N: u$08>() {}
3727}
3728"#,
3729        );
3730
3731        check(
3732            r#"
3733pub mod foo {
3734    pub struct buz {}
3735    pub mod bar {
3736        pub mod buz {}
3737             // ^^^
3738    }
3739}
3740
3741fn main() {
3742    use foo::buz;
3743    {
3744        use foo::bar::buz;
3745
3746        fn f1<const N: buz$0>() {}
3747    }
3748}
3749"#,
3750        );
3751    }
3752
3753    #[test]
3754    fn offset_of() {
3755        check(
3756            r#"
3757//- minicore: offset_of
3758struct Foo {
3759    field: i32,
3760 // ^^^^^
3761}
3762
3763fn foo() {
3764    let _ = core::mem::offset_of!(Foo, fiel$0d);
3765}
3766        "#,
3767        );
3768
3769        check(
3770            r#"
3771//- minicore: offset_of
3772struct Bar(Foo);
3773struct Foo {
3774    field: i32,
3775 // ^^^^^
3776}
3777
3778fn foo() {
3779    let _ = core::mem::offset_of!(Bar, 0.fiel$0d);
3780}
3781        "#,
3782        );
3783
3784        check(
3785            r#"
3786//- minicore: offset_of
3787struct Bar(Baz);
3788enum Baz {
3789    Abc(Foo),
3790    None,
3791}
3792struct Foo {
3793    field: i32,
3794 // ^^^^^
3795}
3796
3797fn foo() {
3798    let _ = core::mem::offset_of!(Bar, 0.Abc.0.fiel$0d);
3799}
3800        "#,
3801        );
3802
3803        check(
3804            r#"
3805//- minicore: offset_of
3806struct Bar(Baz);
3807enum Baz {
3808    Abc(Foo),
3809 // ^^^
3810    None,
3811}
3812struct Foo {
3813    field: i32,
3814}
3815
3816fn foo() {
3817    let _ = core::mem::offset_of!(Bar, 0.Ab$0c.0.field);
3818}
3819        "#,
3820        );
3821    }
3822
3823    #[test]
3824    fn goto_def_for_match_keyword() {
3825        check(
3826            r#"
3827fn main() {
3828    match$0 0 {
3829 // ^^^^^
3830        0 => {},
3831        _ => {},
3832    }
3833}
3834"#,
3835        );
3836    }
3837
3838    #[test]
3839    fn goto_def_for_match_arm_fat_arrow() {
3840        check(
3841            r#"
3842fn main() {
3843    match 0 {
3844        0 =>$0 {},
3845       // ^^
3846        _ => {},
3847    }
3848}
3849"#,
3850        );
3851    }
3852
3853    #[test]
3854    fn goto_def_for_if_keyword() {
3855        check(
3856            r#"
3857fn main() {
3858    if$0 true {
3859 // ^^
3860        ()
3861    }
3862}
3863"#,
3864        );
3865    }
3866
3867    #[test]
3868    fn goto_def_for_match_nested_in_if() {
3869        check(
3870            r#"
3871fn main() {
3872    if true {
3873        match$0 0 {
3874     // ^^^^^
3875            0 => {},
3876            _ => {},
3877        }
3878    }
3879}
3880"#,
3881        );
3882    }
3883
3884    #[test]
3885    fn goto_def_for_multiple_match_expressions() {
3886        check(
3887            r#"
3888fn main() {
3889    match 0 {
3890        0 => {},
3891        _ => {},
3892    };
3893
3894    match$0 1 {
3895 // ^^^^^
3896        1 => {},
3897        _ => {},
3898    }
3899}
3900"#,
3901        );
3902    }
3903
3904    #[test]
3905    fn goto_def_for_nested_match_expressions() {
3906        check(
3907            r#"
3908fn main() {
3909    match 0 {
3910        0 => match$0 1 {
3911          // ^^^^^
3912            1 => {},
3913            _ => {},
3914        },
3915        _ => {},
3916    }
3917}
3918"#,
3919        );
3920    }
3921
3922    #[test]
3923    fn goto_def_for_if_else_chains() {
3924        check(
3925            r#"
3926fn main() {
3927    if true {
3928 // ^^
3929        ()
3930    } else if$0 false {
3931        ()
3932    } else {
3933        ()
3934    }
3935}
3936"#,
3937        );
3938    }
3939
3940    #[test]
3941    fn goto_def_for_match_with_guards() {
3942        check(
3943            r#"
3944fn main() {
3945    match 42 {
3946        x if x > 0 =>$0 {},
3947                // ^^
3948        _ => {},
3949    }
3950}
3951"#,
3952        );
3953    }
3954
3955    #[test]
3956    fn goto_def_for_match_with_macro_arm() {
3957        check(
3958            r#"
3959macro_rules! arm {
3960    () => { 0 => {} };
3961}
3962
3963fn main() {
3964    match$0 0 {
3965 // ^^^^^
3966        arm!(),
3967        _ => {},
3968    }
3969}
3970"#,
3971        );
3972    }
3973
3974    #[test]
3975    fn goto_const_from_match_pat_with_tuple_struct() {
3976        check(
3977            r#"
3978struct Tag(u8);
3979struct Path {}
3980
3981const Path: u8 = 0;
3982   // ^^^^
3983fn main() {
3984    match Tag(Path) {
3985        Tag(Path$0) => {}
3986        _ => {}
3987    }
3988}
3989
3990"#,
3991        );
3992    }
3993
3994    #[test]
3995    fn goto_const_from_match_pat() {
3996        check(
3997            r#"
3998type T1 = u8;
3999const T1: u8 = 0;
4000   // ^^
4001fn main() {
4002    let x = 0;
4003    match x {
4004        T1$0 => {}
4005        _ => {}
4006    }
4007}
4008"#,
4009        );
4010    }
4011
4012    #[test]
4013    fn goto_struct_from_match_pat() {
4014        check(
4015            r#"
4016struct T1;
4017    // ^^
4018fn main() {
4019    let x = 0;
4020    match x {
4021        T1$0 => {}
4022        _ => {}
4023    }
4024}
4025"#,
4026        );
4027    }
4028
4029    #[test]
4030    fn no_goto_trait_from_match_pat() {
4031        check(
4032            r#"
4033trait T1 {}
4034fn main() {
4035    let x = 0;
4036    match x {
4037        T1$0 => {}
4038     // ^^
4039        _ => {}
4040    }
4041}
4042"#,
4043        );
4044    }
4045
4046    #[test]
4047    fn goto_builtin_type() {
4048        check(
4049            r#"
4050//- /main.rs crate:main deps:std
4051const _: &str$0 = ""; }
4052
4053//- /libstd.rs crate:std
4054mod prim_str {}
4055//  ^^^^^^^^
4056"#,
4057        );
4058    }
4059
4060    #[test]
4061    fn ra_fixture() {
4062        check(
4063            r##"
4064fn fixture(#[rust_analyzer::rust_fixture] ra_fixture: &str) {}
4065
4066fn foo() {
4067    fixture(r#"
4068fn foo() {}
4069// ^^^
4070fn bar() {
4071    f$0oo();
4072}
4073    "#)
4074}
4075        "##,
4076        );
4077    }
4078
4079    #[test]
4080    fn regression_20038() {
4081        check(
4082            r#"
4083//- minicore: clone, fn
4084struct Map<Fut, F>(Fut, F);
4085
4086struct InspectFn<F>(F);
4087
4088trait FnOnce1<A> {
4089    type Output;
4090}
4091
4092trait Future1 {
4093    type Output;
4094}
4095
4096trait FusedFuture1: Future1 {
4097    fn is_terminated(&self) -> bool;
4098     //^^^^^^^^^^^^^
4099}
4100
4101impl<T, A, R> FnOnce1<A> for T
4102where
4103    T: FnOnce(A) -> R,
4104{
4105    type Output = R;
4106}
4107
4108impl<F, A> FnOnce1<A> for InspectFn<F>
4109where
4110    F: for<'a> FnOnce1<&'a A, Output = ()>,
4111{
4112    type Output = A;
4113}
4114
4115impl<Fut, F, T> Future1 for Map<Fut, F>
4116where
4117    Fut: Future1,
4118    F: FnOnce1<Fut::Output, Output = T>,
4119{
4120    type Output = T;
4121}
4122
4123impl<Fut, F, T> FusedFuture1 for Map<Fut, F>
4124where
4125    Fut: Future1,
4126    F: FnOnce1<Fut::Output, Output = T>,
4127{
4128    fn is_terminated(&self) -> bool {
4129        false
4130    }
4131}
4132
4133fn overflows<Fut, F>(inner: &Map<Fut, InspectFn<F>>)
4134where
4135    Map<Fut, InspectFn<F>>: FusedFuture1
4136{
4137    let _x = inner.is_terminated$0();
4138}
4139"#,
4140        )
4141    }
4142
4143    #[test]
4144    fn question_mark_on_result_goes_to_conversion() {
4145        check(
4146            r#"
4147//- minicore: try, result, from
4148
4149struct Foo;
4150struct Bar;
4151impl From<Foo> for Bar {
4152    fn from(_: Foo) -> Bar { Bar }
4153    // ^^^^
4154}
4155
4156fn foo() -> Result<(), Bar> {
4157    Err(Foo)?$0;
4158    Ok(())
4159}
4160        "#,
4161        );
4162    }
4163
4164    #[test]
4165    fn goto_definition_for_comparison_operators() {
4166        check(
4167            r#"
4168//- minicore: eq, ord
4169struct Foo;
4170impl PartialEq for Foo {
4171    fn eq(&self, other: &Self) -> bool { true }
4172     //^^
4173}
4174
4175fn main() {
4176    let a = Foo;
4177    let b = Foo;
4178    let _ = a !=$0 b;
4179}
4180"#,
4181        );
4182    }
4183}