Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21915 from ChayimFriedman2/hang
fix: Fix a cycle in bounds lowering
Shoyu Vanilla (Flint) 8 weeks ago
parent 689fa85 · parent 7c4af83 · commit df8a807
-rw-r--r--crates/hir-ty/src/builtin_derive.rs15
-rw-r--r--crates/hir-ty/src/display.rs4
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs10
-rw-r--r--crates/hir-ty/src/infer/expr.rs2
-rw-r--r--crates/hir-ty/src/infer/path.rs2
-rw-r--r--crates/hir-ty/src/lower.rs103
-rw-r--r--crates/hir-ty/src/method_resolution.rs2
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs4
-rw-r--r--crates/hir-ty/src/method_resolution/probe.rs2
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs92
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs2
-rw-r--r--crates/hir-ty/src/specialization.rs2
-rw-r--r--crates/hir-ty/src/tests/regression.rs15
-rw-r--r--crates/hir/src/display.rs4
-rw-r--r--crates/hir/src/lib.rs2
15 files changed, 134 insertions, 127 deletions
diff --git a/crates/hir-ty/src/builtin_derive.rs b/crates/hir-ty/src/builtin_derive.rs
index 92629b7a05..eb3922f4b6 100644
--- a/crates/hir-ty/src/builtin_derive.rs
+++ b/crates/hir-ty/src/builtin_derive.rs
@@ -174,8 +174,11 @@ pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) ->
if matches!(loc.adt, AdtId::EnumId(_)) {
// Enums don't have extra bounds.
GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
- Clauses::new_from_slice(adt_predicates.explicit_predicates().skip_binder())
- .store(),
+ Clauses::new_from_iter(
+ interner,
+ adt_predicates.own_explicit_predicates().skip_binder(),
+ )
+ .store(),
))
} else {
simple_trait_predicates(interner, loc, generic_params, adt_predicates, trait_id)
@@ -191,7 +194,7 @@ pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) ->
));
};
let duplicated_bounds =
- adt_predicates.explicit_predicates().iter_identity_copied().filter_map(|pred| {
+ adt_predicates.explicit_predicates().iter_identity().filter_map(|pred| {
let mentions_pointee =
pred.visit_with(&mut MentionsPointee { pointee_param_idx }).is_break();
if !mentions_pointee {
@@ -212,7 +215,7 @@ pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) ->
interner,
adt_predicates
.explicit_predicates()
- .iter_identity_copied()
+ .iter_identity()
.chain(duplicated_bounds)
.chain(unsize_bound),
)
@@ -313,7 +316,7 @@ fn simple_trait_predicates<'db>(
interner,
adt_predicates
.explicit_predicates()
- .iter_identity_copied()
+ .iter_identity()
.chain(extra_predicates)
.chain(assoc_type_bounds),
)
@@ -440,7 +443,7 @@ mod tests {
format_to!(
predicates,
"{}\n\n",
- preds.iter().format_with("\n", |pred, formatter| formatter(&format_args!(
+ preds.format_with("\n", |pred, formatter| formatter(&format_args!(
"{pred:?}"
))),
);
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index d680588645..0c4e34db7d 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -640,7 +640,7 @@ fn write_projection<'db>(
// FIXME: We shouldn't use `param.id`, it should be removed. We should know the
// `GenericDefId` from the formatted type (store it inside the `HirFormatter`).
let bounds = GenericPredicates::query_all(f.db, param.id.parent())
- .iter_identity_copied()
+ .iter_identity()
.filter(|wc| {
let ty = match wc.kind().skip_binder() {
ClauseKind::Trait(tr) => tr.self_ty(),
@@ -1466,7 +1466,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
}
TypeParamProvenance::ArgumentImplTrait => {
let bounds = GenericPredicates::query_all(f.db, param.id.parent())
- .iter_identity_copied()
+ .iter_identity()
.filter(|wc| match wc.kind().skip_binder() {
ClauseKind::Trait(tr) => tr.self_ty() == *self,
ClauseKind::Projection(proj) => proj.self_ty() == *self,
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index 4c300affd8..e70918f8e1 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -141,7 +141,7 @@ 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_copied()).any(|pred| {
+ elaborate::elaborate(interner, predicates.iter_identity()).any(|pred| {
match pred.kind().skip_binder() {
ClauseKind::Trait(trait_pred) => {
if sized == trait_pred.def_id().0
@@ -164,7 +164,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
// 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_copied()
+ .iter_identity()
.any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No))
}
@@ -360,8 +360,8 @@ where
cb(MethodViolationCode::UndispatchableReceiver)?;
}
- let predicates = GenericPredicates::query_own(db, func.into());
- for pred in predicates.iter_identity_copied() {
+ let predicates = GenericPredicates::query_own_explicit(db, func.into());
+ for pred in predicates.iter_identity() {
let pred = pred.kind().skip_binder();
if matches!(pred, ClauseKind::TypeOutlives(_)) {
@@ -459,7 +459,7 @@ fn receiver_is_dispatchable<'db>(
clauses: Clauses::new_from_iter(
interner,
generic_predicates
- .iter_identity_copied()
+ .iter_identity()
.chain([unsize_predicate.upcast(interner), trait_predicate.upcast(interner)])
.chain(meta_sized_predicate),
),
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index dc57b1d1c2..ee34a30eba 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -2158,7 +2158,7 @@ impl<'db> InferenceContext<'_, 'db> {
);
let param_env = self.table.param_env;
self.table.register_predicates(clauses_as_obligations(
- generic_predicates.iter_instantiated_copied(self.interner(), parameters.as_slice()),
+ generic_predicates.iter_instantiated(self.interner(), parameters.as_slice()),
ObligationCause::new(),
param_env,
));
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 71d68ccd47..3cadc8e933 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -228,7 +228,7 @@ impl<'db> InferenceContext<'_, 'db> {
let predicates = GenericPredicates::query_all(self.db, def);
let param_env = self.table.param_env;
self.table.register_predicates(clauses_as_obligations(
- predicates.iter_instantiated_copied(interner, subst.as_slice()),
+ predicates.iter_instantiated(interner, subst.as_slice()),
ObligationCause::new(),
param_env,
));
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 7259099107..71a7db6559 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -2016,17 +2016,21 @@ 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 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`.
+ // The order is the following:
+ //
+ // 1. If `has_trait_implied_predicate == true`, the implicit trait predicate.
+ // 2. The bounds of the associated types of the parents, coming from `Trait<Assoc: Trait>`.
+ // Note: associated type bounds from `Self::Assoc: Trait` on traits *won't* be included
+ // here, they are in 3.
+ // 3. The explicit, self-only predicates for the parent.
+ // 4. The explicit, self-only trait predicate for the child,
+ // 5. The bounds of the associated types of the child.
predicates: StoredEarlyBinder<StoredClauses>,
+ // Keep this ordered according to the above.
+ has_trait_implied_predicate: bool,
parent_explicit_self_predicates_start: u32,
own_predicates_start: u32,
own_assoc_ty_bounds_start: u32,
- is_trait: bool,
- parent_is_trait: bool,
}
#[salsa::tracked]
@@ -2065,11 +2069,10 @@ impl GenericPredicates {
let len = predicates.get().skip_binder().len() as u32;
Self {
predicates,
+ has_trait_implied_predicate: false,
parent_explicit_self_predicates_start: 0,
own_predicates_start: 0,
own_assoc_ty_bounds_start: len,
- is_trait: false,
- parent_is_trait: false,
}
}
@@ -2082,58 +2085,68 @@ impl GenericPredicates {
pub fn query_all<'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
- ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
Self::query(db, def).all_predicates()
}
#[inline]
- pub fn query_own<'db>(
+ pub fn query_own_explicit<'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
- ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
- Self::query(db, def).own_predicates()
+ ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
+ Self::query(db, def).own_explicit_predicates()
}
#[inline]
pub fn query_explicit<'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
- ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
+ ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
Self::query(db, def).explicit_predicates()
}
#[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()
+ pub fn all_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
+ self.predicates.get().map_bound(|it| it.as_slice().iter().copied())
}
#[inline]
- pub fn all_predicates(&self) -> EarlyBinder<'_, &[Clause<'_>]> {
- self.predicates.get().map_bound(|it| it.as_slice())
+ pub fn own_explicit_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
+ self.predicates
+ .get()
+ .map_bound(|it| it.as_slice()[self.own_predicates_start as usize..].iter().copied())
}
#[inline]
- pub fn own_predicates(&self) -> EarlyBinder<'_, &[Clause<'_>]> {
- self.predicates.get().map_bound(|it| &it.as_slice()[self.own_predicates_start as usize..])
+ pub fn explicit_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
+ self.predicates.get().map_bound(|it| {
+ it.as_slice()[usize::from(self.has_trait_implied_predicate)..].iter().copied()
+ })
}
- /// 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<'_>]> {
+ pub fn explicit_non_assoc_types_predicates(
+ &self,
+ ) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
self.predicates.get().map_bound(|it| {
- &it.as_slice()[self.parent_explicit_self_predicates_start as usize
+ it.as_slice()[self.parent_explicit_self_predicates_start as usize
..self.own_assoc_ty_bounds_start as usize]
+ .iter()
+ .copied()
})
}
#[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)]
+ pub fn explicit_assoc_types_predicates(
+ &self,
+ ) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
+ self.predicates.get().map_bound(|predicates| {
+ let predicates = predicates.as_slice();
+ predicates[usize::from(self.has_trait_implied_predicate)
+ ..self.parent_explicit_self_predicates_start as usize]
+ .iter()
+ .copied()
+ .chain(predicates[self.own_assoc_ty_bounds_start as usize..].iter().copied())
})
}
}
@@ -2142,10 +2155,8 @@ pub(crate) fn param_env_from_predicates<'db>(
interner: DbInterner<'db>,
predicates: &'db GenericPredicates,
) -> ParamEnv<'db> {
- let clauses = rustc_type_ir::elaborate::elaborate(
- interner,
- predicates.all_predicates().iter_identity_copied(),
- );
+ let clauses =
+ rustc_type_ir::elaborate::elaborate(interner, predicates.all_predicates().iter_identity());
let clauses = Clauses::new_from_iter(interner, clauses);
// FIXME: We should normalize projections here, like rustc does.
@@ -2290,42 +2301,28 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
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(own_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 has_trait_implied_predicate =
+ parent_implicit_trait_predicate.is_some() || own_implicit_trait_predicate.is_some();
let parent_explicit_self_predicates_start =
- parent_is_trait as u32 + parent_assoc_ty_bounds.len() as u32;
+ has_trait_implied_predicate 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 {
+ has_trait_implied_predicate,
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);
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 05b9ea5d74..b18e48c1fe 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -324,7 +324,7 @@ impl<'db> InferenceTable<'db> {
// any late-bound regions appearing in its bounds.
let bounds = GenericPredicates::query_all(self.db, method_item.into());
let bounds = clauses_as_obligations(
- bounds.iter_instantiated_copied(interner, args.as_slice()),
+ bounds.iter_instantiated(interner, args.as_slice()),
ObligationCause::new(),
self.param_env,
);
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index ec589085a8..94c70c29f7 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -136,7 +136,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
);
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(
GenericPredicates::query_all(self.db(), self.candidate.into())
- .iter_instantiated_copied(self.interner(), filler_args.as_slice()),
+ .iter_instantiated(self.interner(), filler_args.as_slice()),
);
// Unify the (adjusted) self type with what the method expects.
@@ -509,7 +509,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
let def_id = self.candidate;
let method_predicates = clauses_as_obligations(
GenericPredicates::query_all(self.db(), def_id.into())
- .iter_instantiated_copied(self.interner(), all_args),
+ .iter_instantiated(self.interner(), all_args),
ObligationCause::new(),
self.ctx.table.param_env,
);
diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs
index 8c76bfbc07..3604076ccd 100644
--- a/crates/hir-ty/src/method_resolution/probe.rs
+++ b/crates/hir-ty/src/method_resolution/probe.rs
@@ -1595,7 +1595,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
// Check whether the impl imposes obligations we have to worry about.
let impl_bounds = GenericPredicates::query_all(self.db(), impl_def_id.into());
let impl_bounds = clauses_as_obligations(
- impl_bounds.iter_instantiated_copied(self.interner(), impl_args.as_slice()),
+ impl_bounds.iter_instantiated(self.interner(), impl_args.as_slice()),
ObligationCause::new(),
self.param_env(),
);
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 5b81c7675d..622648bc8d 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -1439,81 +1439,55 @@ impl<'db> Interner for DbInterner<'db> {
}
}
- #[tracing::instrument(level = "debug", skip(self), ret)]
fn predicates_of(
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- predicates_of(self.db, def_id).all_predicates().map_bound(|it| it.iter().copied())
+ predicates_of(self.db, def_id).all_predicates()
}
- #[tracing::instrument(level = "debug", skip(self), ret)]
fn own_predicates_of(
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- predicates_of(self.db, def_id).own_predicates().map_bound(|it| it.iter().copied())
+ predicates_of(self.db, def_id).own_explicit_predicates()
}
- #[tracing::instrument(skip(self), ret)]
fn explicit_super_predicates_of(
self,
def_id: Self::TraitId,
) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
- let is_self = |ty: Ty<'db>| match ty.kind() {
- rustc_type_ir::TyKind::Param(param) => param.index == 0,
- _ => false,
- };
-
- GenericPredicates::query_explicit(self.db, def_id.0.into()).map_bound(move |predicates| {
- predicates
- .iter()
- .copied()
- .filter(move |p| match p.kind().skip_binder() {
- // rustc has the following assertion:
- // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
- ClauseKind::Trait(it) => is_self(it.self_ty()),
- ClauseKind::TypeOutlives(it) => is_self(it.0),
- ClauseKind::Projection(it) => is_self(it.self_ty()),
- ClauseKind::HostEffect(it) => is_self(it.self_ty()),
- _ => false,
- })
- .map(|p| (p, Span::dummy()))
- })
+ GenericPredicates::query(self.db, def_id.0.into())
+ .explicit_non_assoc_types_predicates()
+ .map_bound(move |predicates| {
+ predicates.filter(|p| is_clause_at_ty(p, is_ty_self)).map(|p| (p, Span::dummy()))
+ })
}
- #[tracing::instrument(skip(self), ret)]
fn explicit_implied_predicates_of(
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
- fn is_self_or_assoc(ty: Ty<'_>) -> bool {
- match ty.kind() {
- rustc_type_ir::TyKind::Param(param) => param.index == 0,
- rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias) => {
- is_self_or_assoc(alias.self_ty())
- }
- _ => false,
+ fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
+ // FIXME: Is this correct wrt. combined kind of assoc type bounds, i.e. `where Self::Assoc: Trait<Assoc2: Trait>`
+ // wrt. `Assoc2`, which we should exclude?
+ if let TyKind::Alias(AliasTyKind::Projection, alias) = ty.kind() {
+ is_ty_assoc_of_self(alias.self_ty())
+ } else {
+ is_ty_self(ty)
}
}
- predicates_of(self.db, def_id).explicit_implied_predicates().map_bound(|predicates| {
- predicates
- .iter()
- .copied()
- .filter(|p| match p.kind().skip_binder() {
- ClauseKind::Trait(it) => is_self_or_assoc(it.self_ty()),
- ClauseKind::TypeOutlives(it) => is_self_or_assoc(it.0),
- ClauseKind::Projection(it) => is_self_or_assoc(it.self_ty()),
- ClauseKind::HostEffect(it) => is_self_or_assoc(it.self_ty()),
- // FIXME: Not sure is this correct to allow other clauses but we might replace
- // `generic_predicates_ns` query here with something closer to rustc's
- // `implied_bounds_with_filter`, which is more granular lowering than this
- // "lower at once and then filter" implementation.
- _ => true,
- })
- .map(|p| (p, Span::dummy()))
- })
+ let predicates = predicates_of(self.db, def_id);
+ let non_assoc_types = predicates
+ .explicit_non_assoc_types_predicates()
+ .skip_binder()
+ .filter(|p| is_clause_at_ty(p, is_ty_self));
+ let assoc_types = predicates
+ .explicit_assoc_types_predicates()
+ .skip_binder()
+ .filter(|p| is_clause_at_ty(p, is_ty_assoc_of_self));
+ EarlyBinder::bind(non_assoc_types.chain(assoc_types).map(|it| (it, Span::dummy())))
}
fn impl_super_outlives(
@@ -2294,6 +2268,24 @@ impl<'db> Interner for DbInterner<'db> {
}
}
+fn is_ty_self(ty: Ty<'_>) -> bool {
+ match ty.kind() {
+ TyKind::Param(param) => param.index == 0,
+ _ => false,
+ }
+}
+fn is_clause_at_ty(p: &Clause<'_>, filter: impl FnOnce(Ty<'_>) -> bool) -> bool {
+ match p.kind().skip_binder() {
+ // rustc has the following assertion:
+ // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
+ ClauseKind::Trait(it) => filter(it.self_ty()),
+ ClauseKind::TypeOutlives(it) => filter(it.0),
+ ClauseKind::Projection(it) => filter(it.self_ty()),
+ ClauseKind::HostEffect(it) => filter(it.self_ty()),
+ _ => false,
+ }
+}
+
impl<'db> DbInterner<'db> {
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
where
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 192cdb70ae..8e892b65ea 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -696,7 +696,7 @@ impl<'db> Ty<'db> {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::ArgumentImplTrait => {
let predicates = GenericPredicates::query_all(db, param.id.parent())
- .iter_identity_copied()
+ .iter_identity()
.filter(|wc| match wc.kind().skip_binder() {
ClauseKind::Trait(tr) => tr.self_ty() == self,
ClauseKind::Projection(pred) => pred.self_ty() == self,
diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs
index 90cbcfea6a..8bc6c51fae 100644
--- a/crates/hir-ty/src/specialization.rs
+++ b/crates/hir-ty/src/specialization.rs
@@ -109,7 +109,7 @@ fn specializes_query(
// only be referenced via projection predicates.
ocx.register_obligations(clauses_as_obligations(
GenericPredicates::query_all(db, parent_impl_def_id.into())
- .iter_instantiated_copied(interner, parent_args.as_slice()),
+ .iter_instantiated(interner, parent_args.as_slice()),
cause.clone(),
param_env,
));
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index e4fc7e56c6..d3dfc44c22 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2841,3 +2841,18 @@ fn wrapped_abs<T: SelfAbs<Output = T>>(v: T) -> T {
"#,
);
}
+
+#[test]
+fn regression_21899() {
+ check_no_mismatches(
+ r#"
+trait B where
+ Self::T: B,
+{
+ type T;
+}
+
+fn foo<T: B>(v: T::T) {}
+ "#,
+ );
+}
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 4bfdd239f9..53f24713cd 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -76,7 +76,7 @@ fn write_builtin_derive_impl_method<'db>(
let predicates =
hir_ty::builtin_derive::predicates(db, impl_).explicit_predicates().skip_binder();
- write_params_bounds(f, predicates)?;
+ write_params_bounds(f, &Vec::from_iter(predicates))?;
}
Ok(())
@@ -578,7 +578,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
let ty = self.ty(f.db).ty;
let predicates = GenericPredicates::query_all(f.db, self.id.parent());
let predicates = predicates
- .iter_identity_copied()
+ .iter_identity()
.filter(|wc| match wc.kind().skip_binder() {
ClauseKind::Trait(tr) => tr.self_ty() == ty,
ClauseKind::Projection(proj) => proj.self_ty() == ty,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index bc5e164830..eb5b3b37a6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -4680,7 +4680,7 @@ impl TypeParam {
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
let self_ty = self.ty(db).ty;
GenericPredicates::query_explicit(db, self.id.parent())
- .iter_identity_copied()
+ .iter_identity()
.filter_map(|pred| match &pred.kind().skip_binder() {
ClauseKind::Trait(trait_ref) if trait_ref.self_ty() == self_ty => {
Some(Trait::from(trait_ref.def_id().0))