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.rs63
1 files changed, 31 insertions, 32 deletions
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index ba63343d49..34858212cb 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -6,8 +6,8 @@ use hir_def::{
AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId,
hir::generics::{GenericParams, LocalTypeOrConstParamId},
- nameres::crate_def_map,
signatures::{FunctionSignature, TraitFlags, TraitSignature},
+ unstable_features::UnstableFeatures,
};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
@@ -21,11 +21,14 @@ use crate::{
db::{HirDatabase, InternedOpaqueTyId},
lower::{GenericPredicates, associated_ty_item_bounds},
next_solver::{
- AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv,
- ParamTy, SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt,
+ AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv, ParamTy,
+ SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, Unnormalized,
+ infer::{
+ DbInternerInferExt,
+ traits::{Obligation, ObligationCause},
+ },
mk_param,
},
- traits::next_trait_solve_in_ctxt,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -111,8 +114,9 @@ where
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
let trait_data = trait_.trait_items(db);
+ let mut features = None;
for (_, assoc_item) in &trait_data.items {
- dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
+ dyn_compatibility_violation_for_assoc_item(db, &mut features, trait_, *assoc_item, cb)?;
}
ControlFlow::Continue(())
@@ -142,8 +146,8 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
// 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_identity()).any(|pred| {
- match pred.kind().skip_binder() {
+ elaborate::elaborate(interner, predicates.iter_identity().map(Unnormalized::skip_norm_wip)).any(
+ |pred| match pred.kind().skip_binder() {
ClauseKind::Trait(trait_pred) => {
if sized == trait_pred.def_id().0
&& let rustc_type_ir::TyKind::Param(param_ty) =
@@ -156,17 +160,17 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
}
}
_ => false,
- }
- })
+ },
+ )
}
// rustc gathers all the spans that references `Self` for error rendering,
// 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 {
- GenericPredicates::query_explicit(db, trait_.into())
- .iter_identity()
- .any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No))
+ GenericPredicates::query_explicit(db, trait_.into()).iter_identity().any(|pred| {
+ predicate_references_self(db, trait_, pred.skip_norm_wip(), AllowSelfProjection::No)
+ })
}
// Same as the above, `predicates_reference_self`
@@ -244,11 +248,7 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI
proj @ AliasTy { kind: AliasTyKind::Projection { .. }, .. },
) => match self.allow_self_projection {
AllowSelfProjection::Yes => {
- let trait_ = proj.trait_def_id(interner);
- let trait_ = match trait_ {
- SolverDefId::TraitId(id) => id,
- _ => unreachable!(),
- };
+ let trait_ = proj.trait_def_id(interner).0;
if self.super_traits.is_none() {
self.super_traits = Some(
elaborate::supertrait_def_ids(interner, self.trait_.into())
@@ -274,8 +274,9 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI
t.visit_with(&mut visitor).is_break()
}
-fn dyn_compatibility_violation_for_assoc_item<F>(
- db: &dyn HirDatabase,
+fn dyn_compatibility_violation_for_assoc_item<'db, F>(
+ db: &'db dyn HirDatabase,
+ features: &mut Option<&'db UnstableFeatures>,
trait_: TraitId,
item: AssocItemId,
cb: &mut F,
@@ -297,8 +298,10 @@ where
})
}
AssocItemId::TypeAliasId(it) => {
- let def_map = crate_def_map(db, trait_.krate(db));
- if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) {
+ if features
+ .get_or_insert_with(|| UnstableFeatures::query(db, trait_.krate(db)))
+ .generic_associated_type_extended
+ {
ControlFlow::Continue(())
} else {
let generic_params = GenericParams::of(db, item.into());
@@ -397,7 +400,7 @@ fn receiver_is_dispatchable<'db>(
func: FunctionId,
sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>>,
) -> bool {
- let sig = sig.instantiate_identity();
+ let sig = sig.instantiate_identity().skip_norm_wip();
let module = trait_.module(db);
let interner = DbInterner::new_with(db, module.krate(db));
@@ -461,6 +464,7 @@ fn receiver_is_dispatchable<'db>(
interner,
generic_predicates
.iter_identity()
+ .map(Unnormalized::skip_norm_wip)
.chain([unsize_predicate.upcast(interner), trait_predicate.upcast(interner)])
.chain(meta_sized_predicate),
),
@@ -470,12 +474,11 @@ fn receiver_is_dispatchable<'db>(
// Receiver: DispatchFromDyn<Receiver[Self => U]>
let predicate =
TraitRef::new(interner, dispatch_from_dyn_did.into(), [receiver_ty, unsized_receiver_ty]);
- let goal = Goal::new(interner, param_env, predicate);
+ let obligation = Obligation::new(interner, ObligationCause::dummy(), param_env, predicate);
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
// the receiver is dispatchable iff the obligation holds
- let res = next_trait_solve_in_ctxt(&infcx, goal);
- res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes))
+ infcx.predicate_must_hold_modulo_regions(&obligation)
}
fn receiver_for_self_ty<'db>(
@@ -488,7 +491,7 @@ fn receiver_for_self_ty<'db>(
if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) }
});
- EarlyBinder::bind(receiver_ty).instantiate(interner, args)
+ EarlyBinder::bind(receiver_ty).instantiate(interner, args).skip_norm_wip()
}
fn contains_illegal_impl_trait_in_trait<'db>(
@@ -509,11 +512,7 @@ fn contains_illegal_impl_trait_in_trait<'db>(
..
}) = ty.kind()
{
- let id = match def_id {
- SolverDefId::InternedOpaqueTyId(id) => id,
- _ => unreachable!(),
- };
- self.0.insert(id);
+ self.0.insert(def_id.0);
}
ty.super_visit_with(self)
}
@@ -526,7 +525,7 @@ fn contains_illegal_impl_trait_in_trait<'db>(
// Since we haven't implemented RPITIT in proper way like rustc yet,
// just check whether `ret` contains RPIT for now
for opaque_ty in visitor.0 {
- let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty);
+ let impl_trait_id = opaque_ty.loc(db);
if matches!(impl_trait_id, ImplTraitId::ReturnTypeImplTrait(..)) {
return Some(MethodViolationCode::ReferencesImplTraitInTrait);
}