Convert some of dyn_compatibility to next-solver and remove generic_predicates_without_parent_query

This commit is contained in:
jackh726 2025-08-08 02:06:01 +00:00
parent 484db3a517
commit 8228f6f9f7
4 changed files with 79 additions and 53 deletions

View File

@ -179,16 +179,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::lower::generic_predicates_query)] #[salsa::invoke(crate::lower::generic_predicates_query)]
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
#[salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)]
fn generic_predicates_without_parent_with_diagnostics(
&self,
def: GenericDefId,
) -> (GenericPredicates, Diagnostics);
#[salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
#[salsa::transparent]
fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates;
#[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::invoke(crate::lower::trait_environment_for_body_query)]
#[salsa::transparent] #[salsa::transparent]
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>; fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>;

View File

@ -13,6 +13,9 @@ use hir_def::{
TypeAliasId, lang_item::LangItem, signatures::TraitFlags, TypeAliasId, lang_item::LangItem, signatures::TraitFlags,
}; };
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use rustc_type_ir::{
AliasTyKind, ClauseKind, PredicatePolarity, TypeSuperVisitable as _, inherent::IntoKind,
};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{ use crate::{
@ -21,6 +24,7 @@ use crate::{
db::HirDatabase, db::HirDatabase,
from_assoc_type_id, from_chalk_trait_id, from_assoc_type_id, from_chalk_trait_id,
generics::{generics, trait_self_param_idx}, generics::{generics, trait_self_param_idx},
next_solver::{DbInterner, SolverDefId, TraitPredicate},
to_chalk_trait_id, to_chalk_trait_id,
utils::elaborate_clause_supertraits, utils::elaborate_clause_supertraits,
}; };
@ -319,6 +323,61 @@ fn contains_illegal_self_type_reference<T: TypeVisitable<Interner>>(
t.visit_with(visitor.as_dyn(), outer_binder).is_break() t.visit_with(visitor.as_dyn(), outer_binder).is_break()
} }
fn contains_illegal_self_type_reference_ns<
'db,
T: rustc_type_ir::TypeVisitable<DbInterner<'db>>,
>(
db: &'db dyn HirDatabase,
trait_: TraitId,
t: &T,
allow_self_projection: AllowSelfProjection,
) -> bool {
struct IllegalSelfTypeVisitor<'db> {
db: &'db dyn HirDatabase,
trait_: TraitId,
super_traits: Option<SmallVec<[TraitId; 4]>>,
allow_self_projection: AllowSelfProjection,
}
impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for IllegalSelfTypeVisitor<'db> {
type Result = ControlFlow<()>;
fn visit_ty(
&mut self,
ty: <DbInterner<'db> as rustc_type_ir::Interner>::Ty,
) -> Self::Result {
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(all_super_traits(self.db, self.trait_));
}
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),
},
_ => ty.super_visit_with(self),
}
}
}
let mut visitor =
IllegalSelfTypeVisitor { db, trait_, super_traits: None, allow_self_projection };
t.visit_with(&mut visitor).is_break()
}
fn dyn_compatibility_violation_for_assoc_item<F>( fn dyn_compatibility_violation_for_assoc_item<F>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
trait_: TraitId, trait_: TraitId,
@ -415,40 +474,33 @@ where
cb(MethodViolationCode::UndispatchableReceiver)?; cb(MethodViolationCode::UndispatchableReceiver)?;
} }
let predicates = &*db.generic_predicates_without_parent(func.into()); let predicates = &*db.generic_predicates_without_parent_ns(func.into());
let trait_self_idx = trait_self_param_idx(db, func.into());
for pred in predicates { for pred in predicates {
let pred = pred.skip_binders().skip_binders(); let pred = pred.kind().skip_binder();
if matches!(pred, WhereClause::TypeOutlives(_)) { if matches!(pred, ClauseKind::TypeOutlives(_)) {
continue; continue;
} }
// Allow `impl AutoTrait` predicates // Allow `impl AutoTrait` predicates
if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred { let interner = DbInterner::new_with(db, None, None);
let trait_data = db.trait_signature(from_chalk_trait_id(*trait_id)); if let ClauseKind::Trait(TraitPredicate {
if trait_data.flags.contains(TraitFlags::AUTO) trait_ref: pred_trait_ref,
&& substitution polarity: PredicatePolarity::Positive,
.as_slice(Interner) }) = pred
.first() && let SolverDefId::TraitId(trait_id) = pred_trait_ref.def_id
.and_then(|arg| arg.ty(Interner)) && let trait_data = db.trait_signature(trait_id)
.and_then(|ty| ty.bound_var(Interner)) && trait_data.flags.contains(TraitFlags::AUTO)
.is_some_and(|b| { && pred_trait_ref.self_ty()
b.debruijn == DebruijnIndex::ONE && Some(b.index) == trait_self_idx == crate::next_solver::Ty::new(
}) interner,
rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }),
)
{ {
continue; continue;
} }
}
if contains_illegal_self_type_reference( if contains_illegal_self_type_reference_ns(db, trait_, &pred, AllowSelfProjection::Yes) {
db,
func.into(),
trait_,
pred,
DebruijnIndex::ONE,
AllowSelfProjection::Yes,
) {
cb(MethodViolationCode::WhereClauseReferencesSelf)?; cb(MethodViolationCode::WhereClauseReferencesSelf)?;
break; break;
} }

View File

@ -1179,22 +1179,6 @@ pub(crate) fn generic_predicates_query(
generic_predicates_filtered_by(db, def, |_, _| true).0 generic_predicates_filtered_by(db, def, |_, _| true).0
} }
pub(crate) fn generic_predicates_without_parent_query(
db: &dyn HirDatabase,
def: GenericDefId,
) -> GenericPredicates {
db.generic_predicates_without_parent_with_diagnostics(def).0
}
/// Resolve the where clause(s) of an item with generics,
/// except the ones inherited from the parent
pub(crate) fn generic_predicates_without_parent_with_diagnostics_query(
db: &dyn HirDatabase,
def: GenericDefId,
) -> (GenericPredicates, Diagnostics) {
generic_predicates_filtered_by(db, def, |_, d| d == def)
}
/// Resolve the where clause(s) of an item with generics, /// Resolve the where clause(s) of an item with generics,
/// with a given filter /// with a given filter
fn generic_predicates_filtered_by<F>( fn generic_predicates_filtered_by<F>(

View File

@ -3750,7 +3750,7 @@ impl GenericDef {
push_ty_diagnostics( push_ty_diagnostics(
db, db,
acc, acc,
db.generic_predicates_without_parent_with_diagnostics(def).1, db.generic_predicates_without_parent_with_diagnostics_ns(def).1,
&source_map, &source_map,
); );
for (param_id, param) in generics.iter_type_or_consts() { for (param_id, param) in generics.iter_type_or_consts() {