about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-04-12 20:36:13 +0200
committerGitHub <noreply@github.com>2019-04-12 20:36:13 +0200
commit2bc127dcc7f97cdbf5950ed461b05f60f198c278 (patch)
tree5c7d4cd8885dbd807ae7af4ddf316586d8f47561
parent8f111951a19ab5e63ac347b2d029216c4e061cd4 (diff)
parent16592f691b71802f8876a4f087cdc22a21869836 (diff)
downloadrust-2bc127dcc7f97cdbf5950ed461b05f60f198c278.tar.gz
rust-2bc127dcc7f97cdbf5950ed461b05f60f198c278.zip
Rollup merge of #59859 - davidtwco:issue-59756, r=cramertj
Suggest removing `?` to resolve type errors.

Fixes #59756.
-rw-r--r--src/librustc/infer/error_reporting/mod.rs28
-rw-r--r--src/librustc/traits/mod.rs1
-rw-r--r--src/librustc/traits/structural_impls.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs1
-rw-r--r--src/test/ui/issue-59756.fixed17
-rw-r--r--src/test/ui/issue-59756.rs17
-rw-r--r--src/test/ui/issue-59756.stderr15
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr5
8 files changed, 84 insertions, 2 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 19663161fe3..9c899fab59e 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -604,13 +604,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 source,
                 ref prior_arms,
                 last_ty,
+                discrim_hir_id,
                 ..
             } => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
                     let msg = "`if let` arms have incompatible types";
                     err.span_label(cause.span, msg);
                 }
-                hir::MatchSource::TryDesugar => {}
+                hir::MatchSource::TryDesugar => {
+                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
+                        let discrim_expr = self.tcx.hir().expect_expr_by_hir_id(discrim_hir_id);
+                        let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.node {
+                            let arg_expr = args.first().expect("try desugaring call w/out arg");
+                            self.in_progress_tables.and_then(|tables| {
+                                tables.borrow().expr_ty_opt(arg_expr)
+                            })
+                        } else {
+                            bug!("try desugaring w/out call expr as discriminant");
+                        };
+
+                        match discrim_ty {
+                            Some(ty) if expected == ty => {
+                                let source_map = self.tcx.sess.source_map();
+                                err.span_suggestion(
+                                    source_map.end_point(cause.span),
+                                    "try removing this `?`",
+                                    "".to_string(),
+                                    Applicability::MachineApplicable,
+                                );
+                            },
+                            _ => {},
+                        }
+                    }
+                }
                 _ => {
                     let msg = "`match` arms have incompatible types";
                     err.span_label(cause.span, msg);
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d91c08b070a..b875bfdfa9f 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -226,6 +226,7 @@ pub enum ObligationCauseCode<'tcx> {
         source: hir::MatchSource,
         prior_arms: Vec<Span>,
         last_ty: Ty<'tcx>,
+        discrim_hir_id: hir::HirId,
     },
 
     /// Computing common supertype in the pattern guard for the arms of a match expression
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index f3a800bf46d..0711f3539e5 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -519,6 +519,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                 source,
                 ref prior_arms,
                 last_ty,
+                discrim_hir_id,
             } => {
                 tcx.lift(&last_ty).map(|last_ty| {
                     super::MatchExpressionArm {
@@ -526,6 +527,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                         source,
                         prior_arms: prior_arms.clone(),
                         last_ty,
+                        discrim_hir_id,
                     }
                 })
             }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index affd3a2d16a..032821e6d42 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -732,6 +732,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                         source: match_src,
                         prior_arms: other_arms.clone(),
                         last_ty: prior_arm_ty.unwrap(),
+                        discrim_hir_id: discrim.hir_id,
                     })
                 };
                 coercion.coerce(self, &cause, &arm.body, arm_ty);
diff --git a/src/test/ui/issue-59756.fixed b/src/test/ui/issue-59756.fixed
new file mode 100644
index 00000000000..7b55d0f17e6
--- /dev/null
+++ b/src/test/ui/issue-59756.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+struct A;
+struct B;
+
+fn foo() -> Result<A, B> {
+    Ok(A)
+}
+
+fn bar() -> Result<A, B> {
+    foo()
+    //~^ ERROR try expression alternatives have incompatible types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59756.rs b/src/test/ui/issue-59756.rs
new file mode 100644
index 00000000000..cccae396b72
--- /dev/null
+++ b/src/test/ui/issue-59756.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+struct A;
+struct B;
+
+fn foo() -> Result<A, B> {
+    Ok(A)
+}
+
+fn bar() -> Result<A, B> {
+    foo()?
+    //~^ ERROR try expression alternatives have incompatible types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-59756.stderr b/src/test/ui/issue-59756.stderr
new file mode 100644
index 00000000000..d46232874fd
--- /dev/null
+++ b/src/test/ui/issue-59756.stderr
@@ -0,0 +1,15 @@
+error[E0308]: try expression alternatives have incompatible types
+  --> $DIR/issue-59756.rs:13:5
+   |
+LL |     foo()?
+   |     ^^^^^-
+   |     |    |
+   |     |    help: try removing this `?`
+   |     expected enum `std::result::Result`, found struct `A`
+   |
+   = note: expected type `std::result::Result<A, B>`
+              found type `A`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index 8f36a3f9618..bf453571479 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,7 +2,10 @@ error[E0308]: try expression alternatives have incompatible types
   --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
    |
 LL |     missing_discourses()?
-   |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found isize
+   |     ^^^^^^^^^^^^^^^^^^^^-
+   |     |                   |
+   |     |                   help: try removing this `?`
+   |     expected enum `std::result::Result`, found isize
    |
    = note: expected type `std::result::Result<isize, ()>`
               found type `isize`