Make diagnostics clearer for ?
operators
This commit is contained in:
parent
78a46efff0
commit
378300a63d
@ -74,6 +74,10 @@ impl DiagnosticStyledString {
|
|||||||
pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
|
pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
|
||||||
DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
|
DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn content(&self) -> String {
|
||||||
|
self.0.iter().map(|x| x.content()).collect::<String>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@ -82,6 +86,14 @@ pub enum StringPart {
|
|||||||
Highlighted(String),
|
Highlighted(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StringPart {
|
||||||
|
pub fn content(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
&StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Diagnostic {
|
impl Diagnostic {
|
||||||
pub fn new(level: Level, message: &str) -> Self {
|
pub fn new(level: Level, message: &str) -> Self {
|
||||||
Diagnostic::new_with_code(level, None, message)
|
Diagnostic::new_with_code(level, None, message)
|
||||||
|
@ -1971,6 +1971,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
trace: TypeTrace<'tcx>,
|
trace: TypeTrace<'tcx>,
|
||||||
terr: &TypeError<'tcx>,
|
terr: &TypeError<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
|
use crate::traits::ObligationCauseCode::MatchExpressionArm;
|
||||||
|
|
||||||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||||
|
|
||||||
let span = trace.cause.span(self.tcx);
|
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
|
err
|
||||||
}
|
}
|
||||||
FailureCode::Error0644(failure_str) => {
|
FailureCode::Error0644(failure_str) => {
|
||||||
@ -2585,9 +2600,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
|||||||
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
|
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
|
||||||
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
|
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
|
||||||
Error0308(match source {
|
Error0308(match source {
|
||||||
hir::MatchSource::TryDesugar => {
|
hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
|
||||||
"try expression alternatives have incompatible types"
|
|
||||||
}
|
|
||||||
_ => "`match` arms have incompatible types",
|
_ => "`match` arms have incompatible types",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
7
src/test/ui/inference/issue-71309.rs
Normal file
7
src/test/ui/inference/issue-71309.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fn foo(x: Result<i32, ()>) -> Result<(), ()> {
|
||||||
|
let y: u32 = x?;
|
||||||
|
//~^ ERROR: `?` operator has incompatible types
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
15
src/test/ui/inference/issue-71309.stderr
Normal file
15
src/test/ui/inference/issue-71309.stderr
Normal 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`.
|
@ -6,7 +6,7 @@ fn missing_discourses() -> Result<isize, ()> {
|
|||||||
|
|
||||||
fn forbidden_narratives() -> Result<isize, ()> {
|
fn forbidden_narratives() -> Result<isize, ()> {
|
||||||
missing_discourses()?
|
missing_discourses()?
|
||||||
//~^ ERROR try expression alternatives have incompatible types
|
//~^ ERROR: `?` operator has incompatible types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -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
|
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
||||||
|
|
|
|
||||||
LL | missing_discourses()?
|
LL | missing_discourses()?
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
|
| ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
|
||||||
|
|
|
|
||||||
|
= note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
|
||||||
= note: expected enum `Result<isize, ()>`
|
= note: expected enum `Result<isize, ()>`
|
||||||
found type `isize`
|
found type `isize`
|
||||||
help: try removing this `?`
|
help: try removing this `?`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user