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