Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/dyn_compatibility.rs')
| -rw-r--r-- | crates/hir-ty/src/dyn_compatibility.rs | 135 |
1 files changed, 66 insertions, 69 deletions
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index 437141e41d..59cfd3fdc9 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -3,22 +3,21 @@ use std::ops::ControlFlow; use hir_def::{ - AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId, - TypeAliasId, TypeOrConstParamId, TypeParamId, hir::generics::LocalTypeOrConstParamId, - lang_item::LangItem, signatures::TraitFlags, + AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId, + TypeOrConstParamId, TypeParamId, hir::generics::LocalTypeOrConstParamId, + nameres::crate_def_map, signatures::TraitFlags, }; use rustc_hash::FxHashSet; use rustc_type_ir::{ AliasTyKind, ClauseKind, PredicatePolarity, TypeSuperVisitable as _, TypeVisitable as _, - Upcast, elaborate, - inherent::{IntoKind, SliceLike}, + Upcast, elaborate, inherent::IntoKind, }; use smallvec::SmallVec; use crate::{ ImplTraitId, db::{HirDatabase, InternedOpaqueTyId}, - lower::associated_ty_item_bounds, + lower::{GenericPredicates, associated_ty_item_bounds}, next_solver::{ Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv, ParamTy, SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt, mk_param, @@ -53,7 +52,7 @@ pub fn dyn_compatibility( db: &dyn HirDatabase, trait_: TraitId, ) -> Option<DynCompatibilityViolation> { - let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let interner = DbInterner::new_no_crate(db); for super_trait in elaborate::supertrait_def_ids(interner, trait_.into()) { if let Some(v) = db.dyn_compatibility_of_trait(super_trait.0) { return if super_trait.0 == trait_ { @@ -75,7 +74,7 @@ pub fn dyn_compatibility_with_callback<F>( where F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>, { - let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let interner = DbInterner::new_no_crate(db); for super_trait in elaborate::supertrait_def_ids(interner, trait_.into()).skip(1) { if db.dyn_compatibility_of_trait(super_trait.0).is_some() { cb(DynCompatibilityViolation::HasNonCompatibleSuperTrait(trait_))?; @@ -130,17 +129,17 @@ pub fn dyn_compatibility_of_trait_query( } pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { - let krate = def.module(db).krate(); - let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else { + let krate = def.module(db).krate(db); + let interner = DbInterner::new_with(db, krate); + let Some(sized) = interner.lang_items().Sized else { return false; }; - let interner = DbInterner::new_with(db, Some(krate), None); - let predicates = db.generic_predicates(def); + let predicates = GenericPredicates::query_explicit(db, def); // FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to // rust-analyzer yet // https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490 - elaborate::elaborate(interner, predicates.iter().copied()).any(|pred| { + elaborate::elaborate(interner, predicates.iter_identity_copied()).any(|pred| { match pred.kind().skip_binder() { ClauseKind::Trait(trait_pred) => { if sized == trait_pred.def_id().0 @@ -162,8 +161,8 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b // but we don't have good way to render such locations. // So, just return single boolean value for existence of such `Self` reference fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { - db.generic_predicates(trait_.into()) - .iter() + GenericPredicates::query_explicit(db, trait_.into()) + .iter_identity_copied() .any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No)) } @@ -199,7 +198,7 @@ enum AllowSelfProjection { fn predicate_references_self<'db>( db: &'db dyn HirDatabase, trait_: TraitId, - predicate: &Clause<'db>, + predicate: Clause<'db>, allow_self_projection: AllowSelfProjection, ) -> bool { match predicate.kind().skip_binder() { @@ -234,34 +233,34 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI &mut self, ty: <DbInterner<'db> as rustc_type_ir::Interner>::Ty, ) -> Self::Result { - let interner = DbInterner::new_with(self.db, None, None); + let interner = DbInterner::new_no_crate(self.db); match ty.kind() { rustc_type_ir::TyKind::Param(param) if param.index == 0 => ControlFlow::Break(()), rustc_type_ir::TyKind::Param(_) => ControlFlow::Continue(()), - rustc_type_ir::TyKind::Alias(AliasTyKind::Projection, proj) => match self - .allow_self_projection - { - AllowSelfProjection::Yes => { - let trait_ = proj.trait_def_id(DbInterner::new_with(self.db, None, None)); - let trait_ = match trait_ { - SolverDefId::TraitId(id) => id, - _ => unreachable!(), - }; - if self.super_traits.is_none() { - self.super_traits = Some( - elaborate::supertrait_def_ids(interner, self.trait_.into()) - .map(|super_trait| super_trait.0) - .collect(), - ) - } - if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) { - ControlFlow::Continue(()) - } else { - ty.super_visit_with(self) + rustc_type_ir::TyKind::Alias(AliasTyKind::Projection, proj) => { + match self.allow_self_projection { + AllowSelfProjection::Yes => { + let trait_ = proj.trait_def_id(interner); + let trait_ = match trait_ { + SolverDefId::TraitId(id) => id, + _ => unreachable!(), + }; + if self.super_traits.is_none() { + self.super_traits = Some( + elaborate::supertrait_def_ids(interner, self.trait_.into()) + .map(|super_trait| super_trait.0) + .collect(), + ) + } + if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) { + ControlFlow::Continue(()) + } else { + ty.super_visit_with(self) + } } + AllowSelfProjection::No => ty.super_visit_with(self), } - AllowSelfProjection::No => ty.super_visit_with(self), - }, + } _ => ty.super_visit_with(self), } } @@ -295,7 +294,7 @@ where }) } AssocItemId::TypeAliasId(it) => { - let def_map = CrateRootModuleId::from(trait_.krate(db)).def_map(db); + let def_map = crate_def_map(db, trait_.krate(db)); if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) { ControlFlow::Continue(()) } else { @@ -329,13 +328,9 @@ where } let sig = db.callable_item_signature(func.into()); - if sig - .skip_binder() - .inputs() - .iter() - .skip(1) - .any(|ty| contains_illegal_self_type_reference(db, trait_, &ty, AllowSelfProjection::Yes)) - { + if sig.skip_binder().inputs().iter().skip(1).any(|ty| { + contains_illegal_self_type_reference(db, trait_, ty.skip_binder(), AllowSelfProjection::Yes) + }) { cb(MethodViolationCode::ReferencesSelfInput)?; } @@ -363,8 +358,8 @@ where cb(MethodViolationCode::UndispatchableReceiver)?; } - let predicates = &*db.generic_predicates_without_parent(func.into()); - for pred in predicates { + let predicates = GenericPredicates::query_own(db, func.into()); + for pred in predicates.iter_identity_copied() { let pred = pred.kind().skip_binder(); if matches!(pred, ClauseKind::TypeOutlives(_)) { @@ -401,7 +396,8 @@ fn receiver_is_dispatchable<'db>( ) -> bool { let sig = sig.instantiate_identity(); - let interner: DbInterner<'_> = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let module = trait_.module(db); + let interner = DbInterner::new_with(db, module.krate(db)); let self_param_id = TypeParamId::from_unchecked(TypeOrConstParamId { parent: trait_.into(), local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), @@ -411,27 +407,29 @@ fn receiver_is_dispatchable<'db>( // `self: Self` can't be dispatched on, but this is already considered dyn-compatible // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437 - if sig.inputs().iter().next().is_some_and(|p| p.skip_binder() == self_param_ty) { + if sig.inputs().iter().next().is_some_and(|p| *p.skip_binder() == self_param_ty) { return true; } - let Some(&receiver_ty) = sig.inputs().skip_binder().as_slice().first() else { + let Some(&receiver_ty) = sig.inputs().skip_binder().first() else { return false; }; - let krate = func.module(db).krate(); - let traits = ( - LangItem::Unsize.resolve_trait(db, krate), - LangItem::DispatchFromDyn.resolve_trait(db, krate), - ); + let lang_items = interner.lang_items(); + let traits = (lang_items.Unsize, lang_items.DispatchFromDyn); let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else { return false; }; - let meta_sized_did = LangItem::MetaSized.resolve_trait(db, krate); - let Some(meta_sized_did) = meta_sized_did else { - return false; - }; + let meta_sized_did = lang_items.MetaSized; + + // TODO: This is for supporting dyn compatibility for toolchains doesn't contain `MetaSized` + // trait. Uncomment and short circuit here once `MINIMUM_SUPPORTED_TOOLCHAIN_VERSION` + // become > 1.88.0 + // + // let Some(meta_sized_did) = meta_sized_did else { + // return false; + // }; // Type `U` // FIXME: That seems problematic to fake a generic param like that? @@ -440,7 +438,7 @@ fn receiver_is_dispatchable<'db>( let unsized_receiver_ty = receiver_for_self_ty(interner, func, receiver_ty, unsized_self_ty); let param_env = { - let generic_predicates = &*db.generic_predicates(func.into()); + let generic_predicates = GenericPredicates::query_all(db, func.into()); // Self: Unsize<U> let unsize_predicate = @@ -452,17 +450,16 @@ fn receiver_is_dispatchable<'db>( }); let trait_predicate = TraitRef::new_from_args(interner, trait_.into(), args); - let meta_sized_predicate = - TraitRef::new(interner, meta_sized_did.into(), [unsized_self_ty]); + let meta_sized_predicate = meta_sized_did + .map(|did| TraitRef::new(interner, did.into(), [unsized_self_ty]).upcast(interner)); ParamEnv { clauses: Clauses::new_from_iter( interner, - generic_predicates.iter().copied().chain([ - unsize_predicate.upcast(interner), - trait_predicate.upcast(interner), - meta_sized_predicate.upcast(interner), - ]), + generic_predicates + .iter_identity_copied() + .chain([unsize_predicate.upcast(interner), trait_predicate.upcast(interner)]) + .chain(meta_sized_predicate), ), } }; |