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.rs135
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),
),
}
};