about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/closure.rs49
-rw-r--r--src/test/ui/generator-yielding-or-returning-itself.rs2
-rw-r--r--src/test/ui/generator-yielding-or-returning-itself.stderr24
-rw-r--r--src/test/ui/generator/type-mismatch-signature-deduction.rs6
-rw-r--r--src/test/ui/generator/type-mismatch-signature-deduction.stderr25
5 files changed, 53 insertions, 53 deletions
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 838874cc2bf..3fa192f16f3 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
-    /// everything we need to know about a closure.
+    /// everything we need to know about a closure or generator.
     ///
     /// The `cause_span` should be the span that caused us to
     /// have this expected signature, or `None` if we can't readily
@@ -262,37 +262,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let trait_ref = projection.to_poly_trait_ref(tcx);
 
-        if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() {
+        let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some();
+        let gen_trait = tcx.lang_items().gen_trait().unwrap();
+        let is_gen = gen_trait == trait_ref.def_id();
+        if !is_fn && !is_gen {
+            debug!("deduce_sig_from_projection: not fn or generator");
             return None;
         }
 
-        let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
-        let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
-        debug!(
-            "deduce_sig_from_projection: arg_param_ty {:?}",
-            arg_param_ty
-        );
+        if is_gen {
+            // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
+            // associated item and not yield.
+            let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id;
+            if return_assoc_item != projection.projection_def_id() {
+                debug!("deduce_sig_from_projection: not return assoc item of generator");
+                return None;
+            }
+        }
+
+        let input_tys = if is_fn {
+            let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
+            let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
+            debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty);
 
-        let input_tys = match arg_param_ty.sty {
-            ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()),
-            _ => return None,
+            match arg_param_ty.sty {
+                ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::<Vec<_>>(),
+                _ => return None,
+            }
+        } else {
+            // Generators cannot have explicit arguments.
+            vec![]
         };
 
         let ret_param_ty = projection.skip_binder().ty;
         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
-        debug!(
-            "deduce_sig_from_projection: ret_param_ty {:?}",
-            ret_param_ty
-        );
+        debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
 
         let sig = self.tcx.mk_fn_sig(
-            input_tys,
-            ret_param_ty,
+            input_tys.iter(),
+            &ret_param_ty,
             false,
             hir::Unsafety::Normal,
             Abi::Rust,
         );
-        debug!("deduce_sig_from_projection: sig {:?}", sig);
+        debug!("deduce_sig_from_projection: sig={:?}", sig);
 
         Some(ExpectedSig { cause_span, sig })
     }
diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator-yielding-or-returning-itself.rs
index 30788e3c186..fd526679818 100644
--- a/src/test/ui/generator-yielding-or-returning-itself.rs
+++ b/src/test/ui/generator-yielding-or-returning-itself.rs
@@ -13,7 +13,7 @@ pub fn want_cyclic_generator_return<T>(_: T)
 
 fn supply_cyclic_generator_return() {
     want_cyclic_generator_return(|| {
-        //~^ ERROR type mismatch
+        //~^ ERROR closure/generator type that references itself
         if false { yield None.unwrap(); }
         None.unwrap()
     })
diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator-yielding-or-returning-itself.stderr
index 5834aed2450..42591683fe4 100644
--- a/src/test/ui/generator-yielding-or-returning-itself.stderr
+++ b/src/test/ui/generator-yielding-or-returning-itself.stderr
@@ -1,20 +1,17 @@
-error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
+error[E0644]: closure/generator type that references itself
+  --> $DIR/generator-yielding-or-returning-itself.rs:15:34
    |
-LL |     want_cyclic_generator_return(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+LL |       want_cyclic_generator_return(|| {
+   |  __________________________________^
+LL | |
+LL | |         if false { yield None.unwrap(); }
+LL | |         None.unwrap()
+LL | |     })
+   | |_____^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
            see https://github.com/rust-lang/rust/issues/46062 for more details
-note: required by `want_cyclic_generator_return`
-  --> $DIR/generator-yielding-or-returning-itself.rs:9:1
-   |
-LL | / pub fn want_cyclic_generator_return<T>(_: T)
-LL | |     where T: Generator<Yield = (), Return = T>
-LL | | {
-LL | | }
-   | |_^
 
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
   --> $DIR/generator-yielding-or-returning-itself.rs:28:5
@@ -36,4 +33,5 @@ LL | | }
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+Some errors have detailed explanations: E0271, E0644.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs
index 7774ff48f56..b9c6bc5d079 100644
--- a/src/test/ui/generator/type-mismatch-signature-deduction.rs
+++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs
@@ -2,15 +2,15 @@
 
 use std::ops::Generator;
 
-fn foo() -> impl Generator<Return = i32> { //~ ERROR type mismatch
+fn foo() -> impl Generator<Return = i32> {
     || {
         if false {
-            return Ok(6);
+            return Ok(6); //~ ERROR mismatched types [E0308]
         }
 
         yield ();
 
-        5 //~ ERROR mismatched types [E0308]
+        5
     }
 }
 
diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
index 9ebf77a02f5..35d3f95c3e9 100644
--- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr
+++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
@@ -1,23 +1,12 @@
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch-signature-deduction.rs:13:9
+  --> $DIR/type-mismatch-signature-deduction.rs:8:20
    |
-LL |         5
-   |         ^ expected enum `std::result::Result`, found integer
+LL |             return Ok(6);
+   |                    ^^^^^ expected i32, found enum `std::result::Result`
    |
-   = note: expected type `std::result::Result<{integer}, _>`
-              found type `{integer}`
+   = note: expected type `i32`
+              found type `std::result::Result<{integer}, _>`
 
-error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6 _] as std::ops::Generator>::Return == i32`
-  --> $DIR/type-mismatch-signature-deduction.rs:5:13
-   |
-LL | fn foo() -> impl Generator<Return = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found i32
-   |
-   = note: expected type `std::result::Result<{integer}, _>`
-              found type `i32`
-   = note: the return type of a function must have a statically known size
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0271, E0308.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0308`.