Skip to content

Commit 378300a

Browse files
committed
Make diagnostics clearer for ? operators
1 parent 78a46ef commit 378300a

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed

Diff for: compiler/rustc_errors/src/diagnostic.rs

+12
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ impl DiagnosticStyledString {
7474
pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
7575
DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
7676
}
77+
78+
pub fn content(&self) -> String {
79+
self.0.iter().map(|x| x.content()).collect::<String>()
80+
}
7781
}
7882

7983
#[derive(Debug, PartialEq, Eq)]
@@ -82,6 +86,14 @@ pub enum StringPart {
8286
Highlighted(String),
8387
}
8488

89+
impl StringPart {
90+
pub fn content(&self) -> &str {
91+
match self {
92+
&StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
93+
}
94+
}
95+
}
96+
8597
impl Diagnostic {
8698
pub fn new(level: Level, message: &str) -> Self {
8799
Diagnostic::new_with_code(level, None, message)

Diff for: compiler/rustc_infer/src/infer/error_reporting/mod.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
19711971
trace: TypeTrace<'tcx>,
19721972
terr: &TypeError<'tcx>,
19731973
) -> DiagnosticBuilder<'tcx> {
1974+
use crate::traits::ObligationCauseCode::MatchExpressionArm;
1975+
19741976
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
19751977

19761978
let span = trace.cause.span(self.tcx);
@@ -2013,6 +2015,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20132015
_ => {}
20142016
}
20152017
}
2018+
if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
2019+
trace.cause.code
2020+
{
2021+
if let hir::MatchSource::TryDesugar = source {
2022+
if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
2023+
err.note(&format!(
2024+
"`?` operator cannot convert from `{}` to `{}`",
2025+
found_ty.content(),
2026+
expected_ty.content(),
2027+
));
2028+
}
2029+
}
2030+
}
20162031
err
20172032
}
20182033
FailureCode::Error0644(failure_str) => {
@@ -2585,9 +2600,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
25852600
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
25862601
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
25872602
Error0308(match source {
2588-
hir::MatchSource::TryDesugar => {
2589-
"try expression alternatives have incompatible types"
2590-
}
2603+
hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
25912604
_ => "`match` arms have incompatible types",
25922605
})
25932606
}

Diff for: src/test/ui/inference/issue-71309.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn foo(x: Result<i32, ()>) -> Result<(), ()> {
2+
let y: u32 = x?;
3+
//~^ ERROR: `?` operator has incompatible types
4+
Ok(())
5+
}
6+
7+
fn main() {}

Diff for: src/test/ui/inference/issue-71309.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: `?` operator has incompatible types
2+
--> $DIR/issue-71309.rs:2:18
3+
|
4+
LL | let y: u32 = x?;
5+
| ^^ expected `u32`, found `i32`
6+
|
7+
= note: `?` operator cannot convert from `i32` to `u32`
8+
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
9+
|
10+
LL | let y: u32 = x?.try_into().unwrap();
11+
| ++++++++++++++++++++
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.

Diff for: src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ fn missing_discourses() -> Result<isize, ()> {
66

77
fn forbidden_narratives() -> Result<isize, ()> {
88
missing_discourses()?
9-
//~^ ERROR try expression alternatives have incompatible types
9+
//~^ ERROR: `?` operator has incompatible types
1010
}
1111

1212
fn main() {}

Diff for: src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
error[E0308]: try expression alternatives have incompatible types
1+
error[E0308]: `?` operator has incompatible types
22
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
33
|
44
LL | missing_discourses()?
55
| ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
66
|
7+
= note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
78
= note: expected enum `Result<isize, ()>`
89
found type `isize`
910
help: try removing this `?`

0 commit comments

Comments
 (0)