Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21399 from ShoyuVanilla/self-only-preds
fix: Properly lower `SelfOnly` predicates
Chayim Refael Friedman 4 months ago
parent 870d845 · parent 7a48463 · commit 54f5eea
-rw-r--r--crates/hir-ty/src/lower.rs369
-rw-r--r--crates/hir-ty/src/lower/path.rs34
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs7
-rw-r--r--crates/hir-ty/src/next_solver/util.rs15
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs60
5 files changed, 373 insertions, 112 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 46ec554e0a..9da32464c8 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -77,6 +77,7 @@ pub struct ImplTraits {
#[derive(PartialEq, Eq, Debug, Hash)]
pub struct ImplTrait {
pub(crate) predicates: StoredClauses,
+ pub(crate) assoc_ty_bounds_start: u32,
}
pub type ImplTraitIdx = Idx<ImplTrait>;
@@ -166,6 +167,12 @@ impl<'db> LifetimeElisionKind<'db> {
}
}
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub(crate) enum GenericPredicateSource {
+ SelfOnly,
+ AssocTyBound,
+}
+
#[derive(Debug)]
pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
@@ -465,10 +472,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
// this dance is to make sure the data is in the right
// place even if we encounter more opaque types while
// lowering the bounds
- let idx = self
- .impl_trait_mode
- .opaque_type_data
- .alloc(ImplTrait { predicates: Clauses::empty(interner).store() });
+ let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait {
+ predicates: Clauses::empty(interner).store(),
+ assoc_ty_bounds_start: 0,
+ });
let impl_trait_id = origin.either(
|f| ImplTraitId::ReturnTypeImplTrait(f, idx),
@@ -608,7 +615,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
ignore_bindings: bool,
generics: &Generics,
predicate_filter: PredicateFilter,
- ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> {
+ ) -> impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'db> {
match where_predicate {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound } => {
@@ -634,8 +641,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
let self_ty = self.lower_ty(*target);
Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings)))
}
- &WherePredicate::Lifetime { bound, target } => {
- Either::Right(iter::once(Clause(Predicate::new(
+ &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once((
+ Clause(Predicate::new(
self.interner,
Binder::dummy(rustc_type_ir::PredicateKind::Clause(
rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
@@ -643,8 +650,9 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.lower_lifetime(target),
)),
)),
- ))))
- }
+ )),
+ GenericPredicateSource::SelfOnly,
+ ))),
}
.into_iter()
}
@@ -654,7 +662,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
bound: &'b TypeBound,
self_ty: Ty<'db>,
ignore_bindings: bool,
- ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
+ ) -> impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'b, 'a, 'db> {
let interner = self.interner;
let meta_sized = self.lang_items.MetaSized;
let pointee_sized = self.lang_items.PointeeSized;
@@ -712,7 +720,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
TypeBound::Use(_) | TypeBound::Error => {}
}
- clause.into_iter().chain(assoc_bounds.into_iter().flatten())
+ clause
+ .into_iter()
+ .map(|pred| (pred, GenericPredicateSource::SelfOnly))
+ .chain(assoc_bounds.into_iter().flatten())
}
fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
@@ -732,7 +743,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
for b in bounds {
let db = ctx.db;
- ctx.lower_type_bound(b, dummy_self_ty, false).for_each(|b| {
+ ctx.lower_type_bound(b, dummy_self_ty, false).for_each(|(b, _)| {
match b.kind().skip_binder() {
rustc_type_ir::ClauseKind::Trait(t) => {
let id = t.def_id();
@@ -990,35 +1001,49 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
rustc_type_ir::AliasTyKind::Opaque,
AliasTy::new_from_args(interner, def_id, args),
);
- let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
- let mut predicates = Vec::new();
- for b in bounds {
- predicates.extend(ctx.lower_type_bound(b, self_ty, false));
- }
+ let (predicates, assoc_ty_bounds_start) =
+ self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
+ let mut predicates = Vec::new();
+ let mut assoc_ty_bounds = Vec::new();
+ for b in bounds {
+ for (pred, source) in ctx.lower_type_bound(b, self_ty, false) {
+ match source {
+ GenericPredicateSource::SelfOnly => predicates.push(pred),
+ GenericPredicateSource::AssocTyBound => assoc_ty_bounds.push(pred),
+ }
+ }
+ }
- if !ctx.unsized_types.contains(&self_ty) {
- let sized_trait = self.lang_items.Sized;
- let sized_clause = sized_trait.map(|trait_id| {
- let trait_ref = TraitRef::new_from_args(
- interner,
- trait_id.into(),
- GenericArgs::new_from_slice(&[self_ty.into()]),
- );
- Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- ))
- });
- predicates.extend(sized_clause);
- }
- predicates
- });
- ImplTrait { predicates: Clauses::new_from_slice(&predicates).store() }
+ if !ctx.unsized_types.contains(&self_ty) {
+ let sized_trait = self.lang_items.Sized;
+ let sized_clause = sized_trait.map(|trait_id| {
+ let trait_ref = TraitRef::new_from_args(
+ interner,
+ trait_id.into(),
+ GenericArgs::new_from_slice(&[self_ty.into()]),
+ );
+ Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ ))
+ });
+ predicates.extend(sized_clause);
+ }
+
+ let assoc_ty_bounds_start = predicates.len() as u32;
+ predicates.extend(assoc_ty_bounds);
+ (predicates, assoc_ty_bounds_start)
+ });
+
+ ImplTrait {
+ predicates: Clauses::new_from_slice(&predicates).store(),
+ assoc_ty_bounds_start,
+ }
}
pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> {
@@ -1139,6 +1164,31 @@ impl ImplTraitId {
.expect("owner should have opaque type")
.get_with(|it| it.impl_traits[idx].predicates.as_ref().as_slice())
}
+
+ #[inline]
+ pub fn self_predicates<'db>(
+ self,
+ db: &'db dyn HirDatabase,
+ ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ let (impl_traits, idx) = match self {
+ ImplTraitId::ReturnTypeImplTrait(owner, idx) => {
+ (ImplTraits::return_type_impl_traits(db, owner), idx)
+ }
+ ImplTraitId::TypeAliasImplTrait(owner, idx) => {
+ (ImplTraits::type_alias_impl_traits(db, owner), idx)
+ }
+ };
+ let predicates =
+ impl_traits.as_deref().expect("owner should have opaque type").get_with(|it| {
+ let impl_trait = &it.impl_traits[idx];
+ (
+ impl_trait.predicates.as_ref().as_slice(),
+ impl_trait.assoc_ty_bounds_start as usize,
+ )
+ });
+
+ predicates.map_bound(|(preds, len)| &preds[..len])
+ }
}
impl InternedOpaqueTyId {
@@ -1146,6 +1196,14 @@ impl InternedOpaqueTyId {
pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> {
self.loc(db).predicates(db)
}
+
+ #[inline]
+ pub fn self_predicates<'db>(
+ self,
+ db: &'db dyn HirDatabase,
+ ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ self.loc(db).self_predicates(db)
+ }
}
#[salsa::tracked]
@@ -1655,12 +1713,15 @@ pub(crate) fn generic_predicates_for_param<'db>(
ctx.store = maybe_parent_generics.store();
for pred in maybe_parent_generics.where_predicates() {
if predicate(pred, &mut ctx) {
- predicates.extend(ctx.lower_where_predicate(
- pred,
- true,
- maybe_parent_generics,
- PredicateFilter::All,
- ));
+ predicates.extend(
+ ctx.lower_where_predicate(
+ pred,
+ true,
+ maybe_parent_generics,
+ PredicateFilter::All,
+ )
+ .map(|(pred, _)| pred),
+ );
}
}
}
@@ -1696,21 +1757,44 @@ pub(crate) fn type_alias_bounds<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
) -> EarlyBinder<'db, &'db [Clause<'db>]> {
- type_alias_bounds_with_diagnostics(db, type_alias).0.map_bound(|it| it.as_slice())
+ type_alias_bounds_with_diagnostics(db, type_alias).0.predicates.map_bound(|it| it.as_slice())
+}
+
+#[inline]
+pub(crate) fn type_alias_self_bounds<'db>(
+ db: &'db dyn HirDatabase,
+ type_alias: TypeAliasId,
+) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ let (TypeAliasBounds { predicates, assoc_ty_bounds_start }, _) =
+ type_alias_bounds_with_diagnostics(db, type_alias);
+ predicates.map_bound(|it| &it.as_slice()[..assoc_ty_bounds_start as usize])
+}
+
+#[derive(PartialEq, Eq, Debug, Hash)]
+struct TypeAliasBounds<T> {
+ predicates: T,
+ assoc_ty_bounds_start: u32,
}
-pub(crate) fn type_alias_bounds_with_diagnostics<'db>(
+fn type_alias_bounds_with_diagnostics<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
-) -> (EarlyBinder<'db, Clauses<'db>>, Diagnostics) {
- let (bounds, diags) = type_alias_bounds_with_diagnostics_query(db, type_alias);
- return (bounds.get(), diags.clone());
+) -> (TypeAliasBounds<EarlyBinder<'db, Clauses<'db>>>, Diagnostics) {
+ let (TypeAliasBounds { predicates, assoc_ty_bounds_start }, diags) =
+ type_alias_bounds_with_diagnostics_query(db, type_alias);
+ return (
+ TypeAliasBounds {
+ predicates: predicates.get(),
+ assoc_ty_bounds_start: *assoc_ty_bounds_start,
+ },
+ diags.clone(),
+ );
#[salsa::tracked(returns(ref))]
pub fn type_alias_bounds_with_diagnostics_query<'db>(
db: &'db dyn HirDatabase,
type_alias: TypeAliasId,
- ) -> (StoredEarlyBinder<StoredClauses>, Diagnostics) {
+ ) -> (TypeAliasBounds<StoredEarlyBinder<StoredClauses>>, Diagnostics) {
let type_alias_data = db.type_alias_signature(type_alias);
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
let mut ctx = TyLoweringContext::new(
@@ -1727,10 +1811,18 @@ pub(crate) fn type_alias_bounds_with_diagnostics<'db>(
let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
let mut bounds = Vec::new();
+ let mut assoc_ty_bounds = Vec::new();
for bound in &type_alias_data.bounds {
- ctx.lower_type_bound(bound, interner_ty, false).for_each(|pred| {
- bounds.push(pred);
- });
+ ctx.lower_type_bound(bound, interner_ty, false).for_each(
+ |(pred, source)| match source {
+ GenericPredicateSource::SelfOnly => {
+ bounds.push(pred);
+ }
+ GenericPredicateSource::AssocTyBound => {
+ assoc_ty_bounds.push(pred);
+ }
+ },
+ );
}
if !ctx.unsized_types.contains(&interner_ty) {
@@ -1745,8 +1837,14 @@ pub(crate) fn type_alias_bounds_with_diagnostics<'db>(
};
}
+ let assoc_ty_bounds_start = bounds.len() as u32;
+ bounds.extend(assoc_ty_bounds);
+
(
- StoredEarlyBinder::bind(Clauses::new_from_slice(&bounds).store()),
+ TypeAliasBounds {
+ predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&bounds).store()),
+ assoc_ty_bounds_start,
+ },
create_diagnostics(ctx.diagnostics),
)
}
@@ -1754,11 +1852,15 @@ pub(crate) fn type_alias_bounds_with_diagnostics<'db>(
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericPredicates {
- // The order is the following: first, if `parent_is_trait == true`, comes the implicit trait predicate for the
- // parent. Then come the explicit predicates for the parent, then the explicit trait predicate for the child,
+ // The order is the following: first, if `parent_is_trait == true`, comes the implicit trait
+ // predicate for the parent. Then come the bounds of the associated types of the parents,
+ // then the explicit, self-only predicates for the parent, then the explicit, self-only trait
+ // predicate for the child, then the bounds of the associated types of the child,
// then the implicit trait predicate for the child, if `is_trait` is `true`.
predicates: StoredEarlyBinder<StoredClauses>,
+ parent_explicit_self_predicates_start: u32,
own_predicates_start: u32,
+ own_assoc_ty_bounds_start: u32,
is_trait: bool,
parent_is_trait: bool,
}
@@ -1782,7 +1884,15 @@ impl GenericPredicates {
pub(crate) fn from_explicit_own_predicates(
predicates: StoredEarlyBinder<StoredClauses>,
) -> Self {
- Self { predicates, own_predicates_start: 0, is_trait: false, parent_is_trait: false }
+ let len = predicates.get().skip_binder().len() as u32;
+ Self {
+ predicates,
+ parent_explicit_self_predicates_start: 0,
+ own_predicates_start: 0,
+ own_assoc_ty_bounds_start: len,
+ is_trait: false,
+ parent_is_trait: false,
+ }
}
#[inline]
@@ -1815,6 +1925,14 @@ impl GenericPredicates {
}
#[inline]
+ pub fn query_explicit_implied<'db>(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+ ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ Self::query(db, def).explicit_implied_predicates()
+ }
+
+ #[inline]
pub fn all_predicates(&self) -> EarlyBinder<'_, &[Clause<'_>]> {
self.predicates.get().map_bound(|it| it.as_slice())
}
@@ -1824,10 +1942,19 @@ impl GenericPredicates {
self.predicates.get().map_bound(|it| &it.as_slice()[self.own_predicates_start as usize..])
}
- /// Returns the predicates, minus the implicit `Self: Trait` predicate for a trait.
+ /// Returns the predicates, minus the implicit `Self: Trait` predicate and bounds of the
+ /// associated types for a trait.
#[inline]
pub fn explicit_predicates(&self) -> EarlyBinder<'_, &[Clause<'_>]> {
self.predicates.get().map_bound(|it| {
+ &it.as_slice()[self.parent_explicit_self_predicates_start as usize
+ ..self.own_assoc_ty_bounds_start as usize]
+ })
+ }
+
+ #[inline]
+ pub fn explicit_implied_predicates(&self) -> EarlyBinder<'_, &[Clause<'_>]> {
+ self.predicates.get().map_bound(|it| {
&it.as_slice()[usize::from(self.parent_is_trait)..it.len() - usize::from(self.is_trait)]
})
}
@@ -1902,26 +2029,22 @@ where
);
let sized_trait = ctx.lang_items.Sized;
- let mut predicates = Vec::new();
+ // We need to lower parents and self separately - see the comment below lowering of implicit
+ // `Sized` predicates for why.
+ let mut own_predicates = Vec::new();
+ let mut parent_predicates = Vec::new();
+ let mut own_assoc_ty_bounds = Vec::new();
+ let mut parent_assoc_ty_bounds = Vec::new();
let all_generics =
std::iter::successors(Some(&generics), |generics| generics.parent_generics())
.collect::<ArrayVec<_, 2>>();
- let mut is_trait = false;
- let mut parent_is_trait = false;
- if all_generics.len() > 1 {
- add_implicit_trait_predicate(
- interner,
- all_generics.last().unwrap().def(),
- predicate_filter,
- &mut predicates,
- &mut parent_is_trait,
- );
- }
- // We need to lower parent predicates first - see the comment below lowering of implicit `Sized` predicates
- // for why.
- let mut own_predicates_start = 0;
+ let own_implicit_trait_predicate = implicit_trait_predicate(interner, def, predicate_filter);
+ let parent_implicit_trait_predicate = if all_generics.len() > 1 {
+ implicit_trait_predicate(interner, all_generics.last().unwrap().def(), predicate_filter)
+ } else {
+ None
+ };
for &maybe_parent_generics in all_generics.iter().rev() {
- let current_def_predicates_start = predicates.len();
// Collect only diagnostics from the child, not including parents.
ctx.diagnostics.clear();
@@ -1929,15 +2052,37 @@ where
ctx.store = maybe_parent_generics.store();
for pred in maybe_parent_generics.where_predicates() {
tracing::debug!(?pred);
- predicates.extend(ctx.lower_where_predicate(
- pred,
- false,
- maybe_parent_generics,
- predicate_filter,
- ));
+ for (pred, source) in
+ ctx.lower_where_predicate(pred, false, maybe_parent_generics, predicate_filter)
+ {
+ match source {
+ GenericPredicateSource::SelfOnly => {
+ if maybe_parent_generics.def() == def {
+ own_predicates.push(pred);
+ } else {
+ parent_predicates.push(pred);
+ }
+ }
+ GenericPredicateSource::AssocTyBound => {
+ if maybe_parent_generics.def() == def {
+ own_assoc_ty_bounds.push(pred);
+ } else {
+ parent_assoc_ty_bounds.push(pred);
+ }
+ }
+ }
+ }
}
- push_const_arg_has_type_predicates(db, &mut predicates, maybe_parent_generics);
+ if maybe_parent_generics.def() == def {
+ push_const_arg_has_type_predicates(db, &mut own_predicates, maybe_parent_generics);
+ } else {
+ push_const_arg_has_type_predicates(
+ db,
+ &mut parent_predicates,
+ maybe_parent_generics,
+ );
+ }
if let Some(sized_trait) = sized_trait {
let mut add_sized_clause = |param_idx, param_id, param_data| {
@@ -1971,7 +2116,11 @@ where
}),
)),
));
- predicates.push(clause);
+ if maybe_parent_generics.def() == def {
+ own_predicates.push(clause);
+ } else {
+ parent_predicates.push(clause);
+ }
};
let parent_params_len = maybe_parent_generics.len_parent();
maybe_parent_generics.iter_self().enumerate().for_each(
@@ -1990,30 +2139,55 @@ where
// predicates before lowering the child, as a child cannot define a `?Sized` predicate for its parent.
// But we do have to lower the parent first.
}
-
- if maybe_parent_generics.def() == def {
- own_predicates_start = current_def_predicates_start as u32;
- }
}
- add_implicit_trait_predicate(interner, def, predicate_filter, &mut predicates, &mut is_trait);
-
let diagnostics = create_diagnostics(ctx.diagnostics);
+
+ // The order is:
+ //
+ // 1. parent implicit trait pred
+ // 2. parent assoc bounds
+ // 3. parent self only preds
+ // 4. own self only preds
+ // 5. own assoc ty bounds
+ // 6. own implicit trait pred
+ //
+ // The purpose of this is to index the slice of the followings, without making extra `Vec`s or
+ // iterators:
+ // - explicit self only predicates, of own or own + self
+ // - explicit predicates, of own or own + self
+ let predicates = parent_implicit_trait_predicate
+ .iter()
+ .chain(parent_assoc_ty_bounds.iter())
+ .chain(parent_predicates.iter())
+ .chain(own_predicates.iter())
+ .chain(own_assoc_ty_bounds.iter())
+ .chain(own_implicit_trait_predicate.iter())
+ .copied()
+ .collect::<Vec<_>>();
+ let parent_is_trait = parent_implicit_trait_predicate.is_some();
+ let is_trait = own_implicit_trait_predicate.is_some();
+ let parent_explicit_self_predicates_start =
+ parent_is_trait as u32 + parent_assoc_ty_bounds.len() as u32;
+ let own_predicates_start =
+ parent_explicit_self_predicates_start + parent_predicates.len() as u32;
+ let own_assoc_ty_bounds_start = own_predicates_start + own_predicates.len() as u32;
+
let predicates = GenericPredicates {
+ parent_explicit_self_predicates_start,
own_predicates_start,
+ own_assoc_ty_bounds_start,
is_trait,
parent_is_trait,
predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()),
};
return (predicates, diagnostics);
- fn add_implicit_trait_predicate<'db>(
+ fn implicit_trait_predicate<'db>(
interner: DbInterner<'db>,
def: GenericDefId,
predicate_filter: PredicateFilter,
- predicates: &mut Vec<Clause<'db>>,
- set_is_trait: &mut bool,
- ) {
+ ) -> Option<Clause<'db>> {
// For traits, add `Self: Trait` predicate. This is
// not part of the predicates that a user writes, but it
// is something that one must prove in order to invoke a
@@ -2029,8 +2203,9 @@ where
if let GenericDefId::TraitId(def_id) = def
&& predicate_filter == PredicateFilter::All
{
- *set_is_trait = true;
- predicates.push(TraitRef::identity(interner, def_id.into()).upcast(interner));
+ Some(TraitRef::identity(interner, def_id.into()).upcast(interner))
+ } else {
+ None
}
}
}
@@ -2327,7 +2502,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
let mut bounds = Vec::new();
for bound in &type_alias_data.bounds {
- ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
+ ctx.lower_type_bound(bound, self_ty, false).for_each(|(pred, _)| {
if let Some(bound) = pred
.kind()
.map_bound(|c| match c {
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index a79f547c2a..b77aeab62d 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -32,7 +32,8 @@ use crate::{
db::HirDatabase,
generics::{Generics, generics},
lower::{
- LifetimeElisionKind, PathDiagnosticCallbackData, named_associated_type_shorthand_candidates,
+ GenericPredicateSource, LifetimeElisionKind, PathDiagnosticCallbackData,
+ named_associated_type_shorthand_candidates,
},
next_solver::{
Binder, Clause, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Predicate,
@@ -853,7 +854,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
pub(super) fn assoc_type_bindings_from_type_bound<'c>(
mut self,
trait_ref: TraitRef<'db>,
- ) -> Option<impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'c, 'db>> {
+ ) -> Option<impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'c, 'db>>
+ {
let interner = self.ctx.interner;
self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| {
args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| {
@@ -921,21 +923,29 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
),
)),
));
- predicates.push(pred);
+ predicates.push((pred, GenericPredicateSource::SelfOnly));
}
}
})
}
for bound in binding.bounds.iter() {
- predicates.extend(self.ctx.lower_type_bound(
- bound,
- Ty::new_alias(
- self.ctx.interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args),
- ),
- false,
- ));
+ predicates.extend(
+ self.ctx
+ .lower_type_bound(
+ bound,
+ Ty::new_alias(
+ self.ctx.interner,
+ AliasTyKind::Projection,
+ AliasTy::new_from_args(
+ self.ctx.interner,
+ associated_ty.into(),
+ args,
+ ),
+ ),
+ false,
+ )
+ .map(|(pred, _)| (pred, GenericPredicateSource::AssocTyBound)),
+ );
}
predicates
})
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 2a3df1d32a..e17bdac68c 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -41,7 +41,8 @@ use crate::{
AdtIdWrapper, AnyImplId, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper,
CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, GeneralConstIdWrapper, OpaqueTypeKey,
RegionAssumptions, SimplifiedType, SolverContext, SolverDefIds, TraitIdWrapper,
- TypeAliasIdWrapper, UnevaluatedConst, util::explicit_item_bounds,
+ TypeAliasIdWrapper, UnevaluatedConst,
+ util::{explicit_item_bounds, explicit_item_self_bounds},
},
};
@@ -1421,7 +1422,7 @@ impl<'db> Interner for DbInterner<'db> {
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- explicit_item_bounds(self, def_id)
+ explicit_item_self_bounds(self, def_id)
.map_bound(|bounds| elaborate(self, bounds).filter_only_self())
}
@@ -1500,7 +1501,7 @@ impl<'db> Interner for DbInterner<'db> {
}
}
- predicates_of(self.db, def_id).explicit_predicates().map_bound(|predicates| {
+ predicates_of(self.db, def_id).explicit_implied_predicates().map_bound(|predicates| {
predicates
.iter()
.copied()
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index 34ecfed08f..9a1b476976 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -455,6 +455,21 @@ pub fn explicit_item_bounds<'db>(
clauses.map_bound(|clauses| clauses.iter().copied())
}
+pub fn explicit_item_self_bounds<'db>(
+ interner: DbInterner<'db>,
+ def_id: SolverDefId,
+) -> EarlyBinder<'db, impl DoubleEndedIterator<Item = Clause<'db>> + ExactSizeIterator> {
+ let db = interner.db();
+ let clauses = match def_id {
+ SolverDefId::TypeAliasId(type_alias) => {
+ crate::lower::type_alias_self_bounds(db, type_alias)
+ }
+ SolverDefId::InternedOpaqueTyId(id) => id.self_predicates(db),
+ _ => panic!("Unexpected GenericDefId"),
+ };
+ clauses.map_bound(|clauses| clauses.iter().copied())
+}
+
pub struct ContainsTypeErrors;
impl<'db> TypeVisitor<DbInterner<'db>> for ContainsTypeErrors {
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index a4554673cd..be6ab23ad7 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -750,3 +750,63 @@ fn main() {
"#]],
);
}
+
+#[test]
+fn regression_19339() {
+ check_infer(
+ r#"
+trait Bar {
+ type Baz;
+
+ fn baz(&self) -> Self::Baz;
+}
+
+trait Foo {
+ type Bar;
+
+ fn bar(&self) -> Self::Bar;
+}
+
+trait FooFactory {
+ type Output: Foo<Bar: Bar<Baz = u8>>;
+
+ fn foo(&self) -> Self::Output;
+
+ fn foo_rpit(&self) -> impl Foo<Bar: Bar<Baz = u8>>;
+}
+
+fn test1(foo: impl Foo<Bar: Bar<Baz = u8>>) {
+ let baz = foo.bar().baz();
+}
+
+fn test2<T: FooFactory>(factory: T) {
+ let baz = factory.foo().bar().baz();
+ let baz = factory.foo_rpit().bar().baz();
+}
+"#,
+ expect![[r#"
+ 39..43 'self': &'? Self
+ 101..105 'self': &'? Self
+ 198..202 'self': &'? Self
+ 239..243 'self': &'? Self
+ 290..293 'foo': impl Foo + ?Sized
+ 325..359 '{ ...z(); }': ()
+ 335..338 'baz': u8
+ 341..344 'foo': impl Foo + ?Sized
+ 341..350 'foo.bar()': impl Bar
+ 341..356 'foo.bar().baz()': u8
+ 385..392 'factory': T
+ 397..487 '{ ...z(); }': ()
+ 407..410 'baz': u8
+ 413..420 'factory': T
+ 413..426 'factory.foo()': <T as FooFactory>::Output
+ 413..432 'factor....bar()': <<T as FooFactory>::Output as Foo>::Bar
+ 413..438 'factor....baz()': u8
+ 448..451 'baz': u8
+ 454..461 'factory': T
+ 454..472 'factor...rpit()': impl Foo + Bar<Baz = u8> + ?Sized
+ 454..478 'factor....bar()': <impl Foo + Bar<Baz = u8> + ?Sized as Foo>::Bar
+ 454..484 'factor....baz()': u8
+ "#]],
+ );
+}