Make diagnostics clearer for ? operators

This commit is contained in:
Yuki Okushi 2021-06-17 06:35:42 +09:00
parent 78a46efff0
commit 378300a63d
No known key found for this signature in database
GPG Key ID: DABA5B072961C18A
6 changed files with 53 additions and 5 deletions

View File

@ -74,6 +74,10 @@ pub fn normal<S: Into<String>>(t: S) -> 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)

View File

@ -1971,6 +1971,8 @@ pub fn report_and_explain_type_error(
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 @@ pub fn report_and_explain_type_error(
_ => {}
}
}
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 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
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",
})
}

View File

@ -0,0 +1,7 @@
fn foo(x: Result<i32, ()>) -> Result<(), ()> {
let y: u32 = x?;
//~^ ERROR: `?` operator has incompatible types
Ok(())
}
fn main() {}

View File

@ -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`.

View File

@ -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() {}

View File

@ -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 `?`