diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 063246f79fe36..1b67e3319a917 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1604,6 +1604,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>, ) -> DiagnosticBuilder<'tcx> { + use crate::traits::ObligationCauseCode::MatchExpressionArm; debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); let span = trace.cause.span(self.tcx); @@ -1620,7 +1621,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str) } FailureCode::Error0308(failure_str) => { - struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str) + let mut diag = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str); + if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = + trace.cause.code + { + if let hir::MatchSource::TryDesugar = source { + if let Some((expected_ty, found_ty)) = self.values_str(&trace.values) { + diag.note(&format!( + "`?` operator cannot convert from `{}` to `{}`", + found_ty.content(), + expected_ty.content() + )); + diag.help( + "`?` operator unwraps `Result` or `Option` \ + and propagates its `Err` or `None`", + ); + } + } + } + diag } FailureCode::Error0644(failure_str) => { struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str) @@ -2088,9 +2107,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { hir::MatchSource::IfLetDesugar { .. } => { "`if let` arms have incompatible types" } - hir::MatchSource::TryDesugar => { - "try expression alternatives have incompatible types" - } + hir::MatchSource::TryDesugar => "`?` operator has incompatible types", _ => "`match` arms have incompatible types", }) } diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs index bb74f0e0dc3c7..35402dff67553 100644 --- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs +++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs @@ -6,7 +6,7 @@ fn missing_discourses() -> Result { fn forbidden_narratives() -> Result { missing_discourses()? - //~^ ERROR try expression alternatives have incompatible types + //~^ ERROR: `?` operator has incompatible types } fn main() {} 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 9ca983df30af5..ca202613c320e 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 @@ -1,9 +1,11 @@ -error[E0308]: try expression alternatives have incompatible types +error[E0308]: `?` operator has incompatible types --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5 | LL | missing_discourses()? | ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `isize` | + = note: `?` operator cannot convert from `isize` to `std::result::Result` + = help: `?` operator unwraps `Result` or `Option` and propagates its `Err` or `None` = note: expected enum `std::result::Result` found type `isize` help: try removing this `?` diff --git a/src/test/ui/issues/issue-59756.rs b/src/test/ui/issues/issue-59756.rs index d6df0592be32c..e08492eda0880 100644 --- a/src/test/ui/issues/issue-59756.rs +++ b/src/test/ui/issues/issue-59756.rs @@ -15,7 +15,7 @@ fn foo() -> Result { fn bar() -> Result { foo()? - //~^ ERROR try expression alternatives have incompatible types [E0308] + //~^ ERROR `?` operator has incompatible types [E0308] } fn main() {} diff --git a/src/test/ui/issues/issue-71309.rs b/src/test/ui/issues/issue-71309.rs new file mode 100644 index 0000000000000..c31107d8fed05 --- /dev/null +++ b/src/test/ui/issues/issue-71309.rs @@ -0,0 +1,7 @@ +fn foo(x: Result) -> Result<(), ()> { + let y: u32 = x?; + //~^ ERROR: `?` operator has incompatible types + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/issues/issue-71309.stderr b/src/test/ui/issues/issue-71309.stderr new file mode 100644 index 0000000000000..5c05cf435ec44 --- /dev/null +++ b/src/test/ui/issues/issue-71309.stderr @@ -0,0 +1,16 @@ +error[E0308]: `?` operator has incompatible types + --> $DIR/issue-71309.rs:2:18 + | +LL | let y: u32 = x?; + | ^^ expected `u32`, found `i32` + | + = note: `?` operator cannot convert from `i32` to `u32` + = help: `?` operator unwraps `Result` or `Option` and propagates its `Err` or `None` +help: you can convert an `i32` to `u32` and panic if the converted value wouldn't fit + | +LL | let y: u32 = x?.try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.