Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize obligation and expected trait_refs in confirm_poly_trait_refs #94108

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 30 additions & 73 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,23 +553,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
.map_bound(|(trait_ref, _)| trait_ref);

let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
trait_ref,
)
});

obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref,
)?);
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations })
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
}

fn confirm_trait_alias_candidate(
Expand Down Expand Up @@ -616,26 +601,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");

let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs);
let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
trait_ref,
)
});

debug!(?trait_ref, ?obligations, "generator candidate obligations");

obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref,
)?);
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "generator candidate obligations");

Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations })
Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
}

#[instrument(skip(self), level = "debug")]
Expand All @@ -657,52 +627,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("closure candidate for non-closure {:?}", obligation),
};

let obligation_predicate = obligation.predicate;
let Normalized { value: obligation_predicate, mut obligations } =
ensure_sufficient_stack(|| {
normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation_predicate,
)
});

let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
ensure_sufficient_stack(|| {
normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
trait_ref,
)
});
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;

debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");

obligations.extend(trait_ref_obligations);
obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
obligation_predicate.to_poly_trait_ref(),
trait_ref,
)?);
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");

// FIXME: Chalk

if !self.tcx().sess.opts.debugging_opts.chalk {
obligations.push(Obligation::new(
nested.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind))
.to_predicate(self.tcx()),
));
}

Ok(ImplSourceClosureData { closure_def_id, substs, nested: obligations })
Ok(ImplSourceClosureData { closure_def_id, substs, nested })
}

/// In the case of closure types and fn pointers,
Expand Down Expand Up @@ -733,15 +674,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self), level = "trace")]
fn confirm_poly_trait_refs(
&mut self,
obligation_cause: ObligationCause<'tcx>,
obligation_param_env: ty::ParamEnv<'tcx>,
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &TraitObligation<'tcx>,
expected_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
// Normalize the obligation and expected trait refs together, because why not
let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } =
ensure_sufficient_stack(|| {
self.infcx.commit_unconditionally(|_| {
normalize_with_depth(
self,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
(obligation_trait_ref, expected_trait_ref),
)
})
});

self.infcx
.at(&obligation_cause, obligation_param_env)
.at(&obligation.cause, obligation.param_env)
.sup(obligation_trait_ref, expected_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map(|InferOk { mut obligations, .. }| {
obligations.extend(nested);
obligations
})
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
}

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/generic-associated-types/bugs/issue-88382.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ error[E0631]: type mismatch in function arguments
--> $DIR/issue-88382.rs:28:40
|
LL | do_something(SomeImplementation(), test);
| ------------ ^^^^ expected signature of `for<'a> fn(&mut <SomeImplementation as Iterable>::Iterator<'a>) -> _`
| ------------ ^^^^ expected signature of `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test highlights that something wonky is going on. It changes were we aren't able to normalize.

Copy link
Member Author

@compiler-errors compiler-errors Feb 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is very interesting. Possibly due to changes in the ordering of resolving the inference variable in &mut <_ as Iterable>::Iterator<'a> and normalizing it. Now that we're eagerly normalizing the trait ref, we probably are substituting that value before we have a chance to unify the argument type with something else, possibly another projection type with an inference variable.

| |
| required by a bound introduced by this call
...
LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
| ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
| ------------------------------------------------- found signature of `for<'r, 'a> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _`
|
note: required by a bound in `do_something`
--> $DIR/issue-88382.rs:22:56
--> $DIR/issue-88382.rs:22:48
|
LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`

error: aborting due to previous error

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/higher-rank-trait-bounds/issue-60283.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// check-pass

pub trait Trait<'a> {
type Item;
}
Expand All @@ -15,6 +17,4 @@ where

fn main() {
foo((), drop)
//~^ ERROR type mismatch in function arguments
//~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
}
42 changes: 0 additions & 42 deletions src/test/ui/higher-rank-trait-bounds/issue-60283.stderr

This file was deleted.