about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-21 10:06:24 +0000
committerbors <bors@rust-lang.org>2022-02-21 10:06:24 +0000
commita924ef73bce6c20b84b1350b256a923b6d36c056 (patch)
treee3635b9bc59fb9ca6b66e90635230c59f5eff7be
parent026d8ce7f5f66ba6fbb8aaf4babb533e95ee3efd (diff)
parentb59c958ba6d1a6834c8915ce8146f9a8e81557b6 (diff)
downloadrust-a924ef73bce6c20b84b1350b256a923b6d36c056.tar.gz
rust-a924ef73bce6c20b84b1350b256a923b6d36c056.zip
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.
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs103
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88382.stderr8
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-60283.rs4
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-60283.stderr42
4 files changed, 36 insertions, 121 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 84bc7cdff28..2579e4b3174 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -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");
-
-        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")]
@@ -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))
     }
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
index d06c3ec8de7..ce196dcbd86 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
@@ -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
 
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
index c63b1544a53..05315b3f9f5 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
+++ b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
@@ -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
 }
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr
deleted file mode 100644
index 34893cd8f19..00000000000
--- a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr
+++ /dev/null
@@ -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`.