Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lang_item.rs')
| -rw-r--r-- | crates/hir-def/src/lang_item.rs | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index a0be69cb2f..600f206770 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -12,7 +12,7 @@ use crate::{ StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, expr_store::path::Path, - nameres::{assoc::TraitItems, crate_def_map}, + nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -170,7 +170,19 @@ pub fn lang_item( { return Some(target); } - start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item)) + + // Our `CrateGraph` eagerly inserts sysroot dependencies like `core` or `std` into dependencies + // even if the target crate has `#![no_std]`, `#![no_core]` or shadowed sysroot dependencies + // like `dependencies.std.path = ".."`. So we use `extern_prelude()` instead of + // `CrateData.dependencies` here, which has already come through such sysroot complexities + // while nameres. + // + // See https://github.com/rust-lang/rust-analyzer/pull/20475 for details. + crate_local_def_map(db, start_crate).local(db).extern_prelude().find_map(|(_, (krate, _))| { + // Some crates declares themselves as extern crate like `extern crate self as core`. + // Ignore these to prevent cycles. + if krate.krate == start_crate { None } else { lang_item(db, krate.krate, item) } + }) } #[derive(Default, Debug, Clone, PartialEq, Eq)] |