Rollup merge of #57783 - davidtwco:issue-57741, r=estebank
Add "dereference boxed value" suggestion. Contributes to #57741. This PR adds a `help: consider dereferencing the boxed value` suggestion to discriminants of match statements when the match arms have type `T` and the discriminant has type `Box<T>`. r? @estebank
This commit is contained in:
commit
74b8cd4957
6 changed files with 183 additions and 2 deletions
|
@ -485,12 +485,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
|
fn note_error_origin(
|
||||||
|
&self,
|
||||||
|
err: &mut DiagnosticBuilder<'tcx>,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||||
|
) {
|
||||||
match cause.code {
|
match cause.code {
|
||||||
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
|
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
|
||||||
if ty.is_suggestable() { // don't show type `_`
|
if ty.is_suggestable() { // don't show type `_`
|
||||||
err.span_label(span, format!("this match expression has type `{}`", ty));
|
err.span_label(span, format!("this match expression has type `{}`", ty));
|
||||||
}
|
}
|
||||||
|
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
|
||||||
|
if ty.is_box() && ty.boxed_ty() == found {
|
||||||
|
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
|
err.span_suggestion_with_applicability(
|
||||||
|
span,
|
||||||
|
"consider dereferencing the boxed value",
|
||||||
|
format!("*{}", snippet),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
|
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
|
||||||
hir::MatchSource::IfLetDesugar { .. } => {
|
hir::MatchSource::IfLetDesugar { .. } => {
|
||||||
|
@ -1013,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// It reads better to have the error origin as the final
|
// It reads better to have the error origin as the final
|
||||||
// thing.
|
// thing.
|
||||||
self.note_error_origin(diag, &cause);
|
self.note_error_origin(diag, &cause, exp_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
||||||
|
|
18
src/test/ui/issues/issue-57741-1.rs
Normal file
18
src/test/ui/issues/issue-57741-1.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made
|
||||||
|
// because the box doesn't deref to the type of the arm.
|
||||||
|
|
||||||
|
enum S {
|
||||||
|
A { a: usize },
|
||||||
|
B { b: usize },
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Box::new(3u32);
|
||||||
|
let y = match x {
|
||||||
|
S::A { a } | S::B { b: a } => a,
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~^^ ERROR mismatched types [E0308]
|
||||||
|
};
|
||||||
|
}
|
25
src/test/ui/issues/issue-57741-1.stderr
Normal file
25
src/test/ui/issues/issue-57741-1.stderr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741-1.rs:14:9
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| - this match expression has type `std::boxed::Box<u32>`
|
||||||
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
|
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<u32>`
|
||||||
|
found type `S`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741-1.rs:14:22
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| - this match expression has type `std::boxed::Box<u32>`
|
||||||
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
|
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<u32>`
|
||||||
|
found type `S`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
31
src/test/ui/issues/issue-57741.fixed
Normal file
31
src/test/ui/issues/issue-57741.fixed
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
|
||||||
|
|
||||||
|
enum S {
|
||||||
|
A { a: usize },
|
||||||
|
B { b: usize },
|
||||||
|
}
|
||||||
|
|
||||||
|
enum T {
|
||||||
|
A(usize),
|
||||||
|
B(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Box::new(T::A(3));
|
||||||
|
let y = match *x {
|
||||||
|
T::A(a) | T::B(a) => a,
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~^^ ERROR mismatched types [E0308]
|
||||||
|
};
|
||||||
|
|
||||||
|
let x = Box::new(S::A { a: 3 });
|
||||||
|
let y = match *x {
|
||||||
|
S::A { a } | S::B { b: a } => a,
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~^^ ERROR mismatched types [E0308]
|
||||||
|
};
|
||||||
|
}
|
31
src/test/ui/issues/issue-57741.rs
Normal file
31
src/test/ui/issues/issue-57741.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
|
||||||
|
|
||||||
|
enum S {
|
||||||
|
A { a: usize },
|
||||||
|
B { b: usize },
|
||||||
|
}
|
||||||
|
|
||||||
|
enum T {
|
||||||
|
A(usize),
|
||||||
|
B(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Box::new(T::A(3));
|
||||||
|
let y = match x {
|
||||||
|
T::A(a) | T::B(a) => a,
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~^^ ERROR mismatched types [E0308]
|
||||||
|
};
|
||||||
|
|
||||||
|
let x = Box::new(S::A { a: 3 });
|
||||||
|
let y = match x {
|
||||||
|
S::A { a } | S::B { b: a } => a,
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~^^ ERROR mismatched types [E0308]
|
||||||
|
};
|
||||||
|
}
|
59
src/test/ui/issues/issue-57741.stderr
Normal file
59
src/test/ui/issues/issue-57741.stderr
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741.rs:20:9
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| -
|
||||||
|
| |
|
||||||
|
| this match expression has type `std::boxed::Box<T>`
|
||||||
|
| help: consider dereferencing the boxed value: `*x`
|
||||||
|
LL | T::A(a) | T::B(a) => a,
|
||||||
|
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<T>`
|
||||||
|
found type `T`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741.rs:20:19
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| -
|
||||||
|
| |
|
||||||
|
| this match expression has type `std::boxed::Box<T>`
|
||||||
|
| help: consider dereferencing the boxed value: `*x`
|
||||||
|
LL | T::A(a) | T::B(a) => a,
|
||||||
|
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<T>`
|
||||||
|
found type `T`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741.rs:27:9
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| -
|
||||||
|
| |
|
||||||
|
| this match expression has type `std::boxed::Box<S>`
|
||||||
|
| help: consider dereferencing the boxed value: `*x`
|
||||||
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
|
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<S>`
|
||||||
|
found type `S`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-57741.rs:27:22
|
||||||
|
|
|
||||||
|
LL | let y = match x {
|
||||||
|
| -
|
||||||
|
| |
|
||||||
|
| this match expression has type `std::boxed::Box<S>`
|
||||||
|
| help: consider dereferencing the boxed value: `*x`
|
||||||
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
|
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
|
||||||
|
|
|
||||||
|
= note: expected type `std::boxed::Box<S>`
|
||||||
|
found type `S`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue