Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/method_resolution.rs')
| -rw-r--r-- | crates/hir-ty/src/method_resolution.rs | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index c370330a87..88f48fdbc6 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -13,11 +13,12 @@ use tracing::{debug, instrument}; use base_db::Crate; use hir_def::{ - AssocItemId, BlockId, ConstId, FunctionId, GenericParamId, HasModule, ImplId, ItemContainerId, - ModuleId, TraitId, + AssocItemId, BlockId, BuiltinDeriveImplId, ConstId, FunctionId, GenericParamId, HasModule, + ImplId, ItemContainerId, ModuleId, TraitId, attrs::AttrFlags, expr_store::path::GenericArgs as HirGenericArgs, hir::ExprId, + lang_item::LangItems, nameres::{DefMap, block_def_map, crate_def_map}, resolver::Resolver, }; @@ -37,7 +38,7 @@ use crate::{ infer::{InferenceContext, unify::InferenceTable}, lower::GenericPredicates, next_solver::{ - Binder, ClauseKind, DbInterner, FnSig, GenericArgs, ParamEnv, PredicateKind, + AnyImplId, Binder, ClauseKind, DbInterner, FnSig, GenericArgs, ParamEnv, PredicateKind, SimplifiedType, SolverDefId, TraitRef, Ty, TyKind, TypingMode, infer::{ BoundRegionConversionTime, DbInternerInferExt, InferCtxt, InferOk, @@ -132,7 +133,7 @@ pub enum MethodError<'db> { // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum CandidateSource { - Impl(ImplId), + Impl(AnyImplId), Trait(TraitId), } @@ -462,6 +463,10 @@ fn lookup_impl_assoc_item_for_trait_ref<'db>( name: &Name, ) -> Option<(AssocItemId, GenericArgs<'db>)> { let (impl_id, impl_subst) = find_matching_impl(infcx, env, trait_ref)?; + let AnyImplId::ImplId(impl_id) = impl_id else { + // FIXME: Handle resolution to builtin derive. + return None; + }; let item = impl_id.impl_items(infcx.interner.db).items.iter().find_map(|(n, it)| match *it { AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)), @@ -475,7 +480,7 @@ pub(crate) fn find_matching_impl<'db>( infcx: &InferCtxt<'db>, env: ParamEnv<'db>, trait_ref: TraitRef<'db>, -) -> Option<(ImplId, GenericArgs<'db>)> { +) -> Option<(AnyImplId, GenericArgs<'db>)> { let trait_ref = infcx.at(&ObligationCause::dummy(), env).deeply_normalize(trait_ref).ok()?; let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env, trait_ref); @@ -635,13 +640,13 @@ impl InherentImpls { #[derive(Debug, PartialEq)] struct OneTraitImpls { - non_blanket_impls: FxHashMap<SimplifiedType, Box<[ImplId]>>, + non_blanket_impls: FxHashMap<SimplifiedType, (Box<[ImplId]>, Box<[BuiltinDeriveImplId]>)>, blanket_impls: Box<[ImplId]>, } #[derive(Default)] struct OneTraitImplsBuilder { - non_blanket_impls: FxHashMap<SimplifiedType, Vec<ImplId>>, + non_blanket_impls: FxHashMap<SimplifiedType, (Vec<ImplId>, Vec<BuiltinDeriveImplId>)>, blanket_impls: Vec<ImplId>, } @@ -650,7 +655,9 @@ impl OneTraitImplsBuilder { let mut non_blanket_impls = self .non_blanket_impls .into_iter() - .map(|(self_ty, impls)| (self_ty, impls.into_boxed_slice())) + .map(|(self_ty, (impls, builtin_derive_impls))| { + (self_ty, (impls.into_boxed_slice(), builtin_derive_impls.into_boxed_slice())) + }) .collect::<FxHashMap<_, _>>(); non_blanket_impls.shrink_to_fit(); let blanket_impls = self.blanket_impls.into_boxed_slice(); @@ -691,8 +698,9 @@ impl TraitImpls { impl TraitImpls { fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap) -> Self { + let lang_items = hir_def::lang_item::lang_items(db, def_map.krate()); let mut map = FxHashMap::default(); - collect(db, def_map, &mut map); + collect(db, def_map, lang_items, &mut map); let mut map = map .into_iter() .map(|(trait_id, trait_map)| (trait_id, trait_map.finish())) @@ -703,6 +711,7 @@ impl TraitImpls { fn collect( db: &dyn HirDatabase, def_map: &DefMap, + lang_items: &LangItems, map: &mut FxHashMap<TraitId, OneTraitImplsBuilder>, ) { for (_module_id, module_data) in def_map.modules() { @@ -727,18 +736,29 @@ impl TraitImpls { let entry = map.entry(trait_ref.def_id.0).or_default(); match simplify_type(interner, self_ty, TreatParams::InstantiateWithInfer) { Some(self_ty) => { - entry.non_blanket_impls.entry(self_ty).or_default().push(impl_id) + entry.non_blanket_impls.entry(self_ty).or_default().0.push(impl_id) } None => entry.blanket_impls.push(impl_id), } } + for impl_id in module_data.scope.builtin_derive_impls() { + let loc = impl_id.loc(db); + let Some(trait_id) = loc.trait_.get_id(lang_items) else { continue }; + let entry = map.entry(trait_id).or_default(); + let entry = entry + .non_blanket_impls + .entry(SimplifiedType::Adt(loc.adt.into())) + .or_default(); + entry.1.push(impl_id); + } + // To better support custom derives, collect impls in all unnamed const items. // const _: () = { ... }; for konst in module_data.scope.unnamed_consts() { let body = db.body(konst.into()); for (_, block_def_map) in body.blocks(db) { - collect(db, block_def_map, map); + collect(db, block_def_map, lang_items, map); } } } @@ -761,11 +781,15 @@ impl TraitImpls { }) } - pub fn for_trait_and_self_ty(&self, trait_: TraitId, self_ty: &SimplifiedType) -> &[ImplId] { + pub fn for_trait_and_self_ty( + &self, + trait_: TraitId, + self_ty: &SimplifiedType, + ) -> (&[ImplId], &[BuiltinDeriveImplId]) { self.map .get(&trait_) .and_then(|map| map.non_blanket_impls.get(self_ty)) - .map(|it| &**it) + .map(|it| (&*it.0, &*it.1)) .unwrap_or_default() } @@ -773,7 +797,7 @@ impl TraitImpls { if let Some(impls) = self.map.get(&trait_) { callback(&impls.blanket_impls); for impls in impls.non_blanket_impls.values() { - callback(impls); + callback(&impls.0); } } } @@ -781,7 +805,7 @@ impl TraitImpls { pub fn for_self_ty(&self, self_ty: &SimplifiedType, mut callback: impl FnMut(&[ImplId])) { for for_trait in self.map.values() { if let Some(for_ty) = for_trait.non_blanket_impls.get(self_ty) { - callback(for_ty); + callback(&for_ty.0); } } } |