Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 912 |
1 files changed, 435 insertions, 477 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 5789bf02a4..7259099107 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -13,19 +13,23 @@ use std::{cell::OnceCell, iter, mem}; use arrayvec::ArrayVec; use either::Either; use hir_def::{ - AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, - LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, - TypeOrConstParamId, TypeParamId, UnionId, VariantId, + AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId, + ExpressionStoreOwnerId, FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule, + ImplId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId, + TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId, builtin_type::BuiltinType, expr_store::{ExpressionStore, HygieneId, path::Path}, hir::generics::{ - GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, + GenericParamDataRef, GenericParams, TypeOrConstParamData, TypeParamProvenance, + WherePredicate, }, item_tree::FieldsShape, lang_item::LangItems, resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs}, - signatures::{FunctionSignature, TraitFlags, TypeAliasFlags}, + signatures::{ + ConstSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature, + TraitFlags, TraitSignature, TypeAliasFlags, TypeAliasSignature, + }, type_ref::{ ConstRef, FnType, LifetimeRefId, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, @@ -36,27 +40,22 @@ use la_arena::{Arena, ArenaMap, Idx}; use path::{PathDiagnosticCallback, PathLoweringContext}; use rustc_ast_ir::Mutability; use rustc_hash::FxHashSet; -use rustc_pattern_analysis::Captures; use rustc_type_ir::{ AliasTyKind, BoundVarIndexKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, - TyKind::{self}, - TypeFoldable, TypeVisitableExt, Upcast, UpcastFrom, elaborate, - inherent::{ - Clause as _, GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, - Ty as _, - }, + TyKind, TypeFoldable, TypeVisitableExt, Upcast, UpcastFrom, elaborate, + inherent::{Clause as _, GenericArgs as _, IntoKind as _, Region as _, Ty as _}, }; -use smallvec::{SmallVec, smallvec}; +use smallvec::SmallVec; use stdx::{impl_from, never}; use tracing::debug; use triomphe::{Arc, ThinArc}; use crate::{ - FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, all_super_traits, + FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, consteval::intern_const_ref, db::{HirDatabase, InternedOpaqueTyId}, - generics::{Generics, generics, trait_self_param_idx}, + generics::{Generics, generics}, next_solver::{ AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FxIndexMap, GenericArg, @@ -182,7 +181,7 @@ pub struct TyLoweringContext<'db, 'a> { resolver: &'a Resolver<'db>, store: &'a ExpressionStore, def: GenericDefId, - generics: OnceCell<Generics>, + generics: OnceCell<Generics<'db>>, in_binders: DebruijnIndex, impl_trait_mode: ImplTraitLoweringState, /// Tracks types with explicit `?Sized` bounds. @@ -283,11 +282,12 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> { - let const_ref = &self.store[const_ref.expr]; - match const_ref { - hir_def::hir::Expr::Path(path) => { - self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) - } + let expr_id = const_ref.expr; + let expr = &self.store[expr_id]; + match expr { + hir_def::hir::Expr::Path(path) => self + .path_to_const(path) + .unwrap_or_else(|| Const::new(self.interner, ConstKind::Error(ErrorGuaranteed))), hir_def::hir::Expr::Literal(literal) => { intern_const_ref(self.db, literal, const_type, self.resolver.krate()) } @@ -304,20 +304,74 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.resolver.krate(), ) } else { - unknown_const(const_type) + Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)) } } // For unsigned integers, chars, bools, etc., negation is not meaningful - _ => unknown_const(const_type), + _ => Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)), } } else { - unknown_const(const_type) + // Complex negation expression (e.g. `-N` where N is a const param) + self.lower_const_as_unevaluated(expr_id, const_type) } } - _ => unknown_const(const_type), + hir_def::hir::Expr::Underscore => { + Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)) + } + // Any other complex expression becomes an unevaluated anonymous const. + _ => self.lower_const_as_unevaluated(expr_id, const_type), } } + /// Lower a complex const expression to an `UnevaluatedConst` backed by an `AnonConstId`. + /// + /// The `expected_ty_ref` is `None` for array lengths (implicitly `usize`) or + /// `Some(type_ref_id)` for const generic arguments where the expected type comes + /// from the const parameter declaration. + fn lower_const_as_unevaluated( + &mut self, + _expr: hir_def::hir::ExprId, + _expected_ty: Ty<'db>, + ) -> Const<'db> { + // /// Build the identity generic args for the current generic context. + // /// + // /// This maps each generic parameter to itself (as a `ParamTy`, `ParamConst`, + // /// or `EarlyParamRegion`), which is the correct substitution when creating + // /// an `UnevaluatedConst` during type lowering — the anon const inherits the + // /// parent's generics and they haven't been substituted yet. + // fn current_generic_args(&self) -> GenericArgs<'db> { + // let generics = self.generics(); + // let interner = self.interner; + // GenericArgs::new_from_iter( + // interner, + // generics.iter_id().enumerate().map(|(index, id)| match id { + // GenericParamId::TypeParamId(id) => { + // GenericArg::from(Ty::new_param(interner, id, index as u32)) + // } + // GenericParamId::ConstParamId(id) => GenericArg::from(Const::new_param( + // interner, + // ParamConst { id, index: index as u32 }, + // )), + // GenericParamId::LifetimeParamId(id) => GenericArg::from(Region::new_early_param( + // interner, + // EarlyParamRegion { id, index: index as u32 }, + // )), + // }), + // ) + // } + // let loc = AnonConstLoc { owner: self.def, expr }; + // let id = loc.intern(self.db); + // let args = self.current_generic_args(); + // Const::new( + // self.interner, + // ConstKind::Unevaluated(UnevaluatedConst::new( + // GeneralConstId::AnonConstId(id).into(), + // args, + // )), + // ) + Const::new(self.interner, ConstKind::Error(ErrorGuaranteed)) + } + pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> { match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) { Some(ValueNs::GenericParam(p)) => { @@ -353,7 +407,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) } - fn generics(&self) -> &Generics { + fn generics(&self) -> &Generics<'db> { self.generics.get_or_init(|| generics(self.db, self.def)) } @@ -618,33 +672,12 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { &'b mut self, where_predicate: &'b WherePredicate, ignore_bindings: bool, - generics: &Generics, - predicate_filter: PredicateFilter, ) -> impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'db> { match where_predicate { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound } => { - if let PredicateFilter::SelfTrait = predicate_filter { - let target_type = &self.store[*target]; - let self_type = 'is_self: { - if let TypeRef::Path(path) = target_type - && path.is_self_type() - { - break 'is_self true; - } - if let TypeRef::TypeParam(param) = target_type - && generics[param.local_id()].is_trait_self() - { - break 'is_self true; - } - false - }; - if !self_type { - return Either::Left(Either::Left(iter::empty())); - } - } let self_ty = self.lower_ty(*target); - Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings))) + Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings)) } &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(( Clause(Predicate::new( @@ -752,7 +785,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { match b.kind().skip_binder() { rustc_type_ir::ClauseKind::Trait(t) => { let id = t.def_id(); - let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); + let is_auto = + TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO); if is_auto { auto_traits.push(t.def_id().0); } else { @@ -831,6 +865,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { let mut ordered_associated_types = vec![]; if let Some(principal_trait) = principal { + // Generally we should not elaborate in lowering as this can lead to cycles, but + // here rustc cycles as well. for clause in elaborate::elaborate( interner, [Clause::upcast_from( @@ -1134,7 +1170,7 @@ pub(crate) fn impl_trait_with_diagnostics<'db>( db: &'db dyn HirDatabase, impl_id: ImplId, ) -> Option<(StoredEarlyBinder<(TraitId, StoredGenericArgs)>, Diagnostics)> { - let impl_data = db.impl_signature(impl_id); + let impl_data = ImplSignature::of(db, impl_id); let resolver = impl_id.resolver(db); let mut ctx = TyLoweringContext::new( db, @@ -1219,7 +1255,7 @@ impl ImplTraits { def: hir_def::FunctionId, ) -> Option<Box<StoredEarlyBinder<ImplTraits>>> { // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe - let data = db.function_signature(def); + let data = FunctionSignature::of(db, def); let resolver = def.resolver(db); let mut ctx_ret = TyLoweringContext::new( db, @@ -1247,7 +1283,7 @@ impl ImplTraits { db: &dyn HirDatabase, def: hir_def::TypeAliasId, ) -> Option<Box<StoredEarlyBinder<ImplTraits>>> { - let data = db.type_alias_signature(def); + let data = TypeAliasSignature::of(db, def); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, @@ -1337,7 +1373,7 @@ fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<Store /// Build the declared type of a const. fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<StoredTy> { let resolver = def.resolver(db); - let data = db.const_signature(def); + let data = ConstSignature::of(db, def); let parent = def.loc(db).container; let mut ctx = TyLoweringContext::new( db, @@ -1353,7 +1389,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> StoredEarlyBinder<Store /// Build the declared type of a static. fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> StoredEarlyBinder<StoredTy> { let resolver = def.resolver(db); - let data = db.static_signature(def); + let data = StaticSignature::of(db, def); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1370,7 +1406,7 @@ fn type_for_struct_constructor( db: &dyn HirDatabase, def: StructId, ) -> Option<StoredEarlyBinder<StoredTy>> { - let struct_data = db.struct_signature(def); + let struct_data = StructSignature::of(db, def); match struct_data.shape { FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.into())), @@ -1445,7 +1481,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics<'db>( db: &'db dyn HirDatabase, t: TypeAliasId, ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) { - let type_alias_data = db.type_alias_signature(t); + let type_alias_data = TypeAliasSignature::of(db, t); let mut diags = None; let resolver = t.resolver(db); let interner = DbInterner::new_no_crate(db); @@ -1508,7 +1544,7 @@ pub(crate) fn impl_self_ty_with_diagnostics<'db>( ) -> (StoredEarlyBinder<StoredTy>, Diagnostics) { let resolver = impl_id.resolver(db); - let impl_data = db.impl_signature(impl_id); + let impl_data = ImplSignature::of(db, impl_id); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1554,14 +1590,14 @@ pub(crate) fn const_param_ty_with_diagnostics<'db>( _: (), def: ConstParamId, ) -> (StoredTy, Diagnostics) { - let (parent_data, store) = db.generic_params_and_store(def.parent()); + let (parent_data, store) = GenericParams::with_store(db, def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db); let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, - &store, + store, def.parent(), LifetimeElisionKind::AnonymousReportError, ); @@ -1624,6 +1660,98 @@ pub(crate) fn field_types_with_diagnostics_query<'db>( (res, create_diagnostics(ctx.diagnostics)) } +#[derive(Debug, PartialEq, Eq, Default)] +pub(crate) struct SupertraitsInfo { + /// This includes the trait itself. + pub(crate) all_supertraits: Box<[TraitId]>, + pub(crate) direct_supertraits: Box<[TraitId]>, + pub(crate) defined_assoc_types: Box<[(Name, TypeAliasId)]>, +} + +impl SupertraitsInfo { + #[inline] + pub(crate) fn query(db: &dyn HirDatabase, trait_: TraitId) -> &Self { + return supertraits_info(db, trait_); + + #[salsa::tracked(returns(ref), cycle_result = supertraits_info_cycle)] + fn supertraits_info(db: &dyn HirDatabase, trait_: TraitId) -> SupertraitsInfo { + let mut all_supertraits = FxHashSet::default(); + let mut direct_supertraits = FxHashSet::default(); + let mut defined_assoc_types = FxHashSet::default(); + + all_supertraits.insert(trait_); + defined_assoc_types.extend(trait_.trait_items(db).items.iter().filter_map( + |(name, id)| match *id { + AssocItemId::TypeAliasId(id) => Some((name.clone(), id)), + _ => None, + }, + )); + + let resolver = trait_.resolver(db); + let signature = TraitSignature::of(db, trait_); + for pred in signature.generic_params.where_predicates() { + let (WherePredicate::TypeBound { target, bound } + | WherePredicate::ForLifetime { lifetimes: _, target, bound }) = pred + else { + continue; + }; + let (TypeBound::Path(bounded_trait, TraitBoundModifier::None) + | TypeBound::ForLifetime(_, bounded_trait)) = *bound + else { + continue; + }; + let target = &signature.store[*target]; + match target { + TypeRef::TypeParam(param) + if param.local_id() == GenericParams::SELF_PARAM_ID_IN_SELF => {} + TypeRef::Path(path) if path.is_self_type() => {} + _ => continue, + } + let Some(TypeNs::TraitId(bounded_trait)) = + resolver.resolve_path_in_type_ns_fully(db, &signature.store[bounded_trait]) + else { + continue; + }; + let SupertraitsInfo { + all_supertraits: bounded_trait_all_supertraits, + direct_supertraits: _, + defined_assoc_types: bounded_traits_defined_assoc_types, + } = SupertraitsInfo::query(db, bounded_trait); + all_supertraits.extend(bounded_trait_all_supertraits); + direct_supertraits.insert(bounded_trait); + defined_assoc_types.extend(bounded_traits_defined_assoc_types.iter().cloned()); + } + + SupertraitsInfo { + all_supertraits: Box::from_iter(all_supertraits), + direct_supertraits: Box::from_iter(direct_supertraits), + defined_assoc_types: Box::from_iter(defined_assoc_types), + } + } + + fn supertraits_info_cycle( + _db: &dyn HirDatabase, + _: salsa::Id, + _trait_: TraitId, + ) -> SupertraitsInfo { + SupertraitsInfo::default() + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum AssocTypeShorthandResolution { + Resolved(StoredEarlyBinder<(TypeAliasId, StoredGenericArgs)>), + Ambiguous { + /// If one resolution belongs to a sub-trait and one to a supertrait, this contains + /// the sub-trait's resolution. This can be `None` if there is no trait inheritance + /// relationship between the resolutions. + sub_trait_resolution: Option<StoredEarlyBinder<(TypeAliasId, StoredGenericArgs)>>, + }, + NotFound, + Cycle, +} + /// Predicates for `param_id` of the form `P: SomeTrait`. If /// `assoc_name` is provided, only return predicates referencing traits /// that have an associated type of that name. @@ -1638,15 +1766,14 @@ pub(crate) fn field_types_with_diagnostics_query<'db>( /// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. #[tracing::instrument(skip(db), ret)] -#[salsa::tracked(returns(ref), cycle_result = generic_predicates_for_param_cycle_result)] -pub(crate) fn generic_predicates_for_param<'db>( - db: &'db dyn HirDatabase, +#[salsa::tracked(returns(ref), cycle_result = resolve_type_param_assoc_type_shorthand_cycle_result)] +fn resolve_type_param_assoc_type_shorthand( + db: &dyn HirDatabase, def: GenericDefId, - param_id: TypeOrConstParamId, - assoc_name: Option<Name>, -) -> StoredEarlyBinder<StoredClauses> { + param: TypeParamId, + assoc_name: Name, +) -> AssocTypeShorthandResolution { let generics = generics(db, def); - let interner = DbInterner::new_no_crate(db); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, @@ -1655,128 +1782,138 @@ pub(crate) fn generic_predicates_for_param<'db>( def, LifetimeElisionKind::AnonymousReportError, ); + let interner = ctx.interner; + let param_ty = Ty::new_param( + interner, + param, + generics.type_or_const_param_idx(param.into()).unwrap() as u32, + ); - // we have to filter out all other predicates *first*, before attempting to lower them - let has_relevant_bound = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound, .. } => { - let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) }; - if invalid_target { - // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented - // sized-hierarchy correctly. - // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into - // `ctx.unsized_types` - let lower = || -> bool { - match bound { - TypeBound::Path(_, TraitBoundModifier::Maybe) => true, - TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => { - let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { - return false; - }; - let Some(pointee_sized) = ctx.lang_items.PointeeSized else { - return false; - }; - // Lower the path directly with `Resolver` instead of PathLoweringContext` - // to prevent diagnostics duplications. - ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and( - |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized), - ) - } - _ => false, - } - }(); - if lower { - ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All) - .for_each(drop); - } - return false; - } - - match bound { - &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { - // Only lower the bound if the trait could possibly define the associated - // type we're looking for. - let path = &ctx.store[path]; - - let Some(assoc_name) = &assoc_name else { return true }; - let Some(TypeNs::TraitId(tr)) = - resolver.resolve_path_in_type_ns_fully(db, path) - else { - return false; - }; - - trait_or_supertrait_has_assoc_type(db, tr, assoc_name) - } - TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false, - } + let mut this_trait_resolution = None; + if let GenericDefId::TraitId(containing_trait) = param.parent() + && param.local_id() == GenericParams::SELF_PARAM_ID_IN_SELF + { + // Add the trait's own associated types. + if let Some(assoc_type) = + containing_trait.trait_items(db).associated_type_by_name(&assoc_name) + { + let args = GenericArgs::identity_for_item(interner, containing_trait.into()); + this_trait_resolution = Some(StoredEarlyBinder::bind((assoc_type, args.store()))); } - WherePredicate::Lifetime { .. } => false, - }; - let mut predicates = Vec::new(); + } + + let mut supertraits_resolution = None; for maybe_parent_generics in std::iter::successors(Some(&generics), |generics| generics.parent_generics()) { ctx.store = maybe_parent_generics.store(); for pred in maybe_parent_generics.where_predicates() { - if has_relevant_bound(pred, &mut ctx) { - predicates.extend( - ctx.lower_where_predicate( - pred, - true, - maybe_parent_generics, - PredicateFilter::All, - ) - .map(|(pred, _)| pred), - ); + let (WherePredicate::TypeBound { target, bound } + | WherePredicate::ForLifetime { lifetimes: _, target, bound }) = pred + else { + continue; + }; + let (TypeBound::Path(bounded_trait_path, TraitBoundModifier::None) + | TypeBound::ForLifetime(_, bounded_trait_path)) = *bound + else { + continue; + }; + let Some(target) = ctx.lower_ty_only_param(*target) else { continue }; + if target != param.into() { + continue; + } + let Some(TypeNs::TraitId(bounded_trait)) = + resolver.resolve_path_in_type_ns_fully(db, &ctx.store[bounded_trait_path]) + else { + continue; + }; + if !SupertraitsInfo::query(db, bounded_trait) + .defined_assoc_types + .iter() + .any(|(name, _)| *name == assoc_name) + { + continue; + } + + let Some((bounded_trait_ref, _)) = + ctx.lower_trait_ref_from_path(bounded_trait_path, param_ty) + else { + continue; + }; + // Now, search from the start on the *bounded* trait like if we wrote `Self::Assoc`. Eventually, we'll get + // the correct trait ref (or a cycle). + let lookup_on_bounded_trait = resolve_type_param_assoc_type_shorthand( + db, + bounded_trait.into(), + TypeParamId::trait_self(bounded_trait), + assoc_name.clone(), + ); + let assoc_type_and_args = match &lookup_on_bounded_trait { + AssocTypeShorthandResolution::Resolved(trait_ref) => trait_ref, + AssocTypeShorthandResolution::Ambiguous { + sub_trait_resolution: Some(trait_ref), + } => trait_ref, + AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: None } => { + return AssocTypeShorthandResolution::Ambiguous { + sub_trait_resolution: this_trait_resolution, + }; + } + AssocTypeShorthandResolution::NotFound => { + never!("we checked that the trait defines this assoc type"); + continue; + } + AssocTypeShorthandResolution::Cycle => return AssocTypeShorthandResolution::Cycle, + }; + let (assoc_type, args) = assoc_type_and_args + .get_with(|(assoc_type, args)| (*assoc_type, args.as_ref())) + .skip_binder(); + let args = EarlyBinder::bind(args).instantiate(interner, bounded_trait_ref.args); + let current_result = StoredEarlyBinder::bind((assoc_type, args.store())); + if let Some(this_trait_resolution) = this_trait_resolution { + return AssocTypeShorthandResolution::Ambiguous { + sub_trait_resolution: Some(this_trait_resolution), + }; + } else if let Some(prev_resolution) = &supertraits_resolution { + if let AssocTypeShorthandResolution::Ambiguous { + sub_trait_resolution: Some(prev_resolution), + } + | AssocTypeShorthandResolution::Resolved(prev_resolution) = prev_resolution + && *prev_resolution == current_result + { + continue; + } else { + return AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: None }; + } + } else { + supertraits_resolution = Some(match lookup_on_bounded_trait { + AssocTypeShorthandResolution::Resolved(_) => { + AssocTypeShorthandResolution::Resolved(current_result) + } + AssocTypeShorthandResolution::Ambiguous { .. } => { + AssocTypeShorthandResolution::Ambiguous { + sub_trait_resolution: Some(current_result), + } + } + AssocTypeShorthandResolution::NotFound + | AssocTypeShorthandResolution::Cycle => unreachable!(), + }); } } } - let args = GenericArgs::identity_for_item(interner, def.into()); - if !args.is_empty() { - let explicitly_unsized_tys = ctx.unsized_types; - if let Some(implicitly_sized_predicates) = implicitly_sized_clauses( - db, - ctx.lang_items, - param_id.parent, - &explicitly_unsized_tys, - &args, - ) { - predicates.extend(implicitly_sized_predicates); - }; - } - StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()) + supertraits_resolution + .or_else(|| this_trait_resolution.map(AssocTypeShorthandResolution::Resolved)) + .unwrap_or(AssocTypeShorthandResolution::NotFound) } -pub(crate) fn generic_predicates_for_param_cycle_result( - db: &dyn HirDatabase, +fn resolve_type_param_assoc_type_shorthand_cycle_result( + _db: &dyn HirDatabase, _: salsa::Id, _def: GenericDefId, - _param_id: TypeOrConstParamId, - _assoc_name: Option<Name>, -) -> StoredEarlyBinder<StoredClauses> { - StoredEarlyBinder::bind(Clauses::empty(DbInterner::new_no_crate(db)).store()) -} - -/// Check if this trait or any of its supertraits define an associated -/// type with the given name. -fn trait_or_supertrait_has_assoc_type( - db: &dyn HirDatabase, - tr: TraitId, - assoc_name: &Name, -) -> bool { - for trait_id in all_super_traits(db, tr) { - if trait_id - .trait_items(db) - .items - .iter() - .any(|(name, item)| matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name) - { - return true; - } - } - - false + _param: TypeParamId, + _assoc_name: Name, +) -> AssocTypeShorthandResolution { + AssocTypeShorthandResolution::Cycle } #[inline] @@ -1822,7 +1959,7 @@ fn type_alias_bounds_with_diagnostics<'db>( db: &'db dyn HirDatabase, type_alias: TypeAliasId, ) -> (TypeAliasBounds<StoredEarlyBinder<StoredClauses>>, Diagnostics) { - let type_alias_data = db.type_alias_signature(type_alias); + let type_alias_data = TypeAliasSignature::of(db, type_alias); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); let mut ctx = TyLoweringContext::new( db, @@ -1897,15 +2034,29 @@ impl<'db> GenericPredicates { /// Resolve the where clause(s) of an item with generics. /// /// Diagnostics are computed only for this item's predicates, not for parents. - #[salsa::tracked(returns(ref))] + #[salsa::tracked(returns(ref), cycle_result=generic_predicates_cycle_result)] pub fn query_with_diagnostics( db: &'db dyn HirDatabase, def: GenericDefId, ) -> (GenericPredicates, Diagnostics) { - generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true) + generic_predicates(db, def) } } +/// A cycle can occur from malformed code. +fn generic_predicates_cycle_result( + _db: &dyn HirDatabase, + _: salsa::Id, + _def: GenericDefId, +) -> (GenericPredicates, Diagnostics) { + ( + GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind( + Clauses::default().store(), + )), + None, + ) +} + impl GenericPredicates { #[inline] pub(crate) fn from_explicit_own_predicates( @@ -1987,16 +2138,6 @@ impl GenericPredicates { } } -pub(crate) fn trait_environment_for_body_query( - db: &dyn HirDatabase, - def: DefWithBodyId, -) -> ParamEnv<'_> { - let Some(def) = def.as_generic_def_id(db) else { - return ParamEnv::empty(); - }; - db.trait_environment(def) -} - pub(crate) fn param_env_from_predicates<'db>( interner: DbInterner<'db>, predicates: &'db GenericPredicates, @@ -2011,7 +2152,12 @@ pub(crate) fn param_env_from_predicates<'db>( ParamEnv { clauses } } -pub(crate) fn trait_environment<'db>(db: &'db dyn HirDatabase, def: GenericDefId) -> ParamEnv<'db> { +pub(crate) fn trait_environment<'db>( + db: &'db dyn HirDatabase, + def: ExpressionStoreOwnerId, +) -> ParamEnv<'db> { + let def = def.generic_def(db); + return ParamEnv { clauses: trait_environment_query(db, def).as_ref() }; #[salsa::tracked(returns(ref))] @@ -2026,24 +2172,10 @@ pub(crate) fn trait_environment<'db>(db: &'db dyn HirDatabase, def: GenericDefId } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(crate) enum PredicateFilter { - SelfTrait, - All, -} - /// Resolve the where clause(s) of an item with generics, /// with a given filter -#[tracing::instrument(skip(db, filter), ret)] -pub(crate) fn generic_predicates_filtered_by<F>( - db: &dyn HirDatabase, - def: GenericDefId, - predicate_filter: PredicateFilter, - filter: F, -) -> (GenericPredicates, Diagnostics) -where - F: Fn(GenericDefId) -> bool, -{ +#[tracing::instrument(skip(db), ret)] +fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredicates, Diagnostics) { let generics = generics(db, def); let resolver = def.resolver(db); let interner = DbInterner::new_no_crate(db); @@ -2065,9 +2197,9 @@ where let all_generics = std::iter::successors(Some(&generics), |generics| generics.parent_generics()) .collect::<ArrayVec<_, 2>>(); - let own_implicit_trait_predicate = implicit_trait_predicate(interner, def, predicate_filter); + let own_implicit_trait_predicate = implicit_trait_predicate(interner, def); let parent_implicit_trait_predicate = if all_generics.len() > 1 { - implicit_trait_predicate(interner, all_generics.last().unwrap().def(), predicate_filter) + implicit_trait_predicate(interner, all_generics.last().unwrap().def()) } else { None }; @@ -2075,97 +2207,85 @@ where // Collect only diagnostics from the child, not including parents. ctx.diagnostics.clear(); - if filter(maybe_parent_generics.def()) { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - tracing::debug!(?pred); - for (pred, source) in - ctx.lower_where_predicate(pred, false, maybe_parent_generics, predicate_filter) - { - match source { - GenericPredicateSource::SelfOnly => { - if maybe_parent_generics.def() == def { - own_predicates.push(pred); - } else { - parent_predicates.push(pred); - } + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + tracing::debug!(?pred); + for (pred, source) in ctx.lower_where_predicate(pred, false) { + match source { + GenericPredicateSource::SelfOnly => { + if maybe_parent_generics.def() == def { + own_predicates.push(pred); + } else { + parent_predicates.push(pred); } - GenericPredicateSource::AssocTyBound => { - if maybe_parent_generics.def() == def { - own_assoc_ty_bounds.push(pred); - } else { - parent_assoc_ty_bounds.push(pred); - } + } + GenericPredicateSource::AssocTyBound => { + if maybe_parent_generics.def() == def { + own_assoc_ty_bounds.push(pred); + } else { + parent_assoc_ty_bounds.push(pred); } } } } + } - if maybe_parent_generics.def() == def { - push_const_arg_has_type_predicates(db, &mut own_predicates, maybe_parent_generics); - } else { - push_const_arg_has_type_predicates( - db, - &mut parent_predicates, - maybe_parent_generics, - ); - } + if maybe_parent_generics.def() == def { + push_const_arg_has_type_predicates(db, &mut own_predicates, maybe_parent_generics); + } else { + push_const_arg_has_type_predicates(db, &mut parent_predicates, maybe_parent_generics); + } - if let Some(sized_trait) = sized_trait { - let mut add_sized_clause = |param_idx, param_id, param_data| { - let ( - GenericParamId::TypeParamId(param_id), - GenericParamDataRef::TypeParamData(param_data), - ) = (param_id, param_data) - else { - return; - }; + if let Some(sized_trait) = sized_trait { + let mut add_sized_clause = |param_idx, param_id, param_data| { + let ( + GenericParamId::TypeParamId(param_id), + GenericParamDataRef::TypeParamData(param_data), + ) = (param_id, param_data) + else { + return; + }; - if param_data.provenance == TypeParamProvenance::TraitSelf { - return; - } + if param_data.provenance == TypeParamProvenance::TraitSelf { + return; + } - let param_ty = Ty::new_param(interner, param_id, param_idx); - if ctx.unsized_types.contains(¶m_ty) { - return; - } - let trait_ref = TraitRef::new_from_args( - interner, - sized_trait.into(), - GenericArgs::new_from_slice(&[param_ty.into()]), - ); - let clause = Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )); - if maybe_parent_generics.def() == def { - own_predicates.push(clause); - } else { - parent_predicates.push(clause); - } - }; - let parent_params_len = maybe_parent_generics.len_parent(); - maybe_parent_generics.iter_self().enumerate().for_each( - |(param_idx, (param_id, param_data))| { - add_sized_clause( - (param_idx + parent_params_len) as u32, - param_id, - param_data, - ); - }, + let param_ty = Ty::new_param(interner, param_id, param_idx); + if ctx.unsized_types.contains(¶m_ty) { + return; + } + let trait_ref = TraitRef::new_from_args( + interner, + sized_trait.into(), + GenericArgs::new_from_slice(&[param_ty.into()]), ); - } - - // We do not clear `ctx.unsized_types`, as the `?Sized` clause of a child (e.g. an associated type) can - // be declared on the parent (e.g. the trait). It is nevertheless fine to register the implicit `Sized` - // predicates before lowering the child, as a child cannot define a `?Sized` predicate for its parent. - // But we do have to lower the parent first. + let clause = Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + )); + if maybe_parent_generics.def() == def { + own_predicates.push(clause); + } else { + parent_predicates.push(clause); + } + }; + let parent_params_len = maybe_parent_generics.len_parent(); + maybe_parent_generics.iter_self().enumerate().for_each( + |(param_idx, (param_id, param_data))| { + add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data); + }, + ); } + + // We do not clear `ctx.unsized_types`, as the `?Sized` clause of a child (e.g. an associated type) can + // be declared on the parent (e.g. the trait). It is nevertheless fine to register the implicit `Sized` + // predicates before lowering the child, as a child cannot define a `?Sized` predicate for its parent. + // But we do have to lower the parent first. } let diagnostics = create_diagnostics(ctx.diagnostics); @@ -2213,7 +2333,6 @@ where fn implicit_trait_predicate<'db>( interner: DbInterner<'db>, def: GenericDefId, - predicate_filter: PredicateFilter, ) -> Option<Clause<'db>> { // For traits, add `Self: Trait` predicate. This is // not part of the predicates that a user writes, but it @@ -2227,9 +2346,7 @@ where // prove that the trait applies to the types that were // used, and adding the predicate into this list ensures // that this is done. - if let GenericDefId::TraitId(def_id) = def - && predicate_filter == PredicateFilter::All - { + if let GenericDefId::TraitId(def_id) = def { Some(TraitRef::identity(interner, def_id.into()).upcast(interner)) } else { None @@ -2240,7 +2357,7 @@ where fn push_const_arg_has_type_predicates<'db>( db: &'db dyn HirDatabase, predicates: &mut Vec<Clause<'db>>, - generics: &Generics, + generics: &Generics<'db>, ) { let interner = DbInterner::new_no_crate(db); let const_params_offset = generics.len_parent() + generics.len_lifetimes_self(); @@ -2266,49 +2383,6 @@ fn push_const_arg_has_type_predicates<'db>( } } -/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. -/// Exception is Self of a trait def. -fn implicitly_sized_clauses<'a, 'subst, 'db>( - db: &'db dyn HirDatabase, - lang_items: &LangItems, - def: GenericDefId, - explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>, - args: &'subst GenericArgs<'db>, -) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> { - let interner = DbInterner::new_no_crate(db); - let sized_trait = lang_items.Sized?; - - let trait_self_idx = trait_self_param_idx(db, def); - - Some( - args.iter() - .enumerate() - .filter_map( - move |(idx, generic_arg)| { - if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } - }, - ) - .filter_map(|generic_arg| generic_arg.as_type()) - .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty)) - .map(move |self_ty| { - let trait_ref = TraitRef::new_from_args( - interner, - sized_trait.into(), - GenericArgs::new_from_slice(&[self_ty.into()]), - ); - Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )) - }), - ) -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericDefaults(Option<Arc<[Option<StoredEarlyBinder<StoredGenericArg>>]>>); @@ -2336,10 +2410,11 @@ pub(crate) fn generic_defaults_with_diagnostics_query( } let resolver = def.resolver(db); + let store_for_self = generic_params.store(); let mut ctx = TyLoweringContext::new( db, &resolver, - generic_params.store(), + store_for_self, def, LifetimeElisionKind::AnonymousReportError, ) @@ -2357,6 +2432,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query( }) .collect::<Vec<_>>(); ctx.diagnostics.clear(); // Don't include diagnostics from the parent. + ctx.store = store_for_self; defaults.extend(generic_params.iter_self().map(|(_id, p)| { let (result, has_default) = handle_generic_param(&mut ctx, idx, p); has_any_default |= has_default; @@ -2427,7 +2503,7 @@ pub(crate) fn callable_item_signature<'db>( } fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<StoredPolyFnSig> { - let data = db.function_signature(def); + let data = FunctionSignature::of(db, def); let resolver = def.resolver(db); let interner = DbInterner::new_no_crate(db); let mut ctx_params = TyLoweringContext::new( @@ -2435,7 +2511,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> StoredEarlyBinder<Sto &resolver, &data.store, def.into(), - LifetimeElisionKind::for_fn_params(&data), + LifetimeElisionKind::for_fn_params(data), ); let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); @@ -2482,7 +2558,7 @@ fn fn_sig_for_struct_constructor( let inputs_and_output = Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret.as_ref()))); StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig { - abi: FnAbi::RustCall, + abi: FnAbi::Rust, c_variadic: false, safety: Safety::Safe, inputs_and_output, @@ -2501,7 +2577,7 @@ fn fn_sig_for_enum_variant_constructor( let inputs_and_output = Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret.as_ref()))); StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig { - abi: FnAbi::RustCall, + abi: FnAbi::Rust, c_variadic: false, safety: Safety::Safe, inputs_and_output, @@ -2513,7 +2589,7 @@ pub(crate) fn associated_ty_item_bounds<'db>( db: &'db dyn HirDatabase, type_alias: TypeAliasId, ) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { - let type_alias_data = db.type_alias_signature(type_alias); + let type_alias_data = TypeAliasSignature::of(db, type_alias); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( @@ -2535,7 +2611,7 @@ pub(crate) fn associated_ty_item_bounds<'db>( .map_bound(|c| match c { rustc_type_ir::ClauseKind::Trait(t) => { let id = t.def_id(); - let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); + let is_auto = TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO); if is_auto { Some(ExistentialPredicate::AutoTrait(t.def_id())) } else { @@ -2583,143 +2659,25 @@ pub(crate) fn associated_ty_item_bounds<'db>( EarlyBinder::bind(BoundExistentialPredicates::new_from_slice(&bounds)) } -pub(crate) fn associated_type_by_name_including_super_traits<'db>( +pub(crate) fn associated_type_by_name_including_super_traits_allow_ambiguity<'db>( db: &'db dyn HirDatabase, trait_ref: TraitRef<'db>, - name: &Name, -) -> Option<(TraitRef<'db>, TypeAliasId)> { - let module = trait_ref.def_id.0.module(db); - let interner = DbInterner::new_with(db, module.krate(db)); - rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| { - let trait_id = t.as_ref().skip_binder().def_id.0; - let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?; - Some((t.skip_binder(), assoc_type)) - }) -} - -pub fn associated_type_shorthand_candidates( - db: &dyn HirDatabase, - def: GenericDefId, - res: TypeNs, - mut cb: impl FnMut(&Name, TypeAliasId) -> bool, -) -> Option<TypeAliasId> { - let interner = DbInterner::new_no_crate(db); - named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { - cb(name, id).then_some(id) - }) -} - -#[tracing::instrument(skip(interner, check_alias))] -fn named_associated_type_shorthand_candidates<'db, R>( - interner: DbInterner<'db>, - // If the type parameter is defined in an impl and we're in a method, there - // might be additional where clauses to consider - def: GenericDefId, - res: TypeNs, - assoc_name: Option<Name>, - mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>, -) -> Option<R> { - let db = interner.db; - let mut search = |t: TraitRef<'db>| -> Option<R> { - let mut checked_traits = FxHashSet::default(); - let mut check_trait = |trait_ref: TraitRef<'db>| { - let trait_id = trait_ref.def_id.0; - let name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_id, ?name); - if !checked_traits.insert(trait_id) { - return None; - } - let data = trait_id.trait_items(db); - - tracing::debug!(?data.items); - for (name, assoc_id) in &data.items { - if let &AssocItemId::TypeAliasId(alias) = assoc_id - && let Some(ty) = check_alias(name, trait_ref, alias) - { - return Some(ty); - } - } - None - }; - let mut stack: SmallVec<[_; 4]> = smallvec![t]; - while let Some(trait_ref) = stack.pop() { - if let Some(alias) = check_trait(trait_ref) { - return Some(alias); - } - let predicates = generic_predicates_filtered_by( - db, - GenericDefId::TraitId(trait_ref.def_id.0), - PredicateFilter::SelfTrait, - // We are likely in the midst of lowering generic predicates of `def`. - // So, if we allow `pred == def` we might fall into an infinite recursion. - // Actually, we have already checked for the case `pred == def` above as we started - // with a stack including `trait_id` - |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0), - ) - .0 - .predicates; - for pred in predicates.get().instantiate_identity() { - tracing::debug!(?pred); - let sup_trait_ref = match pred.kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref, - _ => continue, - }; - let sup_trait_ref = - EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args); - stack.push(sup_trait_ref); - } - tracing::debug!(?stack); - } - - None + name: Name, +) -> Option<(TypeAliasId, GenericArgs<'db>)> { + let (AssocTypeShorthandResolution::Resolved(assoc_type) + | AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: Some(assoc_type) }) = + resolve_type_param_assoc_type_shorthand( + db, + trait_ref.def_id.0.into(), + TypeParamId::trait_self(trait_ref.def_id.0), + name.clone(), + ) + else { + return None; }; - - match res { - TypeNs::SelfType(impl_id) => { - let trait_ref = db.impl_trait(impl_id)?; - - // FIXME(next-solver): same method in `lower` checks for impl or not - // Is that needed here? - - // we're _in_ the impl -- the binders get added back later. Correct, - // but it would be nice to make this more explicit - search(trait_ref.skip_binder()) - } - TypeNs::GenericParam(param_id) => { - // Handle `Self::Type` referring to own associated type in trait definitions - // This *must* be done first to avoid cycles with - // `generic_predicates_for_param`, but not sure that it's sufficient, - if let GenericDefId::TraitId(trait_id) = param_id.parent() { - let trait_name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_name); - let trait_generics = generics(db, trait_id.into()); - tracing::debug!(?trait_generics); - if trait_generics[param_id.local_id()].is_trait_self() { - let args = GenericArgs::identity_for_item(interner, trait_id.into()); - let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args); - tracing::debug!(?args, ?trait_ref); - return search(trait_ref); - } - } - - let predicates = - generic_predicates_for_param(db, def, param_id.into(), assoc_name.clone()); - predicates - .get() - .iter_identity() - .find_map(|pred| match pred.kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate), - _ => None, - }) - .and_then(|trait_predicate| { - let trait_ref = trait_predicate.trait_ref; - assert!( - !trait_ref.has_escaping_bound_vars(), - "FIXME unexpected higher-ranked trait bound" - ); - search(trait_ref) - }) - } - _ => None, - } + let (assoc_type, trait_args) = assoc_type + .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref())) + .skip_binder(); + let interner = DbInterner::new_no_crate(db); + Some((assoc_type, EarlyBinder::bind(trait_args).instantiate(interner, trait_ref.args))) } |