From 7d19971666d50a0719e9a88f7dc67822ba96f87c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 9 Sep 2022 20:04:56 +0200 Subject: [PATCH] Add config to unconditionally prefer core imports over std Fixes https://github.com/rust-lang/rust-analyzer/issues/12979 --- crates/hir-def/src/find_path.rs | 36 +++++++++++++++---- crates/hir-ty/src/display.rs | 1 + crates/hir/src/lib.rs | 18 ++++++++-- crates/ide-assists/src/assist_config.rs | 1 + .../src/handlers/add_missing_match_arms.rs | 17 ++++++--- .../ide-assists/src/handlers/auto_import.rs | 7 ++-- .../src/handlers/convert_into_to_from.rs | 2 +- .../src/handlers/extract_function.rs | 1 + .../extract_struct_from_enum_variant.rs | 1 + .../src/handlers/generate_deref.rs | 6 ++-- .../ide-assists/src/handlers/generate_new.rs | 7 ++-- .../src/handlers/qualify_method_call.rs | 7 ++-- .../ide-assists/src/handlers/qualify_path.rs | 3 +- .../replace_derive_with_manual_impl.rs | 2 +- .../replace_qualified_name_with_use.rs | 1 + crates/ide-assists/src/tests.rs | 1 + crates/ide-completion/src/completions.rs | 4 ++- crates/ide-completion/src/completions/expr.rs | 8 +++-- .../src/completions/flyimport.rs | 14 ++++++-- crates/ide-completion/src/config.rs | 1 + crates/ide-completion/src/lib.rs | 7 +++- crates/ide-completion/src/snippet.rs | 8 +++-- crates/ide-completion/src/tests.rs | 1 + crates/ide-db/src/imports/import_assets.rs | 13 ++++--- crates/ide-db/src/path_transform.rs | 3 +- .../src/handlers/json_is_not_rust.rs | 2 ++ .../src/handlers/missing_fields.rs | 1 + crates/ide-diagnostics/src/lib.rs | 2 ++ crates/ide-ssr/src/matching.rs | 7 ++-- crates/rust-analyzer/src/config.rs | 5 +++ .../src/integrated_benchmarks.rs | 2 ++ docs/user/generated_config.adoc | 5 +++ editors/code/package.json | 5 +++ 33 files changed, 156 insertions(+), 43 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 89e961f84fa..f46054e8cc5 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -16,9 +16,14 @@ use crate::{ /// Find a path that can be used to refer to a certain item. This can depend on /// *from where* you're referring to the item, hence the `from` parameter. -pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option { +pub fn find_path( + db: &dyn DefDatabase, + item: ItemInNs, + from: ModuleId, + prefer_core: bool, +) -> Option { let _p = profile::span("find_path"); - find_path_inner(db, item, from, None) + find_path_inner(db, item, from, None, prefer_core) } pub fn find_path_prefixed( @@ -26,9 +31,10 @@ pub fn find_path_prefixed( item: ItemInNs, from: ModuleId, prefix_kind: PrefixKind, + prefer_core: bool, ) -> Option { let _p = profile::span("find_path_prefixed"); - find_path_inner(db, item, from, Some(prefix_kind)) + find_path_inner(db, item, from, Some(prefix_kind), prefer_core) } const MAX_PATH_LEN: usize = 15; @@ -100,12 +106,22 @@ fn find_path_inner( item: ItemInNs, from: ModuleId, prefixed: Option, + prefer_core: bool, ) -> Option { // FIXME: Do fast path for std/core libs? let mut visited_modules = FxHashSet::default(); let def_map = from.def_map(db); - find_path_inner_(db, &def_map, from, item, MAX_PATH_LEN, prefixed, &mut visited_modules) + find_path_inner_( + db, + &def_map, + from, + item, + MAX_PATH_LEN, + prefixed, + &mut visited_modules, + prefer_core, + ) } fn find_path_inner_( @@ -116,6 +132,7 @@ fn find_path_inner_( max_len: usize, mut prefixed: Option, visited_modules: &mut FxHashSet, + prefer_core: bool, ) -> Option { if max_len == 0 { return None; @@ -191,7 +208,9 @@ fn find_path_inner_( // Recursive case: // - if the item is an enum variant, refer to it via the enum if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { - if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) { + if let Some(mut path) = + find_path(db, ItemInNs::Types(variant.parent.into()), from, prefer_core) + { let data = db.enum_data(variant.parent); path.push_segment(data.variants[variant.local_id].name.clone()); return Some(path); @@ -202,7 +221,7 @@ fn find_path_inner_( } // - otherwise, look for modules containing (reexporting) it and import it from one of those - let prefer_no_std = db.crate_supports_no_std(crate_root.krate); + let prefer_no_std = prefer_core || db.crate_supports_no_std(crate_root.krate); let mut best_path = None; let mut best_path_len = max_len; @@ -223,6 +242,7 @@ fn find_path_inner_( best_path_len - 1, prefixed, visited_modules, + prefer_core, ) { path.push_segment(name); @@ -253,6 +273,7 @@ fn find_path_inner_( best_path_len - 1, prefixed, visited_modules, + prefer_core, )?; cov_mark::hit!(partially_imported); path.push_segment(info.path.segments.last()?.clone()); @@ -428,7 +449,8 @@ mod tests { .take_types() .unwrap(); - let found_path = find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind); + let found_path = + find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind, false); assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index d2f9c2b8b1e..874abdaea83 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -533,6 +533,7 @@ impl HirDisplay for Ty { f.db.upcast(), ItemInNs::Types((*def_id).into()), module_id, + false, ) { write!(f, "{}", path)?; } else { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e4bb63a8647..5fa4c151624 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -582,8 +582,13 @@ impl Module { /// Finds a path that can be used to refer to the given item from within /// this module, if possible. - pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into) -> Option { - hir_def::find_path::find_path(db, item.into().into(), self.into()) + pub fn find_use_path( + self, + db: &dyn DefDatabase, + item: impl Into, + prefer_core: bool, + ) -> Option { + hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_core) } /// Finds a path that can be used to refer to the given item from within @@ -593,8 +598,15 @@ impl Module { db: &dyn DefDatabase, item: impl Into, prefix_kind: PrefixKind, + prefer_core: bool, ) -> Option { - hir_def::find_path::find_path_prefixed(db, item.into().into(), self.into(), prefix_kind) + hir_def::find_path::find_path_prefixed( + db, + item.into().into(), + self.into(), + prefix_kind, + prefer_core, + ) } } diff --git a/crates/ide-assists/src/assist_config.rs b/crates/ide-assists/src/assist_config.rs index d4d148c7745..fe2dfca6d5e 100644 --- a/crates/ide-assists/src/assist_config.rs +++ b/crates/ide-assists/src/assist_config.rs @@ -13,4 +13,5 @@ pub struct AssistConfig { pub snippet_cap: Option, pub allowed: Option>, pub insert_use: InsertUseConfig, + pub prefer_core: bool, } diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 1a7919a5a10..d4e21b778c5 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -87,7 +87,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) .into_iter() .filter_map(|variant| { Some(( - build_pat(ctx.db(), module, variant)?, + build_pat(ctx.db(), module, variant, ctx.config.prefer_core)?, variant.should_be_hidden(ctx.db(), module.krate()), )) }) @@ -132,8 +132,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) let is_hidden = variants .iter() .any(|variant| variant.should_be_hidden(ctx.db(), module.krate())); - let patterns = - variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant)); + let patterns = variants.into_iter().filter_map(|variant| { + build_pat(ctx.db(), module, variant, ctx.config.prefer_core) + }); (ast::Pat::from(make::tuple_pat(patterns)), is_hidden) }) @@ -349,10 +350,16 @@ fn resolve_tuple_of_enum_def( .collect() } -fn build_pat(db: &RootDatabase, module: hir::Module, var: ExtendedVariant) -> Option { +fn build_pat( + db: &RootDatabase, + module: hir::Module, + var: ExtendedVariant, + prefer_core: bool, +) -> Option { match var { ExtendedVariant::Variant(var) => { - let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?); + let path = + mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var), prefer_core)?); // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though let pat: ast::Pat = match var.source(db)?.value.kind() { diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index 949cf3167a8..88a6b8558c9 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -89,8 +89,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; // ``` pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; - let mut proposed_imports = - import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind); + let mut proposed_imports = import_assets.search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, + ); if proposed_imports.is_empty() { return None; } diff --git a/crates/ide-assists/src/handlers/convert_into_to_from.rs b/crates/ide-assists/src/handlers/convert_into_to_from.rs index 30f6dd41a1d..e0c0e9a4847 100644 --- a/crates/ide-assists/src/handlers/convert_into_to_from.rs +++ b/crates/ide-assists/src/handlers/convert_into_to_from.rs @@ -50,7 +50,7 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - _ => return None, }; - mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def)?) + mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def, ctx.config.prefer_core)?) }; let dest_type = match &ast_trait { diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index 52a55ead3af..749d94d5a92 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -152,6 +152,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op ctx.sema.db, ModuleDef::from(control_flow_enum), ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, ); if let Some(mod_path) = mod_path { diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index ddc2052e7aa..431f7b3c0fd 100644 --- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -409,6 +409,7 @@ fn process_references( ctx.sema.db, *enum_module_def, ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, ); if let Some(mut mod_path) = mod_path { mod_path.pop_segment(); diff --git a/crates/ide-assists/src/handlers/generate_deref.rs b/crates/ide-assists/src/handlers/generate_deref.rs index b484635121e..cf4ed84281a 100644 --- a/crates/ide-assists/src/handlers/generate_deref.rs +++ b/crates/ide-assists/src/handlers/generate_deref.rs @@ -58,7 +58,8 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = module.find_use_path(ctx.db(), ModuleDef::Trait(trait_))?; + let trait_path = + module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_core)?; let field_type = field.ty()?; let field_name = field.name()?; @@ -98,7 +99,8 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = module.find_use_path(ctx.db(), ModuleDef::Trait(trait_))?; + let trait_path = + module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_core)?; let field_type = field.ty()?; let target = field.syntax().text_range(); diff --git a/crates/ide-assists/src/handlers/generate_new.rs b/crates/ide-assists/src/handlers/generate_new.rs index 6c93875e9eb..ceb7dac0fe9 100644 --- a/crates/ide-assists/src/handlers/generate_new.rs +++ b/crates/ide-assists/src/handlers/generate_new.rs @@ -60,8 +60,11 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?)); - let type_path = current_module - .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?; + let type_path = current_module.find_use_path( + ctx.sema.db, + item_for_path_search(ctx.sema.db, item_in_ns)?, + ctx.config.prefer_core, + )?; let expr = use_trivial_constructor( &ctx.sema.db, diff --git a/crates/ide-assists/src/handlers/qualify_method_call.rs b/crates/ide-assists/src/handlers/qualify_method_call.rs index 121f8b4a136..cb81ebd2285 100644 --- a/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -44,8 +44,11 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> let current_module = ctx.sema.scope(call.syntax())?.module(); let target_module_def = ModuleDef::from(resolved_call); let item_in_ns = ItemInNs::from(target_module_def); - let receiver_path = current_module - .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?; + let receiver_path = current_module.find_use_path( + ctx.sema.db, + item_for_path_search(ctx.sema.db, item_in_ns)?, + ctx.config.prefer_core, + )?; let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call); diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs index 0c2e9da3863..232cd39e8ba 100644 --- a/crates/ide-assists/src/handlers/qualify_path.rs +++ b/crates/ide-assists/src/handlers/qualify_path.rs @@ -37,7 +37,8 @@ use crate::{ // ``` pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; - let mut proposed_imports = import_assets.search_for_relative_paths(&ctx.sema); + let mut proposed_imports = + import_assets.search_for_relative_paths(&ctx.sema, ctx.config.prefer_core); if proposed_imports.is_empty() { return None; } diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index d139f78a6f3..04a1366327f 100644 --- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -85,7 +85,7 @@ pub(crate) fn replace_derive_with_manual_impl( }) .flat_map(|trait_| { current_module - .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) + .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_), ctx.config.prefer_core) .as_ref() .map(mod_path_to_ast) .zip(Some(trait_)) diff --git a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index 2419fa11c15..533e1670a04 100644 --- a/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -67,6 +67,7 @@ pub(crate) fn replace_qualified_name_with_use( ctx.sema.db, module, ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, ) }) .flatten(); diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs index 9cd66c6b3b0..4e589dc86ab 100644 --- a/crates/ide-assists/src/tests.rs +++ b/crates/ide-assists/src/tests.rs @@ -29,6 +29,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { group: true, skip_glob_imports: true, }, + prefer_core: false, }; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 55c3e28392a..89a971e544d 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -551,7 +551,9 @@ fn enum_variants_with_paths( } for variant in variants { - if let Some(path) = ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) { + if let Some(path) = + ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant), ctx.config.prefer_core) + { // Variants with trivial paths are already added by the existing completion logic, // so we should avoid adding these twice if path.segments().len() > 1 { diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index 588b52cc1ee..1ccf33a96b5 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -165,7 +165,11 @@ pub(crate) fn complete_expr_path( hir::Adt::Struct(strukt) => { let path = ctx .module - .find_use_path(ctx.db, hir::ModuleDef::from(strukt)) + .find_use_path( + ctx.db, + hir::ModuleDef::from(strukt), + ctx.config.prefer_core, + ) .filter(|it| it.len() > 1); acc.add_struct_literal(ctx, path_ctx, strukt, path, None); @@ -183,7 +187,7 @@ pub(crate) fn complete_expr_path( hir::Adt::Union(un) => { let path = ctx .module - .find_use_path(ctx.db, hir::ModuleDef::from(un)) + .find_use_path(ctx.db, hir::ModuleDef::from(un), ctx.config.prefer_core) .filter(|it| it.len() > 1); acc.add_union_literal(ctx, un, path, None); diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index f04cc15d7fa..528959943bb 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -262,7 +262,11 @@ fn import_on_the_fly( acc.add_all( import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, + ) .into_iter() .filter(ns_filter) .filter(|import| { @@ -306,7 +310,11 @@ fn import_on_the_fly_pat_( acc.add_all( import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, + ) .into_iter() .filter(ns_filter) .filter(|import| { @@ -344,7 +352,7 @@ fn import_on_the_fly_method( let user_input_lowercased = potential_import_name.to_lowercase(); import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) + .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_core) .into_iter() .filter(|import| { !ctx.is_item_hidden(&import.item_to_import) diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs index 80d6af28168..54ebce1eb79 100644 --- a/crates/ide-completion/src/config.rs +++ b/crates/ide-completion/src/config.rs @@ -17,6 +17,7 @@ pub struct CompletionConfig { pub callable: Option, pub snippet_cap: Option, pub insert_use: InsertUseConfig, + pub prefer_core: bool, pub snippets: Vec, } diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index ae1a440d06d..7cefb6bb4a3 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -234,7 +234,12 @@ pub fn resolve_completion_edits( ); let import = items_with_name .filter_map(|candidate| { - current_module.find_use_path_prefixed(db, candidate, config.insert_use.prefix_kind) + current_module.find_use_path_prefixed( + db, + candidate, + config.insert_use.prefix_kind, + config.prefer_core, + ) }) .find(|mod_path| mod_path.to_string() == full_import_path); if let Some(import_path) = import { diff --git a/crates/ide-completion/src/snippet.rs b/crates/ide-completion/src/snippet.rs index dc1039fa623..2dc62bbdc65 100644 --- a/crates/ide-completion/src/snippet.rs +++ b/crates/ide-completion/src/snippet.rs @@ -174,8 +174,12 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option def.into(), _ => return None, }; - let path = - ctx.module.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?; + let path = ctx.module.find_use_path_prefixed( + ctx.db, + item, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_core, + )?; Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item, None))) }; let mut res = Vec::with_capacity(requires.len()); diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index cf826648dcf..d24c9148566 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -66,6 +66,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { enable_private_editable: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), + prefer_core: false, insert_use: InsertUseConfig { granularity: ImportGranularity::Crate, prefix_kind: PrefixKind::Plain, diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index 26ef86155e5..53bc516109a 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -212,18 +212,20 @@ impl ImportAssets { &self, sema: &Semantics<'_, RootDatabase>, prefix_kind: PrefixKind, + prefer_core: bool, ) -> Vec { let _p = profile::span("import_assets::search_for_imports"); - self.search_for(sema, Some(prefix_kind)) + self.search_for(sema, Some(prefix_kind), prefer_core) } /// This may return non-absolute paths if a part of the returned path is already imported into scope. pub fn search_for_relative_paths( &self, sema: &Semantics<'_, RootDatabase>, + prefer_core: bool, ) -> Vec { let _p = profile::span("import_assets::search_for_relative_paths"); - self.search_for(sema, None) + self.search_for(sema, None, prefer_core) } pub fn path_fuzzy_name_to_exact(&mut self, case_sensitive: bool) { @@ -242,6 +244,7 @@ impl ImportAssets { &self, sema: &Semantics<'_, RootDatabase>, prefixed: Option, + prefer_core: bool, ) -> Vec { let _p = profile::span("import_assets::search_for"); @@ -252,6 +255,7 @@ impl ImportAssets { item_for_path_search(sema.db, item)?, &self.module_with_candidate, prefixed, + prefer_core, ) }; @@ -564,11 +568,12 @@ fn get_mod_path( item_to_search: ItemInNs, module_with_candidate: &Module, prefixed: Option, + prefer_core: bool, ) -> Option { if let Some(prefix_kind) = prefixed { - module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind) + module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind, prefer_core) } else { - module_with_candidate.find_use_path(db, item_to_search) + module_with_candidate.find_use_path(db, item_to_search, prefer_core) } } diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs index 40af9e6fe2a..12d873b4a0a 100644 --- a/crates/ide-db/src/path_transform.rs +++ b/crates/ide-db/src/path_transform.rs @@ -173,6 +173,7 @@ impl<'a> Ctx<'a> { let found_path = self.target_module.find_use_path( self.source_scope.db.upcast(), hir::ModuleDef::Trait(trait_ref), + false, )?; match ast::make::ty_path(mod_path_to_ast(&found_path)) { ast::Type::PathType(path_ty) => Some(path_ty), @@ -209,7 +210,7 @@ impl<'a> Ctx<'a> { } let found_path = - self.target_module.find_use_path(self.source_scope.db.upcast(), def)?; + self.target_module.find_use_path(self.source_scope.db.upcast(), def, false)?; let res = mod_path_to_ast(&found_path).clone_for_update(); if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) { if let Some(segment) = res.segment() { diff --git a/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index a21db5b2cec..06073ca1b25 100644 --- a/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -137,6 +137,7 @@ pub(crate) fn json_in_items( sema.db, it, config.insert_use.prefix_kind, + config.prefer_core, ) { insert_use( &scope, @@ -152,6 +153,7 @@ pub(crate) fn json_in_items( sema.db, it, config.insert_use.prefix_kind, + config.prefer_core, ) { insert_use( &scope, diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index edb1fc0919c..5a81a55d822 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -124,6 +124,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option ExprFillDefaultMode::Default, }, insert_use: self.insert_use_config(), + prefer_core: self.data.imports_prefer_core, } } @@ -1133,6 +1136,7 @@ impl Config { CallableCompletionDef::None => None, }, insert_use: self.insert_use_config(), + prefer_core: self.data.imports_prefer_core, snippet_cap: SnippetCap::new(try_or_def!( self.caps .text_document @@ -1156,6 +1160,7 @@ impl Config { snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")), allowed: None, insert_use: self.insert_use_config(), + prefer_core: self.data.imports_prefer_core, } } diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index e49a98685a7..5dbb64d7df1 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -145,6 +145,7 @@ fn integrated_completion_benchmark() { skip_glob_imports: true, }, snippets: Vec::new(), + prefer_core: false, }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; @@ -182,6 +183,7 @@ fn integrated_completion_benchmark() { skip_glob_imports: true, }, snippets: Vec::new(), + prefer_core: false, }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 72b92572647..6757624aea6 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -353,6 +353,11 @@ Group inserted imports by the https://rust-analyzer.github.io/manual.html#auto-i -- Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`. -- +[[rust-analyzer.imports.prefer.core]]rust-analyzer.imports.prefer.core (default: `false`):: ++ +-- +Prefer to use imports of the core crate over the std crate. +-- [[rust-analyzer.imports.prefix]]rust-analyzer.imports.prefix (default: `"plain"`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 767c5875bf7..7e91d989f15 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -803,6 +803,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.imports.prefer.core": { + "markdownDescription": "Prefer to use imports of the core crate over the std crate.", + "default": false, + "type": "boolean" + }, "rust-analyzer.imports.prefix": { "markdownDescription": "The path structure for newly inserted paths to use.", "default": "plain",