about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-09-15 00:35:23 +0000
committerMichael Goulet <michael@errs.io>2022-11-03 15:52:38 +0000
commitcaa701e3c190c4d77634c9075548746e4917e56d (patch)
tree5d51fa43a97f2c9a3788be4170b5abdcb2be957d
parent060d4392b1679fa4f7323ee702a7669af281d5db (diff)
downloadrust-caa701e3c190c4d77634c9075548746e4917e56d.tar.gz
rust-caa701e3c190c4d77634c9075548746e4917e56d.zip
Elaborate supertrait obligations when deducing closure signature
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs18
-rw-r--r--src/test/ui/closures/issue-23012-supertrait-signature-inference.rs29
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr26
4 files changed, 41 insertions, 35 deletions
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index cc1191d3245..4f8ac45d5a6 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -15,6 +15,7 @@ use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use std::cmp;
@@ -226,27 +227,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_vid: ty::TyVid,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         let mut expected_sig = None;
-        // Even if we can't infer the full signature, we may be able to
-        // infer the kind. This can occur when we elaborate a predicate
-        // like `F : Fn<A>`. Note that due to subtyping we could encounter
-        // many viable options, so pick the most restrictive.
         let mut expected_kind = None;
 
-        for obligation in self.obligations_for_self_ty(expected_vid) {
+        for obligation in traits::elaborate_obligations(
+            self.tcx,
+            self.obligations_for_self_ty(expected_vid).collect(),
+        ) {
             debug!(?obligation.predicate);
             let bound_predicate = obligation.predicate.kind();
 
+            // Given a Projection predicate, we can potentially infer
+            // the complete signature.
             if expected_sig.is_none()
                 && let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
             {
-                // Given a Projection predicate, we can potentially infer
-                // the complete signature.
                 expected_sig = self.deduce_sig_from_projection(
                     Some(obligation.cause.span),
                     bound_predicate.rebind(proj_predicate),
                 );
             }
 
+            // Even if we can't infer the full signature, we may be able to
+            // infer the kind. This can occur when we elaborate a predicate
+            // like `F : Fn<A>`. Note that due to subtyping we could encounter
+            // many viable options, so pick the most restrictive.
             let trait_def_id = match bound_predicate.skip_binder() {
                 ty::PredicateKind::Projection(data) => {
                     Some(data.projection_ty.trait_def_id(self.tcx))
diff --git a/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs
new file mode 100644
index 00000000000..5899b703e7c
--- /dev/null
+++ b/src/test/ui/closures/issue-23012-supertrait-signature-inference.rs
@@ -0,0 +1,29 @@
+// check-pass
+// Checks that we can infer a closure signature even if the `FnOnce` bound is
+// a supertrait of the obligations we have currently registered for the Ty var.
+
+pub trait Receive<T, E>: FnOnce(Result<T, E>) {
+    fn receive(self, res: Result<T, E>);
+}
+
+impl<T, E, F: FnOnce(Result<T, E>)> Receive<T, E> for F {
+    fn receive(self, res: Result<T, E>) {
+        self(res)
+    }
+}
+
+pub trait Async<T, E> {
+    fn receive<F: Receive<T, E>>(self, f: F);
+}
+
+impl<T, E> Async<T, E> for Result<T, E> {
+    fn receive<F: Receive<T, E>>(self, f: F) {
+        f(self)
+    }
+}
+
+pub fn main() {
+    Ok::<u32, ()>(123).receive(|res| {
+        res.unwrap();
+    });
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
index 067ed7ea1e5..cad3e0f6677 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -1,7 +1,6 @@
+// check-pass
 // Regression test for issue #57611
 // Ensures that we don't ICE
-// FIXME: This should compile, but it currently doesn't
-// known-bug: unknown
 
 #![feature(trait_alias)]
 #![feature(type_alias_impl_trait)]
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
deleted file mode 100644
index 6344f114a91..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^^^ one type is more general than the other
-   |
-   = note: expected trait `for<'a> Fn<(&'a X,)>`
-              found trait `Fn<(&X,)>`
-note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.