Auto merge of #94108 - compiler-errors:just-confirmation-normalization, r=jackh726

Normalize obligation and expected trait_refs in confirm_poly_trait_refs

Consolidate normalization the obligation and expected trait refs in `confirm_poly_trait_refs`. Also, _always_ normalize these trait refs -- we were already normalizing the obligation trait ref when confirming closure and generator candidates, but this does it for fn pointer confirmation as well.

This presumably does more work in the case that the obligation's trait ref is already normalized, but we can see from the perf runs in #94070, it actually (paradoxically, perhaps) improves performance when paired with logic that normalizes projections in fulfillment loop.
This commit is contained in:
bors 2022-02-21 10:06:24 +00:00
commit a924ef73bc
4 changed files with 36 additions and 121 deletions

View File

@ -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(
@ -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");
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "generator candidate obligations");
obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
obligation.predicate.to_poly_trait_ref(),
trait_ref,
)?);
Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations })
Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
}
#[instrument(skip(self), level = "debug")]
@ -657,44 +627,15 @@ 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))
@ -702,7 +643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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,
@ -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))
}

View File

@ -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>) -> _`
| |
| 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

View File

@ -1,3 +1,5 @@
// check-pass
pub trait Trait<'a> {
type Item;
}
@ -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
}

View File

@ -1,42 +0,0 @@
error[E0631]: type mismatch in function arguments
--> $DIR/issue-60283.rs:17:13
|
LL | foo((), drop)
| --- ^^^^
| | |
| | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
| | found signature of `fn(()) -> _`
| required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/issue-60283.rs:12:16
|
LL | pub fn foo<T, F>(_: T, _: F)
| --- required by a bound in this
...
LL | F: for<'a> FnMut(<T as Trait<'a>>::Item),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
--> $DIR/issue-60283.rs:17:13
|
LL | foo((), drop)
| --- ^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
note: required by a bound in `std::mem::drop`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | pub fn drop<T>(_x: T) {}
| ^ required by this bound in `std::mem::drop`
help: consider further restricting the associated type
|
LL | fn main() where <() as Trait<'_>>::Item: Sized {
| ++++++++++++++++++++++++++++++++++++
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0631.
For more information about an error, try `rustc --explain E0277`.