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.rs36
1 files changed, 33 insertions, 3 deletions
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index d431f21401..df0705bf90 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)]
@@ -84,6 +84,15 @@ impl LangItemTarget {
_ => None,
}
}
+
+ pub fn as_adt(self) -> Option<AdtId> {
+ match self {
+ LangItemTarget::Union(it) => Some(it.into()),
+ LangItemTarget::EnumId(it) => Some(it.into()),
+ LangItemTarget::Struct(it) => Some(it.into()),
+ _ => None,
+ }
+ }
}
/// Salsa query. This will look for lang items in a specific crate.
@@ -170,7 +179,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)]
@@ -277,6 +298,10 @@ impl LangItem {
lang_item(db, start_crate, self).and_then(|t| t.as_trait())
}
+ pub fn resolve_adt(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<AdtId> {
+ lang_item(db, start_crate, self).and_then(|t| t.as_adt())
+ }
+
pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
lang_item(db, start_crate, self).and_then(|t| t.as_enum())
}
@@ -383,12 +408,17 @@ language_item_table! {
AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
- AsyncFnOnceOutput, sym::async_fn_once_output,async_fn_once_output, Target::AssocTy, GenericRequirement::None;
+ CallRefFuture, sym::call_ref_future, call_ref_future_ty, Target::AssocTy, GenericRequirement::None;
+ CallOnceFuture, sym::call_once_future, call_once_future_ty, Target::AssocTy, GenericRequirement::None;
+ AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output_ty, Target::AssocTy, GenericRequirement::None;
+
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
+ CoroutineReturn, sym::coroutine_return, coroutine_return_ty, Target::AssocTy, GenericRequirement::None;
+ CoroutineYield, sym::coroutine_yield, coroutine_yield_ty, Target::AssocTy, GenericRequirement::None;
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;