Repository: rust-lang/rust-analyzer
Pull request #19028 (2025-01-25 11:19:52)

fix: Fix flyimport not filtering via stability of import path
This also should have the benefit of no longer importing intrinsics on stable (as their module is unstable, funnily rustc doesn't check that?).


Patch:
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 5d67902c8a..c30ad0163b 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -445,6 +445,10 @@ fn find_in_dep(
         };
         cov_mark::hit!(partially_imported);
         if info.is_unstable {
+            if !ctx.cfg.allow_unstable {
+                // the item is unstable and we are not allowed to use unstable items
+                continue;
+            }
             choice.stability = Unstable;
         }
 
@@ -670,6 +674,7 @@ mod tests {
         prefer_prelude: bool,
         prefer_absolute: bool,
         prefer_no_std: bool,
+        allow_unstable: bool,
         expect: Expect,
     ) {
         let (db, pos) = TestDB::with_position(ra_fixture);
@@ -711,7 +716,7 @@ mod tests {
                 module,
                 prefix,
                 ignore_local_imports,
-                ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute },
+                ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
             );
             format_to!(
                 res,
@@ -732,7 +737,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, false, false, expect);
+        check_found_path_(ra_fixture, path, false, false, false, false, expect);
     }
 
     fn check_found_path_prelude(
@@ -740,7 +745,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, true, false, false, expect);
+        check_found_path_(ra_fixture, path, true, false, false, false, expect);
     }
 
     fn check_found_path_absolute(
@@ -748,7 +753,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, true, false, expect);
+        check_found_path_(ra_fixture, path, false, true, false, false, expect);
     }
 
     fn check_found_path_prefer_no_std(
@@ -756,7 +761,15 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, false, true, expect);
+        check_found_path_(ra_fixture, path, false, false, true, false, expect);
+    }
+
+    fn check_found_path_prefer_no_std_allow_unstable(
+        #[rust_analyzer::rust_fixture] ra_fixture: &str,
+        path: &str,
+        expect: Expect,
+    ) {
+        check_found_path_(ra_fixture, path, false, false, true, true, expect);
     }
 
     #[test]
@@ -1951,7 +1964,7 @@ pub mod ops {
 
     #[test]
     fn respect_unstable_modules() {
-        check_found_path_prefer_no_std(
+        check_found_path_prefer_no_std_allow_unstable(
             r#"
 //- /main.rs crate:main deps:std,core
 extern crate std;
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index da9ffae8aa..c78818c642 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -114,6 +114,9 @@ pub struct ImportPathConfig {
     pub prefer_prelude: bool,
     /// If true, prefer abs path (starting with `::`) where it is available.
     pub prefer_absolute: bool,
+    /// If true, paths containing `#[unstable]` segments may be returned, but only if if there is no
+    /// stable path. This does not check, whether the item itself that is being imported is `#[unstable]`.
+    pub allow_unstable: bool,
 }
 
 #[derive(Debug)]
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 3545bf7677..d960aaf99f 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1159,6 +1159,7 @@ impl HirDisplay for Ty {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             },
                         ) {
                             write!(f, "{}", path.display(f.db.upcast(), f.edition()))?;
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 2ebd88edae..c1c45d8175 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -158,32 +158,24 @@ impl<'a> SymbolCollector<'a> {
         // Nested trees are very common, so a cache here will hit a lot.
         let import_child_source_cache = &mut FxHashMap::default();
 
-        let is_explicit_import = |vis| match vis {
-            Visibility::Public => true,
-            Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
-            Visibility::Module(_, VisibilityExplicitness::Implicit) => false,
-        };
-
-        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId, vis| {
+        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| {
             let source = import_child_source_cache
                 .entry(i.use_)
                 .or_insert_with(|| i.use_.child_source(this.db.upcast()));
             let Some(use_tree_src) = source.value.get(i.idx) else { return };
-            let rename = use_tree_src.rename().and_then(|rename| rename.name());
-            let name_syntax = match rename {
-                Some(name) => Some(Either::Left(name)),
-                None if is_explicit_import(vis) => {
-                    (|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))()
-                }
-                None => None,
-            };
-            let Some(name_syntax) = name_syntax else {
+            let Some(name_ptr) = use_tree_src
+                .rename()
+                .and_then(|rename| rename.name())
+                .map(Either::Left)
+                .or_else(|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))
+                .map(|it| AstPtr::new(&it))
+            else {
                 return;
             };
             let dec_loc = DeclarationLocation {
                 hir_file_id: source.file_id,
                 ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
-                name_ptr: AstPtr::new(&name_syntax),
+                name_ptr,
             };
             this.symbols.insert(FileSymbol {
                 name: name.symbol().clone(),
@@ -196,23 +188,23 @@ impl<'a> SymbolCollector<'a> {
         };
 
         let push_extern_crate =
-            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId, vis| {
+            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId| {
                 let loc = i.lookup(this.db.upcast());
                 let source = loc.source(this.db.upcast());
-                let rename = source.value.rename().and_then(|rename| rename.name());
-
-                let name_syntax = match rename {
-                    Some(name) => Some(Either::Left(name)),
-                    None if is_explicit_import(vis) => None,
-                    None => source.value.name_ref().map(Either::Right),
-                };
-                let Some(name_syntax) = name_syntax else {
+                let Some(name_ptr) = source
+                    .value
+                    .rename()
+                    .and_then(|rename| rename.name())
+                    .map(Either::Left)
+                    .or_else(|| source.value.name_ref().map(Either::Right))
+                    .map(|it| AstPtr::new(&it))
+                else {
                     return;
                 };
                 let dec_loc = DeclarationLocation {
                     hir_file_id: source.file_id,
                     ptr: SyntaxNodePtr::new(source.value.syntax()),
-                    name_ptr: AstPtr::new(&name_syntax),
+                    name_ptr,
                 };
                 this.symbols.insert(FileSymbol {
                     name: name.symbol().clone(),
@@ -224,6 +216,18 @@ impl<'a> SymbolCollector<'a> {
                 });
             };
 
+        let is_explicit_import = |vis| {
+            match vis {
+                Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
+                Visibility::Module(_, VisibilityExplicitness::Implicit) => {
+                    // consider imports in the crate root explicit, as these are visibly
+                    // crate-wide anyways
+                    module_id.is_crate_root()
+                }
+                Visibility::Public => true,
+            }
+        };
+
         let def_map = module_id.def_map(self.db.upcast());
         let scope = &def_map[module_id.local_id].scope;
 
@@ -233,14 +237,15 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.types() {
             if let Some(i) = import {
-                match i {
-                    ImportOrExternCrate::Import(i) => push_import(self, i, name, def, vis),
-                    ImportOrExternCrate::Glob(_) => (),
-                    ImportOrExternCrate::ExternCrate(i) => {
-                        push_extern_crate(self, i, name, def, vis)
+                if is_explicit_import(vis) {
+                    match i {
+                        ImportOrExternCrate::Import(i) => push_import(self, i, name, def),
+                        ImportOrExternCrate::Glob(_) => (),
+                        ImportOrExternCrate::ExternCrate(i) => {
+                            push_extern_crate(self, i, name, def)
+                        }
                     }
                 }
-
                 continue;
             }
             // self is a declaration
@@ -249,9 +254,11 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.macros() {
             if let Some(i) = import {
-                match i {
-                    ImportOrGlob::Import(i) => push_import(self, i, name, def.into(), vis),
-                    ImportOrGlob::Glob(_) => (),
+                if is_explicit_import(vis) {
+                    match i {
+                        ImportOrGlob::Import(i) => push_import(self, i, name, def.into()),
+                        ImportOrGlob::Glob(_) => (),
+                    }
                 }
                 continue;
             }
@@ -261,9 +268,11 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.values() {
             if let Some(i) = import {
-                match i {
-                    ImportOrGlob::Import(i) => push_import(self, i, name, def, vis),
-                    ImportOrGlob::Glob(_) => (),
+                if is_explicit_import(vis) {
+                    match i {
+                        ImportOrGlob::Import(i) => push_import(self, i, name, def),
+                        ImportOrGlob::Glob(_) => (),
+                    }
                 }
                 continue;
             }
diff --git a/crates/ide-assists/src/assist_config.rs b/crates/ide-assists/src/assist_config.rs
index 82d8db4258..fb533077d9 100644
--- a/crates/ide-assists/src/assist_config.rs
+++ b/crates/ide-assists/src/assist_config.rs
@@ -28,6 +28,7 @@ impl AssistConfig {
             prefer_no_std: self.prefer_no_std,
             prefer_prelude: self.prefer_prelude,
             prefer_absolute: self.prefer_absolute,
+            allow_unstable: true,
         }
     }
 }
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 40669c65c5..88f893e42a 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -660,7 +660,7 @@ fn enum_variants_with_paths(
         if let Some(path) = ctx.module.find_path(
             ctx.db,
             hir::ModuleDef::from(variant),
-            ctx.config.import_path_config(),
+            ctx.config.import_path_config(ctx.is_nightly),
         ) {
             // Variants with trivial paths are already added by the existing completion logic,
             // so we should avoid adding these twice
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index db18b531d7..e710175170 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -247,7 +247,7 @@ pub(crate) fn complete_expr_path(
                             .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(strukt),
-                                ctx.config.import_path_config(),
+                                ctx.config.import_path_config(ctx.is_nightly),
                             )
                             .filter(|it| it.len() > 1);
 
@@ -269,7 +269,7 @@ pub(crate) fn complete_expr_path(
                             .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(un),
-                                ctx.config.import_path_config(),
+                                ctx.config.import_path_config(ctx.is_nightly),
                             )
                             .filter(|it| it.len() > 1);
 
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 435b88de4a..24243f57b4 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -257,7 +257,7 @@ fn import_on_the_fly(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    let import_cfg = ctx.config.import_path_config();
+    let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, import_cfg, ctx.config.insert_use.prefix_kind)
@@ -316,7 +316,7 @@ fn import_on_the_fly_pat_(
         ItemInNs::Values(def) => matches!(def, hir::ModuleDef::Const(_)),
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
@@ -358,7 +358,7 @@ fn import_on_the_fly_method(
 
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index 67ea05e002..2c39a8fdfe 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -60,7 +60,7 @@ pub(crate) fn complete_postfix(
         None => return,
     };
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
         if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs
index c641df38ff..45aab38e8e 100644
--- a/crates/ide-completion/src/config.rs
+++ b/crates/ide-completion/src/config.rs
@@ -59,11 +59,12 @@ impl CompletionConfig<'_> {
             .flat_map(|snip| snip.prefix_triggers.iter().map(move |trigger| (&**trigger, snip)))
     }
 
-    pub fn import_path_config(&self) -> ImportPathConfig {
+    pub fn import_path_config(&self, allow_unstable: bool) -> ImportPathConfig {
         ImportPathConfig {
             prefer_no_std: self.prefer_no_std,
             prefer_prelude: self.prefer_prelude,
             prefer_absolute: self.prefer_absolute,
+            allow_unstable,
         }
     }
 }
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 3a2a4a23a1..366e79cddf 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -443,7 +443,9 @@ pub(crate) struct CompletionContext<'a> {
     /// The module of the `scope`.
     pub(crate) module: hir::Module,
     /// Whether nightly toolchain is used. Cached since this is looked up a lot.
-    is_nightly: bool,
+    pub(crate) is_nightly: bool,
+    /// The edition of the current crate
+    // FIXME: This should probably be the crate of the current token?
     pub(crate) edition: Edition,
 
     /// The expected name of what we are completing.
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 56d7eeaf8e..ac6b1207f2 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -289,7 +289,7 @@ pub fn resolve_completion_edits(
     let new_ast = scope.clone_for_update();
     let mut import_insert = TextEdit::builder();
 
-    let cfg = config.import_path_config();
+    let cfg = config.import_path_config(true);
 
     imports.into_iter().for_each(|(full_import_path, imported_name)| {
         let items_with_name = items_locator::items_with_name(
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 1b7adf1adb..dc7eacbfba 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -301,7 +301,7 @@ pub(crate) fn render_expr(
             .unwrap_or_else(|| String::from("..."))
     };
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.edition).ok()?;
 
diff --git a/crates/ide-completion/src/snippet.rs b/crates/ide-completion/src/snippet.rs
index 04bb178c65..866b83a614 100644
--- a/crates/ide-completion/src/snippet.rs
+++ b/crates/ide-completion/src/snippet.rs
@@ -164,7 +164,7 @@ impl Snippet {
 }
 
 fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec<LocatedImport>> {
-    let import_cfg = ctx.config.import_path_config();
+    let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     let resolve = |import| {
         let item = ctx.scope.resolve_mod_path(import).next()?;
diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs
index a045c22c2d..f045e44dd3 100644
--- a/crates/ide-db/src/path_transform.rs
+++ b/crates/ide-db/src/path_transform.rs
@@ -319,6 +319,7 @@ impl Ctx<'_> {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             };
                             let found_path = self.target_module.find_path(
                                 self.source_scope.db.upcast(),
@@ -378,6 +379,7 @@ impl Ctx<'_> {
                     prefer_no_std: false,
                     prefer_prelude: true,
                     prefer_absolute: false,
+                    allow_unstable: true,
                 };
                 let found_path =
                     self.target_module.find_path(self.source_scope.db.upcast(), def, cfg)?;
@@ -417,6 +419,7 @@ impl Ctx<'_> {
                             prefer_no_std: false,
                             prefer_prelude: true,
                             prefer_absolute: false,
+                            allow_unstable: true,
                         };
                         let found_path = self.target_module.find_path(
                             self.source_scope.db.upcast(),
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 dca889d1a8..f22041ebe2 100644
--- a/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -147,6 +147,7 @@ pub(crate) fn json_in_items(
                             prefer_no_std: config.prefer_no_std,
                             prefer_prelude: config.prefer_prelude,
                             prefer_absolute: config.prefer_absolute,
+                            allow_unstable: true,
                         };
 
                         if !scope_has("Serialize") {
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index fd1044e51b..938b7182bc 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -128,6 +128,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
                                 prefer_no_std: ctx.config.prefer_no_std,
                                 prefer_prelude: ctx.config.prefer_prelude,
                                 prefer_absolute: ctx.config.prefer_absolute,
+                                allow_unstable: ctx.is_nightly,
                             },
                         )?;
 
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 3ad84f7bda..b023a95fb3 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -70,6 +70,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
                     prefer_no_std: ctx.config.prefer_no_std,
                     prefer_prelude: ctx.config.prefer_prelude,
                     prefer_absolute: ctx.config.prefer_absolute,
+                    allow_unstable: ctx.is_nightly,
                 },
                 ctx.edition,
             )
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 1e99d7ad6e..50c91a6960 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -83,7 +83,7 @@ use either::Either;
 use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics};
 use ide_db::{
     assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
-    base_db::SourceDatabase,
+    base_db::{ReleaseChannel, SourceDatabase},
     generated::lints::{Lint, LintGroup, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, DEFAULT_LINT_GROUPS},
     imports::insert_use::InsertUseConfig,
     label::Label,
@@ -276,6 +276,7 @@ struct DiagnosticsContext<'a> {
     sema: Semantics<'a, RootDatabase>,
     resolve: &'a AssistResolveStrategy,
     edition: Edition,
+    is_nightly: bool,
 }
 
 impl DiagnosticsContext<'_> {
@@ -368,7 +369,11 @@ pub fn semantic_diagnostics(
 
     let module = sema.file_to_module_def(file_id);
 
-    let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition() };
+    let is_nightly = matches!(
+        module.and_then(|m| db.toolchain_channel(m.krate().into())),
+        Some(ReleaseChannel::Nightly) | None
+    );
+    let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition(), is_nightly };
 
     let mut diags = Vec::new();
     match module {
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index 4edc3633fb..4bead14e31 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/crates/ide-ssr/src/matching.rs
@@ -673,6 +673,7 @@ impl Match {
                     prefer_no_std: false,
                     prefer_prelude: true,
                     prefer_absolute: false,
+                    allow_unstable: true,
                 };
                 let mod_path = module.find_path(sema.db, module_def, cfg).ok_or_else(|| {
                     match_error!("Failed to render template path `{}` at match location")
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index bcaec52019..18c27c8449 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -465,6 +465,7 @@ impl flags::AnalysisStats {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             },
                             Edition::LATEST,
                         )


Test patch:
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index d491e438fe..2e7c53def7 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -1390,6 +1390,41 @@ pub struct FooStruct {}
     );
 }
 
+#[test]
+fn flyimport_pattern_unstable_path() {
+    check(
+        r#"
+//- /main.rs crate:main deps:std
+fn function() {
+    let foo$0
+}
+//- /std.rs crate:std
+#[unstable]
+pub mod unstable {
+    pub struct FooStruct {}
+}
+"#,
+        expect![""],
+    );
+    check(
+        r#"
+//- toolchain:nightly
+//- /main.rs crate:main deps:std
+fn function() {
+    let foo$0
+}
+//- /std.rs crate:std
+#[unstable]
+pub mod unstable {
+    pub struct FooStruct {}
+}
+"#,
+        expect![[r#"
+            st FooStruct (use std::unstable::FooStruct)
+        "#]],
+    );
+}
+
 #[test]
 fn flyimport_pattern_unstable_item_on_nightly() {
     check(
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 7dce95592b..535777dfcb 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -1007,39 +1007,6 @@
                 is_alias: false,
                 is_assoc: false,
             },
-            FileSymbol {
-                name: "ThisStruct",
-                def: Adt(
-                    Struct(
-                        Struct {
-                            id: StructId(
-                                4,
-                            ),
-                        },
-                    ),
-                ),
-                loc: DeclarationLocation {
-                    hir_file_id: EditionedFileId(
-                        FileId(
-                            1,
-                        ),
-                        Edition2021,
-                    ),
-                    ptr: SyntaxNodePtr {
-                        kind: USE_TREE,
-                        range: 85..125,
-                    },
-                    name_ptr: AstPtr(
-                        SyntaxNodePtr {
-                            kind: NAME,
-                            range: 115..125,
-                        },
-                    ),
-                },
-                container_name: None,
-                is_alias: false,
-                is_assoc: false,
-            },
         ],
     ),
 ]