about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2021-09-17 14:09:43 +0900
committerGitHub <noreply@github.com>2021-09-17 14:09:43 +0900
commitf4f7704eddb007c9b5b5a0c5663ab3efe778ca57 (patch)
tree8a982f7ef97c997308268d9de13532a72e313104
parent78a46efff06558674b51c10d8d81758285746ab5 (diff)
parent378300a63d1951e2718a6b0a077439fc1b14742b (diff)
downloadrust-f4f7704eddb007c9b5b5a0c5663ab3efe778ca57.tar.gz
rust-f4f7704eddb007c9b5b5a0c5663ab3efe778ca57.zip
Rollup merge of #86382 - JohnTitor:try-desugar, r=estebank
Make diagnostics clearer for `?` operators

Re-submission of #75029, fixes #71309
This also revives the `content` methods removed by #83185.
r? `@estebank`
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs19
-rw-r--r--src/test/ui/inference/issue-71309.rs7
-rw-r--r--src/test/ui/inference/issue-71309.stderr15
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs2
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr3
6 files changed, 53 insertions, 5 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 232cf4bdb7f..41a73268f46 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -74,6 +74,10 @@ impl DiagnosticStyledString {
     pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
         DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
     }
+
+    pub fn content(&self) -> String {
+        self.0.iter().map(|x| x.content()).collect::<String>()
+    }
 }
 
 #[derive(Debug, PartialEq, Eq)]
@@ -82,6 +86,14 @@ pub enum StringPart {
     Highlighted(String),
 }
 
+impl StringPart {
+    pub fn content(&self) -> &str {
+        match self {
+            &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
+        }
+    }
+}
+
 impl Diagnostic {
     pub fn new(level: Level, message: &str) -> Self {
         Diagnostic::new_with_code(level, None, message)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 1139b714d0a..b8089b2499b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1971,6 +1971,8 @@ 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);
@@ -2013,6 +2015,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         _ => {}
                     }
                 }
+                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) {
+                            err.note(&format!(
+                                "`?` operator cannot convert from `{}` to `{}`",
+                                found_ty.content(),
+                                expected_ty.content(),
+                            ));
+                        }
+                    }
+                }
                 err
             }
             FailureCode::Error0644(failure_str) => {
@@ -2585,9 +2600,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
                 Error0308(match source {
-                    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/inference/issue-71309.rs b/src/test/ui/inference/issue-71309.rs
new file mode 100644
index 00000000000..c31107d8fed
--- /dev/null
+++ b/src/test/ui/inference/issue-71309.rs
@@ -0,0 +1,7 @@
+fn foo(x: Result<i32, ()>) -> Result<(), ()> {
+    let y: u32 = x?;
+    //~^ ERROR: `?` operator has incompatible types
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/issue-71309.stderr b/src/test/ui/inference/issue-71309.stderr
new file mode 100644
index 00000000000..af8714f1c80
--- /dev/null
+++ b/src/test/ui/inference/issue-71309.stderr
@@ -0,0 +1,15 @@
+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: you can convert an `i32` to a `u32` and panic if the converted value doesn'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`.
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 bb74f0e0dc3..35402dff675 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<isize, ()> {
 
 fn forbidden_narratives() -> Result<isize, ()> {
     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 2c821aa2308..0f61e03c3b5 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,10 @@
-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 `Result`, found `isize`
    |
+   = note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
    = note: expected enum `Result<isize, ()>`
               found type `isize`
 help: try removing this `?`