diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index d6a561248565..4588a8548118 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -43,6 +43,7 @@ pub trait TyExt { /// If this is a `dyn Trait`, returns that trait. fn dyn_trait(&self) -> Option; + fn dyn_trait_ref(&self) -> Option; fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option>; fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option; @@ -193,6 +194,31 @@ impl TyExt for Ty { } } + fn dyn_trait_ref(&self) -> Option { + let trait_ref = match self.kind(Interner) { + // The principal trait bound should be the first element of the bounds. This is an + // invariant ensured by `TyLoweringContext::lower_dyn_trait()`. + // FIXME: dyn types may not have principal trait and we don't want to return auto trait + // here. + TyKind::Dyn(dyn_ty) => dyn_ty.bounds.as_ref().filter_map(|x| { + x.interned().get(0).and_then(|b| { + b.as_ref().filter_map(|b| match b { + WhereClause::Implemented(trait_ref) => Some(trait_ref.clone()), + _ => None, + }) + }) + }), + _ => None, + }?; + // FIXME: qualified bounds not handled (is not valid here I think?) + Some( + trait_ref + .substitute(Interner, &Substitution::from1(Interner, self.clone())) + .into_value_and_skipped_binders() + .0, + ) + } + fn dyn_trait(&self) -> Option { let trait_ref = match self.kind(Interner) { // The principal trait bound should be the first element of the bounds. This is an diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 64f37c761e96..957b2d91617f 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1483,10 +1483,44 @@ impl<'a> InferenceContext<'a> { method_name, ); let (receiver_ty, method_ty, substs) = match resolved { - Some((adjust, func, visible)) => { + Some((adjust, func, visible, subst)) => { let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty); let generics = generics(self.db.upcast(), func.into()); - let substs = self.substs_for_method_call(generics, generic_args); + let substs = match subst { + Some(s) => { + // FIXME: here we need the method subst, but result of `lookup_method` incorrectly returns the trait + // subst. For some traits (which their methods are not generic, and are not `dyn Trait`) this + // happens to be the same, so I didn't bothered myself to correctly implement it. Instead, I added + // this check and we ignore the returned subst if it doesn't match. + // + // It might be a good idea to keep this check even after fixing the above, and just add a `never!` to + // it, as mistakes will make chalk panic. But if you are sure about the implementation, you can remove + // it to save some performance. + let default_subst = self.substs_for_method_call(generics, generic_args); + let is_valid = 'b: { + if default_subst.len(Interner) != s.len(Interner) { + break 'b false; + } + default_subst.iter(Interner).zip(s.iter(Interner)).all(|(x, y)| { + matches!( + (x.data(Interner), y.data(Interner),), + (GenericArgData::Ty(_), GenericArgData::Ty(_)) + | ( + GenericArgData::Lifetime(_), + GenericArgData::Lifetime(_) + ) + | (GenericArgData::Const(_), GenericArgData::Const(_)) + ) + }) + }; + if is_valid { + s + } else { + default_subst + } + } + None => self.substs_for_method_call(generics, generic_args), + }; self.write_expr_adj(receiver, adjustments); self.write_method_resolution(tgt_expr, func, substs.clone()); if !visible { diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 368c3f65243d..e933c592738a 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -237,19 +237,19 @@ impl<'a> InferenceContext<'a> { VisibleFromModule::Filter(self.resolver.module()), Some(name), method_resolution::LookupMode::Path, - |_ty, item, visible| { + |_ty, item, visible, subst| { if visible { - Some((item, true)) + Some((item, true, subst)) } else { if not_visible.is_none() { - not_visible = Some((item, false)); + not_visible = Some((item, false, subst)); } None } }, ); let res = res.or(not_visible); - let (item, visible) = res?; + let (item, visible, substs) = res?; let (def, container) = match item { AssocItemId::FunctionId(f) => { @@ -258,7 +258,7 @@ impl<'a> InferenceContext<'a> { AssocItemId::ConstId(c) => (ValueNs::ConstId(c), c.lookup(self.db.upcast()).container), AssocItemId::TypeAliasId(_) => unreachable!(), }; - let substs = match container { + let substs = substs.unwrap_or_else(|| match container { ItemContainerId::ImplId(impl_id) => { let impl_substs = TyBuilder::subst_for_def(self.db, impl_id, None) .fill_with_inference_vars(&mut self.table) @@ -278,9 +278,9 @@ impl<'a> InferenceContext<'a> { } ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => { never!("assoc item contained in module/extern block"); - return None; + return Substitution::empty(Interner); } - }; + }); self.write_assoc_resolution(id, item, substs.clone()); if !visible { diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index b37fe1d63d5b..cc07c0b887b3 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1405,9 +1405,11 @@ pub(crate) fn generic_predicates_for_param_query( Some(TypeNs::TraitId(tr)) => tr, _ => return false, }; - - all_super_traits(db.upcast(), tr).iter().any(|tr| { - db.trait_data(*tr).items.iter().any(|(name, item)| { + let substs = TyBuilder::placeholder_subst(db, tr); + let tr_ref = + TraitRef { trait_id: to_chalk_trait_id(tr), substitution: substs }; + all_super_traits(db, tr_ref).iter().any(|tr| { + db.trait_data(tr.hir_trait_id()).items.iter().any(|(name, item)| { matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name }) }) @@ -1464,7 +1466,7 @@ pub(crate) fn trait_environment_query( for pred in resolver.where_predicates_in_scope() { for pred in ctx.lower_where_predicate(pred, false) { if let WhereClause::Implemented(tr) = &pred.skip_binders() { - traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id())); + traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.clone())); } let program_clause: chalk_ir::ProgramClause = pred.cast(Interner); clauses.push(program_clause.into_from_env_clause(Interner)); diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 740b6ddc27ab..822966374c0c 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -2,7 +2,7 @@ //! For details about how this works in rustc, see the method lookup page in the //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html) //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs. -use std::{ops::ControlFlow, sync::Arc}; +use std::{collections::hash_map::Entry, ops::ControlFlow, sync::Arc}; use base_db::{CrateId, Edition}; use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause}; @@ -463,7 +463,7 @@ pub(crate) fn lookup_method( traits_in_scope: &FxHashSet, visible_from_module: VisibleFromModule, name: &Name, -) -> Option<(ReceiverAdjustments, FunctionId, bool)> { +) -> Option<(ReceiverAdjustments, FunctionId, bool, Option)> { let mut not_visible = None; let res = iterate_method_candidates( ty, @@ -473,10 +473,10 @@ pub(crate) fn lookup_method( visible_from_module, Some(name), LookupMode::MethodCall, - |adjustments, f, visible| match f { - AssocItemId::FunctionId(f) if visible => Some((adjustments, f, true)), + |adjustments, f, visible, subst| match f { + AssocItemId::FunctionId(f) if visible => Some((adjustments, f, true, subst)), AssocItemId::FunctionId(f) if not_visible.is_none() => { - not_visible = Some((adjustments, f, false)); + not_visible = Some((adjustments, f, false, subst)); None } _ => None, @@ -600,7 +600,7 @@ pub(crate) fn iterate_method_candidates( visible_from_module: VisibleFromModule, name: Option<&Name>, mode: LookupMode, - mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option, + mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool, Option) -> Option, ) -> Option { let mut slot = None; iterate_method_candidates_dyn( @@ -611,9 +611,9 @@ pub(crate) fn iterate_method_candidates( visible_from_module, name, mode, - &mut |adj, item, visible| { + &mut |adj, item, visible, subst| { assert!(slot.is_none()); - if let Some(it) = callback(adj, item, visible) { + if let Some(it) = callback(adj, item, visible, subst) { slot = Some(it); return ControlFlow::Break(()); } @@ -858,7 +858,7 @@ pub fn iterate_path_candidates( name, LookupMode::Path, // the adjustments are not relevant for path lookup - &mut |_, id, _| callback(id), + &mut |_, id, _, _| callback(id), ) } @@ -870,7 +870,12 @@ pub fn iterate_method_candidates_dyn( visible_from_module: VisibleFromModule, name: Option<&Name>, mode: LookupMode, - callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, + callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, ) -> ControlFlow<()> { match mode { LookupMode::MethodCall => { @@ -934,7 +939,12 @@ fn iterate_method_candidates_with_autoref( traits_in_scope: &FxHashSet, visible_from_module: VisibleFromModule, name: Option<&Name>, - mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, + mut callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, ) -> ControlFlow<()> { if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) { // don't try to resolve methods on unknown types @@ -991,7 +1001,12 @@ fn iterate_method_candidates_by_receiver( traits_in_scope: &FxHashSet, visible_from_module: VisibleFromModule, name: Option<&Name>, - mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, + mut callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, ) -> ControlFlow<()> { let mut table = InferenceTable::new(db, env); let receiver_ty = table.instantiate_canonical(receiver_ty.clone()); @@ -1023,7 +1038,7 @@ fn iterate_method_candidates_by_receiver( name, Some(&receiver_ty), Some(receiver_adjustments.clone()), - &mut callback, + &mut |a1, a2, a3| callback(a1, a2, a3, None), )? } @@ -1037,7 +1052,12 @@ fn iterate_method_candidates_for_self_ty( traits_in_scope: &FxHashSet, visible_from_module: VisibleFromModule, name: Option<&Name>, - mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, + mut callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, ) -> ControlFlow<()> { let mut table = InferenceTable::new(db, env); let self_ty = table.instantiate_canonical(self_ty.clone()); @@ -1057,7 +1077,7 @@ fn iterate_method_candidates_for_self_ty( name, None, None, - callback, + &mut |a1, a2, a3| callback(a1, a2, a3, None), ) } @@ -1117,6 +1137,23 @@ fn iterate_trait_method_candidates( ControlFlow::Continue(()) } +/// When there is two bound with the same trait, for example `T: Into + Into`, we want to ignore subst in +/// of `Into` in method resolution for `T`. This function handle that. +fn unique_trait_refs( + trait_refs: impl Iterator, +) -> impl Iterator)> { + let mut result = FxHashMap::default(); + for trait_ref in trait_refs { + match result.entry(trait_ref.hir_trait_id()) { + Entry::Occupied(mut e) => *e.get_mut() = None, + Entry::Vacant(e) => { + e.insert(Some(trait_ref.substitution)); + } + } + } + result.into_iter() +} + fn iterate_inherent_methods( self_ty: &Ty, table: &mut InferenceTable<'_>, @@ -1124,7 +1161,12 @@ fn iterate_inherent_methods( receiver_ty: Option<&Ty>, receiver_adjustments: Option, visible_from_module: VisibleFromModule, - callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, + callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, ) -> ControlFlow<()> { let db = table.db; let env = table.trait_env.clone(); @@ -1136,9 +1178,10 @@ fn iterate_inherent_methods( match self_ty.kind(Interner) { TyKind::Placeholder(_) => { let env = table.trait_env.clone(); - let traits = env - .traits_in_scope_from_clauses(self_ty.clone()) - .flat_map(|t| all_super_traits(db.upcast(), t)); + let traits = unique_trait_refs( + env.traits_in_scope_from_clauses(self_ty.clone()) + .flat_map(|t| all_super_traits(db, t.clone())), + ); iterate_inherent_trait_methods( self_ty, table, @@ -1150,8 +1193,8 @@ fn iterate_inherent_methods( )?; } TyKind::Dyn(_) => { - if let Some(principal_trait) = self_ty.dyn_trait() { - let traits = all_super_traits(db.upcast(), principal_trait); + if let Some(principal_trait) = self_ty.dyn_trait_ref() { + let traits = unique_trait_refs(all_super_traits(db, principal_trait).into_iter()); iterate_inherent_trait_methods( self_ty, table, @@ -1159,7 +1202,7 @@ fn iterate_inherent_methods( receiver_ty, receiver_adjustments.clone(), callback, - traits.into_iter(), + traits, )?; } } @@ -1187,7 +1230,7 @@ fn iterate_inherent_methods( receiver_ty, receiver_adjustments.clone(), module, - callback, + &mut |a1, a2, a3| callback(a1, a2, a3, None), )?; } @@ -1207,7 +1250,7 @@ fn iterate_inherent_methods( receiver_ty, receiver_adjustments.clone(), module, - callback, + &mut |a1, a2, a3| callback(a1, a2, a3, None), )?; } return ControlFlow::Continue(()); @@ -1218,21 +1261,33 @@ fn iterate_inherent_methods( name: Option<&Name>, receiver_ty: Option<&Ty>, receiver_adjustments: Option, - callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, - traits: impl Iterator, + callback: &mut dyn FnMut( + ReceiverAdjustments, + AssocItemId, + bool, + Option, + ) -> ControlFlow<()>, + traits: impl Iterator)>, ) -> ControlFlow<()> { let db = table.db; for t in traits { - let data = db.trait_data(t); + let data = db.trait_data(t.0); for &(_, item) in data.items.iter() { // We don't pass `visible_from_module` as all trait items should be visible. + // FIXME: is_valid_candidate should consider subst let visible = match is_valid_candidate(table, name, receiver_ty, item, self_ty, None) { IsValidCandidate::Yes => true, IsValidCandidate::NotVisible => false, IsValidCandidate::No => continue, }; - callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?; + // FIXME: change this subst to be a method subst, not a trait + callback( + receiver_adjustments.clone().unwrap_or_default(), + item, + visible, + t.1.clone(), + )?; } } ControlFlow::Continue(()) diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs index f62a3cfabe89..ca5cfbd54111 100644 --- a/crates/hir-ty/src/tests/method_resolution.rs +++ b/crates/hir-ty/src/tests/method_resolution.rs @@ -949,6 +949,34 @@ fn test() { S2.into(); } ); } +#[test] +fn method_resolution_prefer_explicit_bound() { + check_types( + r#" +trait Tr { + fn tr(self) -> T; +} + +impl Tr for T { + fn tr(self) -> T { + self + } +} + +trait Tr2: Tr<&[T]> {} + +fn test0(x: T) { x.tr(); } + //^^^^^^ T +fn test1>(x: T) { x.tr(); } + //^^^^^^ i32 +fn test2>(x: T) { x.tr(); } + //^^^^^^ &[i32] +fn test3 + Tr>(x: T) { let x: i64 = x.tr(); } + //^^^^^^ i64 +"#, + ); +} + #[test] fn method_resolution_overloaded_method() { check_types( diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index 8bc38aca4722..5ceef7d35162 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -16,8 +16,8 @@ use stdx::panic_context; use crate::{ db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal, - Guidance, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, Solution, TraitRefExt, Ty, - TyKind, WhereClause, + Guidance, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, Solution, TraitRef, + TraitRefExt, Ty, TyKind, WhereClause, }; /// This controls how much 'time' we give the Chalk solver before giving up. @@ -47,7 +47,8 @@ pub struct TraitEnvironment { pub krate: CrateId, pub block: Option, // FIXME make this a BTreeMap - pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, + // Note this is not trivial, as `Ty` doesn't implement `Ord` currently. + pub(crate) traits_from_clauses: Vec<(Ty, TraitRef)>, pub env: chalk_ir::Environment, } @@ -61,10 +62,8 @@ impl TraitEnvironment { } } - pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator + '_ { - self.traits_from_clauses - .iter() - .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) + pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator + '_ { + self.traits_from_clauses.iter().filter(move |(self_ty, _)| *self_ty == ty).map(|(_, t)| t) } } diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 3b2a726688d0..0c2b614ba4ed 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -8,14 +8,9 @@ use chalk_ir::{cast::Cast, fold::Shift, BoundVar, DebruijnIndex, Mutability}; use either::Either; use hir_def::{ db::DefDatabase, - generics::{ - GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate, - WherePredicateTypeTarget, - }, + generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance}, hir::BindingAnnotation, lang_item::LangItem, - resolver::{HasResolver, TypeNs}, - type_ref::{TraitBoundModifier, TypeRef}, ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, }; @@ -41,16 +36,16 @@ pub(crate) fn fn_traits( /// Returns an iterator over the whole super trait hierarchy (including the /// trait itself). -pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> { +pub fn all_super_traits(db: &dyn HirDatabase, trait_: TraitRef) -> SmallVec<[TraitRef; 4]> { // we need to take care a bit here to avoid infinite loops in case of cycles // (i.e. if we have `trait A: B; trait B: A;`) - let mut result = smallvec![trait_]; + let mut result: SmallVec<[TraitRef; 4]> = smallvec![trait_]; let mut i = 0; - while let Some(&t) = result.get(i) { + while let Some(t) = result.get(i) { // yeah this is quadratic, but trait hierarchies should be flat // enough that this doesn't matter - direct_super_traits(db, t, |tt| { + direct_super_traits(db, t.clone(), |tt| { if !result.contains(&tt) { result.push(tt); } @@ -103,35 +98,19 @@ impl<'a> Iterator for SuperTraits<'a> { } } -fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) { - let resolver = trait_.resolver(db); +fn direct_super_traits(db: &dyn HirDatabase, trait_ref: TraitRef, cb: impl FnMut(TraitRef)) { + let trait_ = trait_ref.hir_trait_id(); let generic_params = db.generic_params(trait_.into()); - let trait_self = generic_params.find_trait_self_param(); - generic_params - .where_predicates + let Some(trait_self) = generic_params.find_trait_self_param() else { + return; + }; + let trait_self_id = TypeOrConstParamId { parent: trait_.into(), local_id: trait_self }; + let bounds = db.generic_predicates_for_param(trait_.into(), trait_self_id, None); + bounds .iter() - .filter_map(|pred| match pred { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound } => { - let is_trait = match target { - WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref { - TypeRef::Path(p) => p.is_self_type(), - _ => false, - }, - WherePredicateTypeTarget::TypeOrConstParam(local_id) => { - Some(*local_id) == trait_self - } - }; - match is_trait { - true => bound.as_path(), - false => None, - } - } - WherePredicate::Lifetime { .. } => None, - }) - .filter(|(_, bound_modifier)| matches!(bound_modifier, TraitBoundModifier::None)) - .filter_map(|(path, _)| match resolver.resolve_path_in_type_ns_fully(db, path) { - Some(TypeNs::TraitId(t)) => Some(t), + .map(|x| x.clone().substitute(Interner, &trait_ref.substitution)) + .filter_map(|x| match x.skip_binders() { + chalk_ir::WhereClause::Implemented(t) => Some(t.clone()), _ => None, }) .for_each(cb); diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index db923cb0fe23..c08ee0008ac0 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -65,6 +65,7 @@ use hir_ty::{ method_resolution::{self, TyFingerprint}, mir::{self, interpret_mir}, primitive::UintTy, + to_chalk_trait_id, traits::FnTrait, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution, @@ -2045,8 +2046,11 @@ impl Trait { } pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec { - let traits = all_super_traits(db.upcast(), self.into()); - traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect() + let tr = self.into(); + let substs = TyBuilder::placeholder_subst(db, tr); + let tr_ref = hir_ty::TraitRef { trait_id: to_chalk_trait_id(tr), substitution: substs }; + let traits = all_super_traits(db, tr_ref); + traits.iter().flat_map(|tr| Trait::from(tr.hir_trait_id()).items(db)).collect() } pub fn is_auto(self, db: &dyn HirDatabase) -> bool { @@ -3733,7 +3737,7 @@ impl Type { with_local_impls.and_then(|b| b.id.containing_block()).into(), name, method_resolution::LookupMode::MethodCall, - &mut |_adj, id, _| callback(id), + &mut |_adj, id, _, _| callback(id), ); } @@ -3814,8 +3818,9 @@ impl Type { ) -> impl Iterator + 'a { let _p = profile::span("applicable_inherent_traits"); self.autoderef_(db) - .filter_map(|ty| ty.dyn_trait()) - .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) + .filter_map(|ty| ty.dyn_trait_ref()) + .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db, dyn_trait_id)) + .map(|x| x.hir_trait_id()) .map(Trait::from) } @@ -3826,8 +3831,9 @@ impl Type { .flat_map(|ty| { self.env .traits_in_scope_from_clauses(ty) - .flat_map(|t| hir_ty::all_super_traits(db.upcast(), t)) + .flat_map(|t| hir_ty::all_super_traits(db, t.clone())) }) + .map(|x| x.hir_trait_id()) .map(Trait::from) }