src/tools/rust-analyzer/crates/ide/src/goto_definition.rs RUST 4,103 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,103.
1use std::{iter, mem::discriminant};23use 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};2627#[derive(Debug)]28pub struct GotoDefinitionConfig<'a> {29    pub ra_fixture: RaFixtureConfig<'a>,30}3132// Feature: Go to Definition33//34// Navigates to the definition of an identifier.35//36// For outline modules, this will navigate to the source file of the module.37//38// | Editor  | Shortcut |39// |---------|----------|40// | VS Code | <kbd>F12</kbd> |41//42// ![Go to Definition](https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif)43pub(crate) fn goto_definition(44    db: &RootDatabase,45    FilePosition { file_id, offset }: FilePosition,46    config: &GotoDefinitionConfig<'_>,47) -> Option<RangeInfo<Vec<NavigationTarget>>> {48    let sema = &Semantics::new(db);49    let file = sema.parse_guess_edition(file_id).syntax().clone();50    let edition = sema.attach_first_edition(file_id).edition(db);51    let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {52        IDENT53        | INT_NUMBER54        | LIFETIME_IDENT55        | T![self]56        | T![super]57        | T![crate]58        | T![Self]59        | COMMENT => 4,60        // index and prefix ops61        T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,62        kind if kind.is_keyword(edition) => 2,63        T!['('] | T![')'] => 2,64        kind if kind.is_trivia() => 0,65        _ => 1,66    })?;67    if let Some(doc_comment) = token_as_doc_comment(&original_token) {68        return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, link_range| {69            let nav = def.try_to_nav(sema)?;70            Some(RangeInfo::new(link_range, nav.collect()))71        });72    }7374    if let Some((range, _, _, resolution)) =75        sema.check_for_format_args_template(original_token.clone(), offset)76    {77        return Some(RangeInfo::new(78            range,79            match resolution {80                Some(res) => def_to_nav(sema, Definition::from(res)),81                None => vec![],82            },83        ));84    }8586    if let Some(navs) = handle_control_flow_keywords(sema, &original_token) {87        return Some(RangeInfo::new(original_token.text_range(), navs));88    }8990    let tokens = sema.descend_into_macros_no_opaque(original_token.clone(), false);91    let mut navs = Vec::new();92    for token in tokens {93        if let Some(n) = find_definition_for_known_blanket_dual_impls(sema, &token.value) {94            navs.extend(n);95            continue;96        }9798        let parent = token.value.parent()?;99100        if let Some(question_mark_conversion) = goto_question_mark_conversions(sema, &parent) {101            navs.extend(def_to_nav(sema, question_mark_conversion.into()));102            continue;103        }104105        if let Some(token) = ast::String::cast(token.value.clone())106            && let Some(original_token) = ast::String::cast(original_token.clone())107            && let Some((analysis, fixture_analysis)) =108                Analysis::from_ra_fixture(sema, original_token, &token, &config.ra_fixture)109            && let Some((virtual_file_id, file_offset)) = fixture_analysis.map_offset_down(offset)110        {111            return hir::attach_db_allow_change(&analysis.db, || {112                goto_definition(113                    &analysis.db,114                    FilePosition { file_id: virtual_file_id, offset: file_offset },115                    config,116                )117            })118            .and_then(|navs| {119                navs.upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id).ok()120            });121        }122123        let token_file_id = token.file_id;124        if let Some(token) = ast::String::cast(token.value.clone())125            && let Some(x) =126                try_lookup_include_path(sema, InFile::new(token_file_id, token), file_id)127        {128            navs.push(x);129            continue;130        }131132        if ast::TokenTree::can_cast(parent.kind())133            && let Some(x) = try_lookup_macro_def_in_macro_use(sema, token.value)134        {135            navs.push(x);136            continue;137        }138139        let Some(ident_class) = IdentClass::classify_node(sema, &parent) else { continue };140        navs.extend(ident_class.definitions().into_iter().flat_map(|(def, _)| {141            if let Definition::ExternCrateDecl(crate_def) = def {142                return crate_def143                    .resolved_crate(db)144                    .map(|it| it.root_module(db).to_nav(db))145                    .into_iter()146                    .flatten()147                    .collect();148            }149            try_filter_trait_item_definition(sema, &def).unwrap_or_else(|| def_to_nav(sema, def))150        }));151    }152    let navs = navs.into_iter().unique().collect();153154    Some(RangeInfo::new(original_token.text_range(), navs))155}156157/// When the `?` operator is used on `Result`, go to the `From` impl if it exists as this provides more value.158fn goto_question_mark_conversions(159    sema: &Semantics<'_, RootDatabase>,160    node: &SyntaxNode,161) -> Option<hir::Function> {162    let node = ast::TryExpr::cast(node.clone())?;163    let try_expr_ty = sema.type_of_expr(&node.expr()?)?.adjusted();164165    let fd = FamousDefs(sema, try_expr_ty.krate(sema.db));166    let result_enum = fd.core_result_Result()?.into();167168    let (try_expr_ty_adt, try_expr_ty_args) = try_expr_ty.as_adt_with_args()?;169    if try_expr_ty_adt != result_enum {170        // FIXME: Support `Poll<Result>`.171        return None;172    }173    let original_err_ty = try_expr_ty_args.get(1)?.clone()?;174175    let returned_ty = sema.try_expr_returned_type(&node)?;176    let (returned_adt, returned_ty_args) = returned_ty.as_adt_with_args()?;177    if returned_adt != result_enum {178        return None;179    }180    let returned_err_ty = returned_ty_args.get(1)?.clone()?;181182    if returned_err_ty.could_unify_with_deeply(sema.db, &original_err_ty) {183        return None;184    }185186    let from_trait = fd.core_convert_From()?;187    let from_fn = from_trait.function(sema.db, sym::from)?;188    sema.resolve_trait_impl_method(189        returned_err_ty.clone(),190        from_trait,191        from_fn,192        [returned_err_ty, original_err_ty],193    )194}195196// If the token is into(), try_into(), search the definition of From, TryFrom.197fn find_definition_for_known_blanket_dual_impls(198    sema: &Semantics<'_, RootDatabase>,199    original_token: &SyntaxToken,200) -> Option<Vec<NavigationTarget>> {201    let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;202    let callable = sema.resolve_method_call_as_callable(&method_call)?;203    let CallableKind::Function(f) = callable.kind() else { return None };204    let assoc = f.as_assoc_item(sema.db)?;205206    let return_type = callable.return_type();207    let fd = FamousDefs(sema, return_type.krate(sema.db));208209    let t = match assoc.container(sema.db) {210        hir::AssocItemContainer::Trait(t) => t,211        hir::AssocItemContainer::Impl(impl_)212            if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>213        {214            let t = fd.core_convert_FromStr()?;215            let t_f = t.function(sema.db, &sym::from_str)?;216            return sema217                .resolve_trait_impl_method(218                    return_type.clone(),219                    t,220                    t_f,221                    [return_type.type_arguments().next()?],222                )223                .map(|f| def_to_nav(sema, f.into()));224        }225        hir::AssocItemContainer::Impl(_) => return None,226    };227228    let fn_name = f.name(sema.db);229    let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) {230        let dual = fd.core_convert_From()?;231        let dual_f = dual.function(sema.db, &sym::from)?;232        sema.resolve_trait_impl_method(233            return_type.clone(),234            dual,235            dual_f,236            [return_type, callable.receiver_param(sema.db)?.1],237        )?238    } else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) {239        let dual = fd.core_convert_TryFrom()?;240        let dual_f = dual.function(sema.db, &sym::try_from)?;241        sema.resolve_trait_impl_method(242            return_type.clone(),243            dual,244            dual_f,245            // Extract the `T` from `Result<T, ..>`246            [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1],247        )?248    } else if fn_name == sym::to_string && fd.alloc_string_ToString() == Some(t) {249        let dual = fd.core_fmt_Display()?;250        let dual_f = dual.function(sema.db, &sym::fmt)?;251        sema.resolve_trait_impl_method(252            return_type.clone(),253            dual,254            dual_f,255            [callable.receiver_param(sema.db)?.1.strip_reference()],256        )?257    } else {258        return None;259    };260    // Assert that we got a trait impl function, if we are back in a trait definition we didn't261    // succeed262    let _t = f.as_assoc_item(sema.db)?.implemented_trait(sema.db)?;263    let def = Definition::from(f);264    Some(def_to_nav(sema, def))265}266267fn try_lookup_include_path(268    sema: &Semantics<'_, RootDatabase>,269    token: InFile<ast::String>,270    file_id: FileId,271) -> Option<NavigationTarget> {272    let file = token.file_id.macro_file()?;273274    // Check that we are in the eager argument expansion of an include macro275    // that is we are the string input of it276    if !iter::successors(Some(file), |file| file.parent(sema.db).macro_file())277        .any(|file| file.is_include_like_macro(sema.db) && file.eager_arg(sema.db).is_none())278    {279        return None;280    }281    let path = token.value.value().ok()?;282283    let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;284    let size = sema.db.file_text(file_id).text(sema.db).len().try_into().ok()?;285    Some(NavigationTarget {286        file_id,287        full_range: TextRange::new(0.into(), size),288        name: hir::Symbol::intern(&path),289        alias: None,290        focus_range: None,291        kind: None,292        container_name: None,293        description: None,294        docs: None,295    })296}297298fn try_lookup_macro_def_in_macro_use(299    sema: &Semantics<'_, RootDatabase>,300    token: SyntaxToken,301) -> Option<NavigationTarget> {302    let extern_crate = token.parent()?.ancestors().find_map(ast::ExternCrate::cast)?;303    let extern_crate = sema.to_def(&extern_crate)?;304    let krate = extern_crate.resolved_crate(sema.db)?;305306    for mod_def in krate.root_module(sema.db).declarations(sema.db) {307        if let ModuleDef::Macro(mac) = mod_def308            && mac.name(sema.db).as_str() == token.text()309            && let Some(nav) = mac.try_to_nav(sema)310        {311            return Some(nav.call_site);312        }313    }314315    None316}317318/// finds the trait definition of an impl'd item, except function319/// e.g.320/// ```rust321/// trait A { type a; }322/// struct S;323/// impl A for S { type a = i32; } // <-- on this associate type, will get the location of a in the trait324/// ```325fn try_filter_trait_item_definition(326    sema: &Semantics<'_, RootDatabase>,327    def: &Definition,328) -> Option<Vec<NavigationTarget>> {329    let db = sema.db;330    let assoc = def.as_assoc_item(db)?;331    match assoc {332        AssocItem::Function(..) => None,333        AssocItem::Const(..) | AssocItem::TypeAlias(..) => {334            let trait_ = assoc.implemented_trait(db)?;335            let name = def.name(db)?;336            let discriminant_value = discriminant(&assoc);337            trait_338                .items(db)339                .iter()340                .filter(|itm| discriminant(*itm) == discriminant_value)341                .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(sema)).flatten())342                .map(|it| it.collect())343        }344    }345}346347fn handle_control_flow_keywords(348    sema: &Semantics<'_, RootDatabase>,349    token: &SyntaxToken,350) -> Option<Vec<NavigationTarget>> {351    match token.kind() {352        // For `fn` / `loop` / `while` / `for` / `async` / `match`, return the keyword it self,353        // so that VSCode will find the references when using `ctrl + click`354        T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),355        T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),356        T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {357            nav_for_break_points(sema, token)358        }359        T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),360        _ => None,361    }362}363364pub(crate) fn find_fn_or_blocks(365    sema: &Semantics<'_, RootDatabase>,366    token: &SyntaxToken,367) -> Vec<SyntaxNode> {368    let find_ancestors = |token: SyntaxToken| {369        let token_kind = token.kind();370371        for anc in sema.token_ancestors_with_macros(token) {372            let node = match_ast! {373                match anc {374                    ast::Fn(fn_) => fn_.syntax().clone(),375                    ast::ClosureExpr(c) => c.syntax().clone(),376                    ast::BlockExpr(blk) => {377                        match blk.modifier() {378                            Some(ast::BlockModifier::Async(_)) => blk.syntax().clone(),379                            Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => blk.syntax().clone(),380                            _ => continue,381                        }382                    },383                    _ => continue,384                }385            };386387            return Some(node);388        }389        None390    };391392    sema.descend_into_macros(token.clone()).into_iter().filter_map(find_ancestors).collect_vec()393}394395fn nav_for_exit_points(396    sema: &Semantics<'_, RootDatabase>,397    token: &SyntaxToken,398) -> Option<Vec<NavigationTarget>> {399    let db = sema.db;400    let token_kind = token.kind();401402    let navs = find_fn_or_blocks(sema, token)403        .into_iter()404        .filter_map(|node| {405            let file_id = sema.hir_file_for(&node);406407            match_ast! {408                match node {409                    ast::Fn(fn_) => {410                        let mut nav = sema.to_def(&fn_)?.try_to_nav(sema)?;411                        // For async token, we navigate to itself, which triggers412                        // VSCode to find the references413                        let focus_token = if matches!(token_kind, T![async]) {414                            fn_.async_token()?415                        } else {416                            fn_.fn_token()?417                        };418419                        let focus_frange = InFile::new(file_id, focus_token.text_range())420                            .original_node_file_range_opt(db)421                            .map(|(frange, _)| frange);422423                        if let Some(FileRange { file_id, range }) = focus_frange {424                            let contains_frange = |nav: &NavigationTarget| {425                                nav.file_id == file_id.file_id(db) && nav.full_range.contains_range(range)426                            };427428                            if let Some(def_site) = nav.def_site.as_mut() {429                                if contains_frange(def_site) {430                                    def_site.focus_range = Some(range);431                                }432                            } else if contains_frange(&nav.call_site) {433                                nav.call_site.focus_range = Some(range);434                            }435                        }436437                        Some(nav)438                    },439                    ast::ClosureExpr(c) => {440                        let pipe_tok = c.param_list().and_then(|it| it.pipe_token())?.text_range();441                        let closure_in_file = InFile::new(file_id, c.into());442                        Some(expr_to_nav(db, closure_in_file, Some(pipe_tok)))443                    },444                    ast::BlockExpr(blk) => {445                        match blk.modifier() {446                            Some(ast::BlockModifier::Async(_)) => {447                                let async_tok = blk.async_token()?.text_range();448                                let blk_in_file = InFile::new(file_id, blk.into());449                                Some(expr_to_nav(db, blk_in_file, Some(async_tok)))450                            },451                            Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => {452                                let try_tok = blk.try_block_modifier()?.try_token()?.text_range();453                                let blk_in_file = InFile::new(file_id, blk.into());454                                Some(expr_to_nav(db, blk_in_file, Some(try_tok)))455                            },456                            _ => None,457                        }458                    },459                    _ => None,460                }461            }462        })463        .flatten()464        .collect_vec();465466    Some(navs)467}468469pub(crate) fn find_branch_root(470    sema: &Semantics<'_, RootDatabase>,471    token: &SyntaxToken,472) -> Vec<SyntaxNode> {473    let find_nodes = |node_filter: fn(SyntaxNode) -> Option<SyntaxNode>| {474        sema.descend_into_macros(token.clone())475            .into_iter()476            .filter_map(|token| node_filter(token.parent()?))477            .collect_vec()478    };479480    match token.kind() {481        T![match] => find_nodes(|node| Some(ast::MatchExpr::cast(node)?.syntax().clone())),482        T![=>] => find_nodes(|node| Some(ast::MatchArm::cast(node)?.syntax().clone())),483        T![if] => find_nodes(|node| {484            let if_expr = ast::IfExpr::cast(node)?;485486            let root_if = iter::successors(Some(if_expr.clone()), |if_expr| {487                let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;488                let ast::ElseBranch::IfExpr(else_branch) = parent_if.else_branch()? else {489                    return None;490                };491492                (else_branch.syntax() == if_expr.syntax()).then_some(parent_if)493            })494            .last()?;495496            Some(root_if.syntax().clone())497        }),498        _ => vec![],499    }500}501502fn nav_for_branch_exit_points(503    sema: &Semantics<'_, RootDatabase>,504    token: &SyntaxToken,505) -> Option<Vec<NavigationTarget>> {506    let db = sema.db;507508    let navs = match token.kind() {509        T![match] => find_branch_root(sema, token)510            .into_iter()511            .filter_map(|node| {512                let file_id = sema.hir_file_for(&node);513                let match_expr = ast::MatchExpr::cast(node)?;514                let focus_range = match_expr.match_token()?.text_range();515                let match_expr_in_file = InFile::new(file_id, match_expr.into());516                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))517            })518            .flatten()519            .collect_vec(),520521        T![=>] => find_branch_root(sema, token)522            .into_iter()523            .filter_map(|node| {524                let match_arm = ast::MatchArm::cast(node)?;525                let match_expr = sema526                    .ancestors_with_macros(match_arm.syntax().clone())527                    .find_map(ast::MatchExpr::cast)?;528                let file_id = sema.hir_file_for(match_expr.syntax());529                let focus_range = match_arm.fat_arrow_token()?.text_range();530                let match_expr_in_file = InFile::new(file_id, match_expr.into());531                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))532            })533            .flatten()534            .collect_vec(),535536        T![if] => find_branch_root(sema, token)537            .into_iter()538            .filter_map(|node| {539                let file_id = sema.hir_file_for(&node);540                let if_expr = ast::IfExpr::cast(node)?;541                let focus_range = if_expr.if_token()?.text_range();542                let if_expr_in_file = InFile::new(file_id, if_expr.into());543                Some(expr_to_nav(db, if_expr_in_file, Some(focus_range)))544            })545            .flatten()546            .collect_vec(),547548        _ => return Some(Vec::new()),549    };550551    Some(navs)552}553554fn nav_for_break_points(555    sema: &Semantics<'_, RootDatabase>,556    token: &SyntaxToken,557) -> Option<Vec<NavigationTarget>> {558    let db = sema.db;559560    let navs = find_loops(sema, token)?561        .filter_map(|expr| {562            let file_id = sema.hir_file_for(expr.syntax());563            let expr_in_file = InFile::new(file_id, expr.clone());564            let focus_range = match expr {565                ast::Expr::LoopExpr(loop_) => loop_.loop_token()?.text_range(),566                ast::Expr::WhileExpr(while_) => while_.while_token()?.text_range(),567                ast::Expr::ForExpr(for_) => for_.for_token()?.text_range(),568                // We guarantee that the label exists569                ast::Expr::BlockExpr(blk) => blk.label().unwrap().syntax().text_range(),570                _ => return None,571            };572            let nav = expr_to_nav(db, expr_in_file, Some(focus_range));573            Some(nav)574        })575        .flatten()576        .collect_vec();577578    Some(navs)579}580581fn def_to_nav(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Vec<NavigationTarget> {582    def.try_to_nav(sema).map(|it| it.collect()).unwrap_or_default()583}584585fn expr_to_nav(586    db: &RootDatabase,587    InFile { file_id, value }: InFile<ast::Expr>,588    focus_range: Option<TextRange>,589) -> UpmappingResult<NavigationTarget> {590    let kind = SymbolKind::Label;591592    let value_range = value.syntax().text_range();593    let navs = navigation_target::orig_range_with_focus_r(db, file_id, value_range, focus_range);594    navs.map(|(hir::FileRangeWrapper { file_id, range }, focus_range)| {595        NavigationTarget::from_syntax(596            file_id,597            hir::Symbol::intern("<expr>"),598            focus_range,599            range,600            kind,601        )602    })603}604605#[cfg(test)]606mod tests {607    use crate::{GotoDefinitionConfig, fixture};608    use ide_db::{FileRange, ra_fixture::RaFixtureConfig};609    use itertools::Itertools;610611    const TEST_CONFIG: GotoDefinitionConfig<'_> =612        GotoDefinitionConfig { ra_fixture: RaFixtureConfig::default() };613614    #[track_caller]615    fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {616        let (analysis, position, expected) = fixture::annotations(ra_fixture);617        let navs = analysis618            .goto_definition(position, &TEST_CONFIG)619            .unwrap()620            .expect("no definition found")621            .info;622623        let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());624        let navs = navs625            .into_iter()626            .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })627            .sorted_by_key(cmp)628            .collect::<Vec<_>>();629        let expected = expected630            .into_iter()631            .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range })632            .sorted_by_key(cmp)633            .collect::<Vec<_>>();634635        assert_eq!(expected, navs);636    }637638    fn check_unresolved(#[rust_analyzer::rust_fixture] ra_fixture: &str) {639        let (analysis, position) = fixture::position(ra_fixture);640        let navs = analysis641            .goto_definition(position, &TEST_CONFIG)642            .unwrap()643            .expect("no definition found")644            .info;645646        assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}")647    }648649    fn check_name(expected_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) {650        let (analysis, position, _) = fixture::annotations(ra_fixture);651        let navs = analysis652            .goto_definition(position, &TEST_CONFIG)653            .unwrap()654            .expect("no definition found")655            .info;656        assert!(navs.len() < 2, "expected single navigation target but encountered {}", navs.len());657        let Some(target) = navs.into_iter().next() else {658            panic!("expected single navigation target but encountered none");659        };660        assert_eq!(target.name, hir::Symbol::intern(expected_name));661    }662663    #[test]664    fn goto_def_pat_range_to_inclusive() {665        check_name(666            "RangeToInclusive",667            r#"668//- minicore: range669fn f(ch: char) -> bool {670    match ch {671        ..$0='z' => true,672        _ => false673    }674}675"#,676        );677    }678679    #[test]680    fn goto_def_pat_range_to() {681        check_name(682            "RangeTo",683            r#"684//- minicore: range685fn f(ch: char) -> bool {686    match ch {687        .$0.'z' => true,688        _ => false689    }690}691"#,692        );693    }694695    #[test]696    fn goto_def_pat_range() {697        check_name(698            "Range",699            r#"700//- minicore: range701fn f(ch: char) -> bool {702    match ch {703        'a'.$0.'z' => true,704        _ => false705    }706}707"#,708        );709    }710711    #[test]712    fn goto_def_pat_range_inclusive() {713        check_name(714            "RangeInclusive",715            r#"716//- minicore: range717fn f(ch: char) -> bool {718    match ch {719        'a'..$0='z' => true,720        _ => false721    }722}723"#,724        );725    }726727    #[test]728    fn goto_def_pat_range_from() {729        check_name(730            "RangeFrom",731            r#"732//- minicore: range733fn f(ch: char) -> bool {734    match ch {735        'a'..$0 => true,736        _ => false737    }738}739"#,740        );741    }742743    #[test]744    fn goto_def_expr_range() {745        check_name(746            "Range",747            r#"748//- minicore: range749let x = 0.$0.1;750"#,751        );752    }753754    #[test]755    fn goto_def_expr_range_from() {756        check_name(757            "RangeFrom",758            r#"759//- minicore: range760fn f(arr: &[i32]) -> &[i32] {761    &arr[0.$0.]762}763"#,764        );765    }766767    #[test]768    fn goto_def_expr_range_inclusive() {769        check_name(770            "RangeInclusive",771            r#"772//- minicore: range773let x = 0.$0.=1;774"#,775        );776    }777778    #[test]779    fn goto_def_expr_range_full() {780        check_name(781            "RangeFull",782            r#"783//- minicore: range784fn f(arr: &[i32]) -> &[i32] {785    &arr[.$0.]786}787"#,788        );789    }790791    #[test]792    fn goto_def_expr_range_to() {793        check_name(794            "RangeTo",795            r#"796//- minicore: range797fn f(arr: &[i32]) -> &[i32] {798    &arr[.$0.10]799}800"#,801        );802    }803804    #[test]805    fn goto_def_expr_range_to_inclusive() {806        check_name(807            "RangeToInclusive",808            r#"809//- minicore: range810fn f(arr: &[i32]) -> &[i32] {811    &arr[.$0.=10]812}813"#,814        );815    }816817    #[test]818    fn goto_def_in_included_file() {819        check(820            r#"821//- minicore:include822//- /main.rs823824include!("a.rs");825826fn main() {827    foo();828}829830//- /a.rs831fn func_in_include() {832 //^^^^^^^^^^^^^^^833}834835fn foo() {836    func_in_include$0();837}838"#,839        );840    }841842    #[test]843    fn goto_def_in_included_file_nested() {844        check(845            r#"846//- minicore:include847//- /main.rs848849macro_rules! passthrough {850    ($($tt:tt)*) => { $($tt)* }851}852853passthrough!(include!("a.rs"));854855fn main() {856    foo();857}858859//- /a.rs860fn func_in_include() {861 //^^^^^^^^^^^^^^^862}863864fn foo() {865    func_in_include$0();866}867"#,868        );869    }870871    #[test]872    fn goto_def_in_included_file_inside_mod() {873        check(874            r#"875//- minicore:include876//- /main.rs877mod a {878    include!("b.rs");879}880//- /b.rs881fn func_in_include() {882 //^^^^^^^^^^^^^^^883}884fn foo() {885    func_in_include$0();886}887"#,888        );889890        check(891            r#"892//- minicore:include893//- /main.rs894mod a {895    include!("a.rs");896}897//- /a.rs898fn func_in_include() {899 //^^^^^^^^^^^^^^^900}901902fn foo() {903    func_in_include$0();904}905"#,906        );907    }908909    #[test]910    fn goto_def_if_items_same_name() {911        check(912            r#"913trait Trait {914    type A;915    const A: i32;916        //^917}918919struct T;920impl Trait for T {921    type A = i32;922    const A$0: i32 = -9;923}"#,924        );925    }926    #[test]927    fn goto_def_in_mac_call_in_attr_invoc() {928        check(929            r#"930//- proc_macros: identity931pub struct Struct {932        // ^^^^^^933    field: i32,934}935936macro_rules! identity {937    ($($tt:tt)*) => {$($tt)*};938}939940#[proc_macros::identity]941fn function() {942    identity!(Struct$0 { field: 0 });943}944945"#,946        )947    }948949    #[test]950    fn goto_def_for_extern_crate() {951        check(952            r#"953//- /main.rs crate:main deps:std954extern crate std$0;955//- /std/lib.rs crate:std956// empty957//^file958"#,959        )960    }961962    #[test]963    fn goto_def_for_renamed_extern_crate() {964        check(965            r#"966//- /main.rs crate:main deps:std967extern crate std as abc$0;968//- /std/lib.rs crate:std969// empty970//^file971"#,972        )973    }974975    #[test]976    fn goto_def_in_items() {977        check(978            r#"979struct Foo;980     //^^^981enum E { X(Foo$0) }982"#,983        );984    }985986    #[test]987    fn goto_def_at_start_of_item() {988        check(989            r#"990struct Foo;991     //^^^992enum E { X($0Foo) }993"#,994        );995    }996997    #[test]998    fn goto_definition_resolves_correct_name() {999        check(1000            r#"1001//- /lib.rs1002use a::Foo;1003mod a;1004mod b;1005enum E { X(Foo$0) }10061007//- /a.rs1008pub struct Foo;1009         //^^^1010//- /b.rs1011pub struct Foo;1012"#,1013        );1014    }10151016    #[test]1017    fn goto_def_for_module_declaration() {1018        check(1019            r#"1020//- /lib.rs1021mod $0foo;10221023//- /foo.rs1024// empty1025//^file1026"#,1027        );10281029        check(1030            r#"1031//- /lib.rs1032mod $0foo;10331034//- /foo/mod.rs1035// empty1036//^file1037"#,1038        );1039    }10401041    #[test]1042    fn goto_def_for_macros() {1043        check(1044            r#"1045macro_rules! foo { () => { () } }1046           //^^^1047fn bar() {1048    $0foo!();1049}1050"#,1051        );1052    }10531054    #[test]1055    fn goto_def_for_macros_from_other_crates() {1056        check(1057            r#"1058//- /lib.rs crate:main deps:foo1059use foo::foo;1060fn bar() {1061    $0foo!();1062}10631064//- /foo/lib.rs crate:foo1065#[macro_export]1066macro_rules! foo { () => { () } }1067           //^^^1068"#,1069        );1070    }10711072    #[test]1073    fn goto_def_for_macros_in_use_tree() {1074        check(1075            r#"1076//- /lib.rs crate:main deps:foo1077use foo::foo$0;10781079//- /foo/lib.rs crate:foo1080#[macro_export]1081macro_rules! foo { () => { () } }1082           //^^^1083"#,1084        );1085    }10861087    #[test]1088    fn goto_def_for_macro_defined_fn_with_arg() {1089        check(1090            r#"1091//- /lib.rs1092macro_rules! define_fn {1093    ($name:ident) => (fn $name() {})1094}10951096define_fn!(foo);1097         //^^^10981099fn bar() {1100   $0foo();1101}1102"#,1103        );1104    }11051106    #[test]1107    fn goto_def_for_macro_defined_fn_no_arg() {1108        check(1109            r#"1110//- /lib.rs1111macro_rules! define_fn {1112    () => (fn foo() {})1113            //^^^1114}11151116  define_fn!();1117//^^^^^^^^^^1118fn bar() {1119   $0foo();1120}1121"#,1122        );1123    }11241125    #[test]1126    fn goto_definition_works_for_macro_inside_pattern() {1127        check(1128            r#"1129//- /lib.rs1130macro_rules! foo {() => {0}}1131           //^^^11321133fn bar() {1134    match (0,1) {1135        ($0foo!(), _) => {}1136    }1137}1138"#,1139        );1140    }11411142    #[test]1143    fn goto_definition_works_for_macro_inside_match_arm_lhs() {1144        check(1145            r#"1146//- /lib.rs1147macro_rules! foo {() => {0}}1148           //^^^1149fn bar() {1150    match 0 {1151        $0foo!() => {}1152    }1153}1154"#,1155        );1156    }11571158    #[test]1159    fn goto_definition_works_for_consts_inside_range_pattern() {1160        check(1161            r#"1162//- /lib.rs1163const A: u32 = 0;1164    //^11651166fn bar(v: u32) {1167    match v {1168        0..=$0A => {}1169        _ => {}1170    }1171}1172"#,1173        );1174    }11751176    #[test]1177    fn goto_def_for_use_alias() {1178        check(1179            r#"1180//- /lib.rs crate:main deps:foo1181use foo as bar$0;11821183//- /foo/lib.rs crate:foo1184// empty1185//^file1186"#,1187        );1188    }11891190    #[test]1191    fn goto_def_for_use_alias_foo_macro() {1192        check(1193            r#"1194//- /lib.rs crate:main deps:foo1195use foo::foo as bar$0;11961197//- /foo/lib.rs crate:foo1198#[macro_export]1199macro_rules! foo { () => { () } }1200           //^^^1201"#,1202        );1203    }12041205    #[test]1206    fn goto_def_for_methods() {1207        check(1208            r#"1209struct Foo;1210impl Foo {1211    fn frobnicate(&self) { }1212     //^^^^^^^^^^1213}12141215fn bar(foo: &Foo) {1216    foo.frobnicate$0();1217}1218"#,1219        );1220    }12211222    #[test]1223    fn goto_def_for_fields() {1224        check(1225            r#"1226struct Foo {1227    spam: u32,1228} //^^^^12291230fn bar(foo: &Foo) {1231    foo.spam$0;1232}1233"#,1234        );1235    }12361237    #[test]1238    fn goto_def_for_record_fields() {1239        check(1240            r#"1241//- /lib.rs1242struct Foo {1243    spam: u32,1244} //^^^^12451246fn bar() -> Foo {1247    Foo {1248        spam$0: 0,1249    }1250}1251"#,1252        );1253    }12541255    #[test]1256    fn goto_def_for_record_pat_fields() {1257        check(1258            r#"1259//- /lib.rs1260struct Foo {1261    spam: u32,1262} //^^^^12631264fn bar(foo: Foo) -> Foo {1265    let Foo { spam$0: _, } = foo1266}1267"#,1268        );1269    }12701271    #[test]1272    fn goto_def_for_record_fields_macros() {1273        check(1274            r"1275macro_rules! m { () => { 92 };}1276struct Foo { spam: u32 }1277           //^^^^12781279fn bar() -> Foo {1280    Foo { spam$0: m!() }1281}1282",1283        );1284    }12851286    #[test]1287    fn goto_for_tuple_fields() {1288        check(1289            r#"1290struct Foo(u32);1291         //^^^12921293fn bar() {1294    let foo = Foo(0);1295    foo.$00;1296}1297"#,1298        );1299    }13001301    #[test]1302    fn goto_def_for_ufcs_inherent_methods() {1303        check(1304            r#"1305struct Foo;1306impl Foo {1307    fn frobnicate() { }1308}    //^^^^^^^^^^13091310fn bar(foo: &Foo) {1311    Foo::frobnicate$0();1312}1313"#,1314        );1315    }13161317    #[test]1318    fn goto_def_for_ufcs_trait_methods_through_traits() {1319        check(1320            r#"1321trait Foo {1322    fn frobnicate();1323}    //^^^^^^^^^^13241325fn bar() {1326    Foo::frobnicate$0();1327}1328"#,1329        );1330    }13311332    #[test]1333    fn goto_def_for_ufcs_trait_methods_through_self() {1334        check(1335            r#"1336struct Foo;1337trait Trait {1338    fn frobnicate();1339}    //^^^^^^^^^^1340impl Trait for Foo {}13411342fn bar() {1343    Foo::frobnicate$0();1344}1345"#,1346        );1347    }13481349    #[test]1350    fn goto_definition_on_self() {1351        check(1352            r#"1353struct Foo;1354impl Foo {1355   //^^^1356    pub fn new() -> Self {1357        Self$0 {}1358    }1359}1360"#,1361        );1362        check(1363            r#"1364struct Foo;1365impl Foo {1366   //^^^1367    pub fn new() -> Self$0 {1368        Self {}1369    }1370}1371"#,1372        );13731374        check(1375            r#"1376enum Foo { A }1377impl Foo {1378   //^^^1379    pub fn new() -> Self$0 {1380        Foo::A1381    }1382}1383"#,1384        );13851386        check(1387            r#"1388enum Foo { A }1389impl Foo {1390   //^^^1391    pub fn thing(a: &Self$0) {1392    }1393}1394"#,1395        );1396    }13971398    #[test]1399    fn goto_definition_on_self_in_trait_impl() {1400        check(1401            r#"1402struct Foo;1403trait Make {1404    fn new() -> Self;1405}1406impl Make for Foo {1407            //^^^1408    fn new() -> Self {1409        Self$0 {}1410    }1411}1412"#,1413        );14141415        check(1416            r#"1417struct Foo;1418trait Make {1419    fn new() -> Self;1420}1421impl Make for Foo {1422            //^^^1423    fn new() -> Self$0 {1424        Self {}1425    }1426}1427"#,1428        );1429    }14301431    #[test]1432    fn goto_def_when_used_on_definition_name_itself() {1433        check(1434            r#"1435struct Foo$0 { value: u32 }1436     //^^^1437            "#,1438        );14391440        check(1441            r#"1442struct Foo {1443    field$0: string,1444} //^^^^^1445"#,1446        );14471448        check(1449            r#"1450fn foo_test$0() { }1451 //^^^^^^^^1452"#,1453        );14541455        check(1456            r#"1457enum Foo$0 { Variant }1458   //^^^1459"#,1460        );14611462        check(1463            r#"1464enum Foo {1465    Variant1,1466    Variant2$0,1467  //^^^^^^^^1468    Variant3,1469}1470"#,1471        );14721473        check(1474            r#"1475static INNER$0: &str = "";1476     //^^^^^1477"#,1478        );14791480        check(1481            r#"1482const INNER$0: &str = "";1483    //^^^^^1484"#,1485        );14861487        check(1488            r#"1489type Thing$0 = Option<()>;1490   //^^^^^1491"#,1492        );14931494        check(1495            r#"1496trait Foo$0 { }1497    //^^^1498"#,1499        );15001501        check(1502            r#"1503trait Foo$0 = ;1504    //^^^1505"#,1506        );15071508        check(1509            r#"1510mod bar$0 { }1511  //^^^1512"#,1513        );1514    }15151516    #[test]1517    fn goto_from_macro() {1518        check(1519            r#"1520macro_rules! id {1521    ($($tt:tt)*) => { $($tt)* }1522}1523fn foo() {}1524 //^^^1525id! {1526    fn bar() {1527        fo$0o();1528    }1529}1530mod confuse_index { fn foo(); }1531"#,1532        );1533    }15341535    #[test]1536    fn goto_through_format() {1537        check(1538            r#"1539//- minicore: fmt1540#[macro_export]1541macro_rules! format {1542    ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))1543}1544pub mod __export {1545    pub use core::format_args;1546    fn foo() {} // for index confusion1547}1548fn foo() -> i8 {}1549 //^^^1550fn test() {1551    format!("{}", fo$0o())1552}1553"#,1554        );1555    }15561557    #[test]1558    fn goto_through_included_file() {1559        check(1560            r#"1561//- /main.rs1562#[rustc_builtin_macro]1563macro_rules! include {}15641565include!("foo.rs");15661567fn f() {1568    foo$0();1569}15701571mod confuse_index {1572    pub fn foo() {}1573}15741575//- /foo.rs1576fn foo() {}1577 //^^^1578        "#,1579        );1580    }15811582    #[test]1583    fn goto_through_included_file_struct_with_doc_comment() {1584        check(1585            r#"1586//- /main.rs1587#[rustc_builtin_macro]1588macro_rules! include {}15891590include!("foo.rs");15911592fn f() {1593    let x = Foo$0;1594}15951596mod confuse_index {1597    pub struct Foo;1598}15991600//- /foo.rs1601/// This is a doc comment1602pub struct Foo;1603         //^^^1604        "#,1605        );1606    }16071608    #[test]1609    fn goto_for_type_param() {1610        check(1611            r#"1612struct Foo<T: Clone> { t: $0T }1613         //^1614"#,1615        );1616    }16171618    #[test]1619    fn goto_within_macro() {1620        check(1621            r#"1622macro_rules! id {1623    ($($tt:tt)*) => ($($tt)*)1624}16251626fn foo() {1627    let x = 1;1628      //^1629    id!({1630        let y = $0x;1631        let z = y;1632    });1633}1634"#,1635        );16361637        check(1638            r#"1639macro_rules! id {1640    ($($tt:tt)*) => ($($tt)*)1641}16421643fn foo() {1644    let x = 1;1645    id!({1646        let y = x;1647          //^1648        let z = $0y;1649    });1650}1651"#,1652        );1653    }16541655    #[test]1656    fn goto_def_in_local_fn() {1657        check(1658            r#"1659fn main() {1660    fn foo() {1661        let x = 92;1662          //^1663        $0x;1664    }1665}1666"#,1667        );1668    }16691670    #[test]1671    fn goto_def_in_local_macro() {1672        check(1673            r#"1674fn bar() {1675    macro_rules! foo { () => { () } }1676               //^^^1677    $0foo!();1678}1679"#,1680        );1681    }16821683    #[test]1684    fn goto_def_for_field_init_shorthand() {1685        check(1686            r#"1687struct Foo { x: i32 }1688           //^1689fn main() {1690    let x = 92;1691      //^1692    Foo { x$0 };1693}1694"#,1695        )1696    }16971698    #[test]1699    fn goto_def_for_enum_variant_field() {1700        check(1701            r#"1702enum Foo {1703    Bar { x: i32 }1704        //^1705}1706fn baz(foo: Foo) {1707    match foo {1708        Foo::Bar { x$0 } => x1709                 //^1710    };1711}1712"#,1713        );1714    }17151716    #[test]1717    fn goto_def_for_enum_variant_self_pattern_const() {1718        check(1719            r#"1720enum Foo { Bar }1721         //^^^1722impl Foo {1723    fn baz(self) {1724        match self { Self::Bar$0 => {} }1725    }1726}1727"#,1728        );1729    }17301731    #[test]1732    fn goto_def_for_enum_variant_self_pattern_record() {1733        check(1734            r#"1735enum Foo { Bar { val: i32 } }1736         //^^^1737impl Foo {1738    fn baz(self) -> i32 {1739        match self { Self::Bar$0 { val } => {} }1740    }1741}1742"#,1743        );1744    }17451746    #[test]1747    fn goto_def_for_enum_variant_self_expr_const() {1748        check(1749            r#"1750enum Foo { Bar }1751         //^^^1752impl Foo {1753    fn baz(self) { Self::Bar$0; }1754}1755"#,1756        );1757    }17581759    #[test]1760    fn goto_def_for_enum_variant_self_expr_record() {1761        check(1762            r#"1763enum Foo { Bar { val: i32 } }1764         //^^^1765impl Foo {1766    fn baz(self) { Self::Bar$0 {val: 4}; }1767}1768"#,1769        );1770    }17711772    #[test]1773    fn goto_def_for_type_alias_generic_parameter() {1774        check(1775            r#"1776type Alias<T> = T$0;1777         //^1778"#,1779        )1780    }17811782    #[test]1783    fn goto_def_for_macro_container() {1784        check(1785            r#"1786//- /lib.rs crate:main deps:foo1787foo::module$0::mac!();17881789//- /foo/lib.rs crate:foo1790pub mod module {1791      //^^^^^^1792    #[macro_export]1793    macro_rules! _mac { () => { () } }1794    pub use crate::_mac as mac;1795}1796"#,1797        );1798    }17991800    #[test]1801    fn goto_def_for_assoc_ty_in_path() {1802        check(1803            r#"1804trait Iterator {1805    type Item;1806       //^^^^1807}18081809fn f() -> impl Iterator<Item$0 = u8> {}1810"#,1811        );1812    }18131814    #[test]1815    fn goto_def_for_super_assoc_ty_in_path() {1816        check(1817            r#"1818trait Super {1819    type Item;1820       //^^^^1821}18221823trait Sub: Super {}18241825fn f() -> impl Sub<Item$0 = u8> {}1826"#,1827        );1828    }18291830    #[test]1831    fn goto_def_for_module_declaration_in_path_if_types_and_values_same_name() {1832        check(1833            r#"1834mod bar {1835    pub struct Foo {}1836             //^^^1837    pub fn Foo() {}1838}18391840fn baz() {1841    let _foo_enum: bar::Foo$0 = bar::Foo {};1842}1843        "#,1844        )1845    }18461847    #[test]1848    fn unknown_assoc_ty() {1849        check_unresolved(1850            r#"1851trait Iterator { type Item; }1852fn f() -> impl Iterator<Invalid$0 = u8> {}1853"#,1854        )1855    }18561857    #[test]1858    fn goto_def_for_assoc_ty_in_path_multiple() {1859        check(1860            r#"1861trait Iterator {1862    type A;1863       //^1864    type B;1865}18661867fn f() -> impl Iterator<A$0 = u8, B = ()> {}1868"#,1869        );1870        check(1871            r#"1872trait Iterator {1873    type A;1874    type B;1875       //^1876}18771878fn f() -> impl Iterator<A = u8, B$0 = ()> {}1879"#,1880        );1881    }18821883    #[test]1884    fn goto_def_for_assoc_ty_ufcs() {1885        check(1886            r#"1887trait Iterator {1888    type Item;1889       //^^^^1890}18911892fn g() -> <() as Iterator<Item$0 = ()>>::Item {}1893"#,1894        );1895    }18961897    #[test]1898    fn goto_def_for_assoc_ty_ufcs_multiple() {1899        check(1900            r#"1901trait Iterator {1902    type A;1903       //^1904    type B;1905}19061907fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {}1908"#,1909        );1910        check(1911            r#"1912trait Iterator {1913    type A;1914    type B;1915       //^1916}19171918fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {}1919"#,1920        );1921    }19221923    #[test]1924    fn goto_self_param_ty_specified() {1925        check(1926            r#"1927struct Foo {}19281929impl Foo {1930    fn bar(self: &Foo) {1931         //^^^^1932        let foo = sel$0f;1933    }1934}"#,1935        )1936    }19371938    #[test]1939    fn goto_self_param_on_decl() {1940        check(1941            r#"1942struct Foo {}19431944impl Foo {1945    fn bar(&self$0) {1946          //^^^^1947    }1948}"#,1949        )1950    }19511952    #[test]1953    fn goto_lifetime_param_on_decl() {1954        check(1955            r#"1956fn foo<'foobar$0>(_: &'foobar ()) {1957     //^^^^^^^1958}"#,1959        )1960    }19611962    #[test]1963    fn goto_lifetime_param_decl() {1964        check(1965            r#"1966fn foo<'foobar>(_: &'foobar$0 ()) {1967     //^^^^^^^1968}"#,1969        )1970    }19711972    #[test]1973    fn goto_lifetime_param_decl_nested() {1974        check(1975            r#"1976fn foo<'foobar>(_: &'foobar ()) {1977    fn foo<'foobar>(_: &'foobar$0 ()) {}1978         //^^^^^^^1979}"#,1980        )1981    }19821983    #[test]1984    fn goto_lifetime_hrtb() {1985        // FIXME: requires the HIR to somehow track these hrtb lifetimes1986        check_unresolved(1987            r#"1988trait Foo<T> {}1989fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {}1990                    //^^1991"#,1992        );1993        check_unresolved(1994            r#"1995trait Foo<T> {}1996fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}1997                    //^^1998"#,1999        );2000    }

Code quality findings 47

Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
ast::Expr::BlockExpr(blk) => blk.label().unwrap().syntax().text_range(),
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
.unwrap()
Warning: '.expect()' will panic with a custom message on None/Err. While better than unwrap() for debugging, prefer non-panicking error handling in production code (match, if let, ?).
warning correctness expect-usage
.expect("no definition found")
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
.unwrap()
Warning: '.expect()' will panic with a custom message on None/Err. While better than unwrap() for debugging, prefer non-panicking error handling in production code (match, if let, ?).
warning correctness expect-usage
.expect("no definition found")
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&arr[0.$0.]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&arr[.$0.]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&arr[.$0.10]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
&arr[.$0.=10]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// Blah, [`bar`](bar) .. [`foo`](foo$0) has [`bar`](bar)
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// You might want to see [`std::fs::read()`] too.
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// Gives you a [`TheItem$0`].
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
Struct[0]$0;
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
foo[0]$0 = Bar;
Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning correctness discarded-result
let _ = core::mem::offset_of!(Foo, fiel$0d);
Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning correctness discarded-result
let _ = core::mem::offset_of!(Bar, 0.fiel$0d);
Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning correctness discarded-result
let _ = core::mem::offset_of!(Bar, 0.Abc.0.fiel$0d);
Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning correctness discarded-result
let _ = core::mem::offset_of!(Bar, 0.Ab$0c.0.field);
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
let tokens = sema.descend_into_macros_no_opaque(original_token.clone(), false);
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match token.kind() {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match anc {
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
ast::Fn(fn_) => fn_.syntax().clone(),
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
ast::ClosureExpr(c) => c.syntax().clone(),
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match blk.modifier() {
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
Some(ast::BlockModifier::Async(_)) => blk.syntax().clone(),
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => blk.syntax().clone(),
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let focus_range = match expr {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ch {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ch {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ch {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ch {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ch {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match v {
Info: This standard library function returns a Result. Ensure the Result is handled properly (e.g., using '?', match, if let) rather than potentially panicking with .unwrap() or .expect().
info correctness unhandled-result
/// You might want to see [`std::fs::read()`] too.
Info: Including file content directly into the binary at compile time. Ensure this is intended, as it increases binary size and doesn't reflect runtime file changes.
info maintainability include-in-binary
let str = include_str!("foo.txt$0");
Info: Including file content directly into the binary at compile time. Ensure this is intended, as it increases binary size and doesn't reflect runtime file changes.
info maintainability include-in-binary
let str = include_str!(concat!("foo", ".tx$0t"));
Info: Including file content directly into the binary at compile time. Ensure this is intended, as it increases binary size and doesn't reflect runtime file changes.
info maintainability include-in-binary
#[doc = include_str!("docs.md$0")]
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("{}", i);
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("{}", i);
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match 0 {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match 0 {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match 0 {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match 42 {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match Tag(Path) {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match x {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match x {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match x {

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.