Skip to content

Commit

Permalink
Auto merge of rust-lang#115039 - jackh726:impl_compare_add_alias_obli…
Browse files Browse the repository at this point in the history
…gations, r=aliemjay

Add projection obligations when comparing impl too

Fixes rust-lang#115033

In the test, when we ask for WF obligations of `DatasetIter<'a, ArrayBase<D>>`, we get back two important obligations: `[<D as Data>::Elem -> ?1, ?1: 'a]`. If we don't add the projection obligation, `?1` remains unconstrained.

An alternative solution would be to use unnormalized obligations, where we only have one relevant obligation: `<D as Data>::Elem: 'a`. This would leave no inference vars unconstrained.
  • Loading branch information
bors committed Aug 21, 2023
2 parents b131feb + 31032ec commit fe5f591
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
9 changes: 8 additions & 1 deletion compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,16 @@ fn compare_method_predicate_entailment<'tcx>(
continue;
};
for obligation in obligations {
debug!(?obligation);
match obligation.predicate.kind().skip_binder() {
// We need to register Projection oblgiations too, because we may end up with
// an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
// If we only register the region outlives obligation, this leads to an unconstrained var.
// See `implied_bounds_entailment_alias_var` test.
ty::PredicateKind::Clause(
ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..),
ty::ClauseKind::RegionOutlives(..)
| ty::ClauseKind::TypeOutlives(..)
| ty::ClauseKind::Projection(..),
) => ocx.register_obligation(obligation),
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
if wf_args_seen.insert(arg) {
Expand Down
32 changes: 32 additions & 0 deletions tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// check-pass

trait Data {
type Elem;
}

impl<F, S: Data<Elem = F>> Data for ArrayBase<S> {
type Elem = F;
}

struct DatasetIter<'a, R: Data> {
data: &'a R::Elem,
}

pub struct ArrayBase<S> {
data: S,
}

trait Trait {
type Item;
fn next() -> Option<Self::Item>;
}

impl<'a, D: Data> Trait for DatasetIter<'a, ArrayBase<D>> {
type Item = ();

fn next() -> Option<Self::Item> {
None
}
}

fn main() {}

0 comments on commit fe5f591

Please sign in to comment.