Skip to content

Commit 74b8cd4

Browse files
authored
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
2 parents 3bb9fc4 + f13fe5f commit 74b8cd4

File tree

6 files changed

+183
-2
lines changed

6 files changed

+183
-2
lines changed

src/librustc/infer/error_reporting/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
485485
}
486486
}
487487

488-
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
488+
fn note_error_origin(
489+
&self,
490+
err: &mut DiagnosticBuilder<'tcx>,
491+
cause: &ObligationCause<'tcx>,
492+
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
493+
) {
489494
match cause.code {
490495
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
491496
if ty.is_suggestable() { // don't show type `_`
492497
err.span_label(span, format!("this match expression has type `{}`", ty));
493498
}
499+
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
500+
if ty.is_box() && ty.boxed_ty() == found {
501+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
502+
err.span_suggestion_with_applicability(
503+
span,
504+
"consider dereferencing the boxed value",
505+
format!("*{}", snippet),
506+
Applicability::MachineApplicable,
507+
);
508+
}
509+
}
510+
}
494511
}
495512
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
496513
hir::MatchSource::IfLetDesugar { .. } => {
@@ -1013,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10131030

10141031
// It reads better to have the error origin as the final
10151032
// thing.
1016-
self.note_error_origin(diag, &cause);
1033+
self.note_error_origin(diag, &cause, exp_found);
10171034
}
10181035

10191036
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,

src/test/ui/issues/issue-57741-1.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![allow(warnings)]
2+
3+
// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made
4+
// because the box doesn't deref to the type of the arm.
5+
6+
enum S {
7+
A { a: usize },
8+
B { b: usize },
9+
}
10+
11+
fn main() {
12+
let x = Box::new(3u32);
13+
let y = match x {
14+
S::A { a } | S::B { b: a } => a,
15+
//~^ ERROR mismatched types [E0308]
16+
//~^^ ERROR mismatched types [E0308]
17+
};
18+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-57741-1.rs:14:9
3+
|
4+
LL | let y = match x {
5+
| - this match expression has type `std::boxed::Box<u32>`
6+
LL | S::A { a } | S::B { b: a } => a,
7+
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
8+
|
9+
= note: expected type `std::boxed::Box<u32>`
10+
found type `S`
11+
12+
error[E0308]: mismatched types
13+
--> $DIR/issue-57741-1.rs:14:22
14+
|
15+
LL | let y = match x {
16+
| - this match expression has type `std::boxed::Box<u32>`
17+
LL | S::A { a } | S::B { b: a } => a,
18+
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
19+
|
20+
= note: expected type `std::boxed::Box<u32>`
21+
found type `S`
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/issues/issue-57741.fixed

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
#![allow(warnings)]
4+
5+
// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
6+
7+
enum S {
8+
A { a: usize },
9+
B { b: usize },
10+
}
11+
12+
enum T {
13+
A(usize),
14+
B(usize),
15+
}
16+
17+
fn main() {
18+
let x = Box::new(T::A(3));
19+
let y = match *x {
20+
T::A(a) | T::B(a) => a,
21+
//~^ ERROR mismatched types [E0308]
22+
//~^^ ERROR mismatched types [E0308]
23+
};
24+
25+
let x = Box::new(S::A { a: 3 });
26+
let y = match *x {
27+
S::A { a } | S::B { b: a } => a,
28+
//~^ ERROR mismatched types [E0308]
29+
//~^^ ERROR mismatched types [E0308]
30+
};
31+
}

src/test/ui/issues/issue-57741.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
#![allow(warnings)]
4+
5+
// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
6+
7+
enum S {
8+
A { a: usize },
9+
B { b: usize },
10+
}
11+
12+
enum T {
13+
A(usize),
14+
B(usize),
15+
}
16+
17+
fn main() {
18+
let x = Box::new(T::A(3));
19+
let y = match x {
20+
T::A(a) | T::B(a) => a,
21+
//~^ ERROR mismatched types [E0308]
22+
//~^^ ERROR mismatched types [E0308]
23+
};
24+
25+
let x = Box::new(S::A { a: 3 });
26+
let y = match x {
27+
S::A { a } | S::B { b: a } => a,
28+
//~^ ERROR mismatched types [E0308]
29+
//~^^ ERROR mismatched types [E0308]
30+
};
31+
}

src/test/ui/issues/issue-57741.stderr

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-57741.rs:20:9
3+
|
4+
LL | let y = match x {
5+
| -
6+
| |
7+
| this match expression has type `std::boxed::Box<T>`
8+
| help: consider dereferencing the boxed value: `*x`
9+
LL | T::A(a) | T::B(a) => a,
10+
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
11+
|
12+
= note: expected type `std::boxed::Box<T>`
13+
found type `T`
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/issue-57741.rs:20:19
17+
|
18+
LL | let y = match x {
19+
| -
20+
| |
21+
| this match expression has type `std::boxed::Box<T>`
22+
| help: consider dereferencing the boxed value: `*x`
23+
LL | T::A(a) | T::B(a) => a,
24+
| ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
25+
|
26+
= note: expected type `std::boxed::Box<T>`
27+
found type `T`
28+
29+
error[E0308]: mismatched types
30+
--> $DIR/issue-57741.rs:27:9
31+
|
32+
LL | let y = match x {
33+
| -
34+
| |
35+
| this match expression has type `std::boxed::Box<S>`
36+
| help: consider dereferencing the boxed value: `*x`
37+
LL | S::A { a } | S::B { b: a } => a,
38+
| ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
39+
|
40+
= note: expected type `std::boxed::Box<S>`
41+
found type `S`
42+
43+
error[E0308]: mismatched types
44+
--> $DIR/issue-57741.rs:27:22
45+
|
46+
LL | let y = match x {
47+
| -
48+
| |
49+
| this match expression has type `std::boxed::Box<S>`
50+
| help: consider dereferencing the boxed value: `*x`
51+
LL | S::A { a } | S::B { b: a } => a,
52+
| ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
53+
|
54+
= note: expected type `std::boxed::Box<S>`
55+
found type `S`
56+
57+
error: aborting due to 4 previous errors
58+
59+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)