diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 6e24aea76d..7a5daac699 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -179,16 +179,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(crate::lower::generic_predicates_query)] 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::transparent] fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc; diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index 2d21947ec6..f571b64464 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -13,6 +13,9 @@ use hir_def::{ TypeAliasId, lang_item::LangItem, signatures::TraitFlags, }; use rustc_hash::FxHashSet; +use rustc_type_ir::{ + AliasTyKind, ClauseKind, PredicatePolarity, TypeSuperVisitable as _, inherent::IntoKind, +}; use smallvec::SmallVec; use crate::{ @@ -21,6 +24,7 @@ use crate::{ db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, generics::{generics, trait_self_param_idx}, + next_solver::{DbInterner, SolverDefId, TraitPredicate}, to_chalk_trait_id, utils::elaborate_clause_supertraits, }; @@ -319,6 +323,61 @@ fn contains_illegal_self_type_reference>( t.visit_with(visitor.as_dyn(), outer_binder).is_break() } +fn contains_illegal_self_type_reference_ns< + 'db, + T: rustc_type_ir::TypeVisitable>, +>( + 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>, + allow_self_projection: AllowSelfProjection, + } + impl<'db> rustc_type_ir::TypeVisitor> for IllegalSelfTypeVisitor<'db> { + type Result = ControlFlow<()>; + + fn visit_ty( + &mut self, + ty: 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( db: &dyn HirDatabase, trait_: TraitId, @@ -415,40 +474,33 @@ where cb(MethodViolationCode::UndispatchableReceiver)?; } - let predicates = &*db.generic_predicates_without_parent(func.into()); - let trait_self_idx = trait_self_param_idx(db, func.into()); + let predicates = &*db.generic_predicates_without_parent_ns(func.into()); 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; } // Allow `impl AutoTrait` predicates - if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred { - let trait_data = db.trait_signature(from_chalk_trait_id(*trait_id)); - if trait_data.flags.contains(TraitFlags::AUTO) - && substitution - .as_slice(Interner) - .first() - .and_then(|arg| arg.ty(Interner)) - .and_then(|ty| ty.bound_var(Interner)) - .is_some_and(|b| { - b.debruijn == DebruijnIndex::ONE && Some(b.index) == trait_self_idx - }) - { - continue; - } + let interner = DbInterner::new_with(db, None, None); + if let ClauseKind::Trait(TraitPredicate { + trait_ref: pred_trait_ref, + polarity: PredicatePolarity::Positive, + }) = pred + && let SolverDefId::TraitId(trait_id) = pred_trait_ref.def_id + && let trait_data = db.trait_signature(trait_id) + && trait_data.flags.contains(TraitFlags::AUTO) + && pred_trait_ref.self_ty() + == crate::next_solver::Ty::new( + interner, + rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }), + ) + { + continue; } - if contains_illegal_self_type_reference( - db, - func.into(), - trait_, - pred, - DebruijnIndex::ONE, - AllowSelfProjection::Yes, - ) { + if contains_illegal_self_type_reference_ns(db, trait_, &pred, AllowSelfProjection::Yes) { cb(MethodViolationCode::WhereClauseReferencesSelf)?; break; } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 7b6b3c3f81..065d2ea084 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1179,22 +1179,6 @@ pub(crate) fn generic_predicates_query( 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, /// with a given filter fn generic_predicates_filtered_by( diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4eb50c1c31..11486ec8d6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3750,7 +3750,7 @@ impl GenericDef { push_ty_diagnostics( db, acc, - db.generic_predicates_without_parent_with_diagnostics(def).1, + db.generic_predicates_without_parent_with_diagnostics_ns(def).1, &source_map, ); for (param_id, param) in generics.iter_type_or_consts() {