about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-22 15:15:43 +0200
committerGitHub <noreply@github.com>2019-08-22 15:15:43 +0200
commitaa9490bd7b646f7b62cf831c462cde45598b468f (patch)
tree5e8d148b8ec66e1106b078ec72df0f042ee3ad0c
parent6c1cdb75ab12a487daee1564beb93e7fd95eff10 (diff)
parenta710c610b2ea1550014e9f6bd20e5e4aed8a716c (diff)
Rollup merge of #63796 - estebank:opaque_future, r=Centril
Tweak E0308 on opaque types

```
error[E0308]: if and else have incompatible types
  --> file.rs:21:9
   |
18 | /     if true {
19 | |         thing_one()
   | |         ----------- expected because of this
20 | |     } else {
21 | |         thing_two()
   | |         ^^^^^^^^^^^ expected opaque type, found a different opaque type
22 | |     }.await
   | |_____- if and else have incompatible types
   |
   = note: expected type `impl std::future::Future` (opaque type)
              found type `impl std::future::Future` (opaque type)
   = note: distinct uses of `impl Trait` result in different opaque types
   = help: if both futures resolve to the same type, consider `await`ing on both of them
```

r? @Centril
CC #63167
-rw-r--r--src/librustc/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc/ty/error.rs22
-rw-r--r--src/test/ui/suggestions/opaque-type-error.rs24
-rw-r--r--src/test/ui/suggestions/opaque-type-error.stderr20
4 files changed, 62 insertions, 6 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 84687b8cab5..9be73cf3c6d 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1650,7 +1650,7 @@ impl<'tcx> ObligationCause<'tcx> {
                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
                 _ => "match arms have compatible types",
             },
-            IfExpression { .. } => "if and else have compatible types",
+            IfExpression { .. } => "if and else have incompatible types",
             IfExpressionWithNoElse => "if missing an else returns ()",
             MainFunctionType => "`main` function has the correct type",
             StartFunctionType => "`start` function has the correct type",
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index d6d17a67e01..c70006b68d6 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -247,13 +247,15 @@ impl<'tcx> ty::TyS<'tcx> {
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    pub fn note_and_explain_type_err(self,
-                                     db: &mut DiagnosticBuilder<'_>,
-                                     err: &TypeError<'tcx>,
-                                     sp: Span) {
+    pub fn note_and_explain_type_err(
+        self,
+        db: &mut DiagnosticBuilder<'_>,
+        err: &TypeError<'tcx>,
+        sp: Span,
+    ) {
         use self::TypeError::*;
 
-        match err.clone() {
+        match err {
             Sorts(values) => {
                 let expected_str = values.expected.sort_string(self);
                 let found_str = values.found.sort_string(self);
@@ -261,6 +263,16 @@ impl<'tcx> TyCtxt<'tcx> {
                     db.note("no two closures, even if identical, have the same type");
                     db.help("consider boxing your closure and/or using it as a trait object");
                 }
+                if expected_str == found_str && expected_str == "opaque type" { // Issue #63167
+                    db.note("distinct uses of `impl Trait` result in different opaque types");
+                    let e_str = values.expected.to_string();
+                    let f_str = values.found.to_string();
+                    if &e_str == &f_str && &e_str == "impl std::future::Future" {
+                        // FIXME: use non-string based check.
+                        db.help("if both `Future`s have the same `Output` type, consider \
+                                 `.await`ing on both of them");
+                    }
+                }
                 if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) =
                        (&values.found.sty, &values.expected.sty) // Issue #53280
                 {
diff --git a/src/test/ui/suggestions/opaque-type-error.rs b/src/test/ui/suggestions/opaque-type-error.rs
new file mode 100644
index 00000000000..979bb60d48c
--- /dev/null
+++ b/src/test/ui/suggestions/opaque-type-error.rs
@@ -0,0 +1,24 @@
+// edition:2018
+use core::future::Future;
+
+async fn base_thing() -> Result<(), ()> {
+    Ok(())
+}
+
+fn thing_one() -> impl Future<Output = Result<(), ()>> {
+    base_thing()
+}
+
+fn thing_two() -> impl Future<Output = Result<(), ()>> {
+    base_thing()
+}
+
+async fn thing() -> Result<(), ()> {
+    if true {
+        thing_one()
+    } else {
+        thing_two() //~ ERROR if and else have incompatible types
+    }.await
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr
new file mode 100644
index 00000000000..3c9ea05aece
--- /dev/null
+++ b/src/test/ui/suggestions/opaque-type-error.stderr
@@ -0,0 +1,20 @@
+error[E0308]: if and else have incompatible types
+  --> $DIR/opaque-type-error.rs:20:9
+   |
+LL | /     if true {
+LL | |         thing_one()
+   | |         ----------- expected because of this
+LL | |     } else {
+LL | |         thing_two()
+   | |         ^^^^^^^^^^^ expected opaque type, found a different opaque type
+LL | |     }.await
+   | |_____- if and else have incompatible types
+   |
+   = note: expected type `impl std::future::Future` (opaque type)
+              found type `impl std::future::Future` (opaque type)
+   = note: distinct uses of `impl Trait` result in different opaque types
+   = help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.