Skip to content

Commit

Permalink
Rollup merge of #86382 - JohnTitor:try-desugar, r=estebank
Browse files Browse the repository at this point in the history
Make diagnostics clearer for `?` operators

Re-submission of #75029, fixes #71309
This also revives the `content` methods removed by #83185.
r? `@estebank`
  • Loading branch information
JohnTitor committed Sep 17, 2021
2 parents 78a46ef + 378300a commit f4f7704
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 5 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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)
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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",
})
}
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/inference/issue-71309.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn foo(x: Result<i32, ()>) -> Result<(), ()> {
let y: u32 = x?;
//~^ ERROR: `?` operator has incompatible types
Ok(())
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/inference/issue-71309.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
@@ -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 `?`
Expand Down

0 comments on commit f4f7704

Please sign in to comment.