Skip to content

Commit 1d9fe9c

Browse files
authored
Rollup merge of #90627 - camelid:suggest-box-deref, r=davidtwco
Suggest dereference of `Box` when inner type is expected For example: enum Ty { Unit, List(Box<Ty>), } fn foo(x: Ty) -> Ty { match x { Ty::Unit => Ty::Unit, Ty::List(elem) => foo(elem), } } Before, the only suggestion was to rewrap `inner` with `Ty::Wrapper`, which is unhelpful and confusing: error[E0308]: mismatched types --> src/test/ui/suggestions/boxed-variant-field.rs:9:31 | 9 | Ty::List(elem) => foo(elem), | ^^^^ | | | expected enum `Ty`, found struct `Box` | help: try using a variant of the expected enum: `Ty::List(elem)` | = note: expected enum `Ty` found struct `Box<Ty>` Now, rustc will first suggest dereferencing the `Box`, which is most likely what the user intended: error[E0308]: mismatched types --> src/test/ui/suggestions/boxed-variant-field.rs:9:31 | 9 | Ty::List(elem) => foo(elem), | ^^^^ expected enum `Ty`, found struct `Box` | = note: expected enum `Ty` found struct `Box<Ty>` help: try dereferencing the `Box` | 9 | Ty::List(elem) => foo(*elem), | + help: try using a variant of the expected enum | 9 | Ty::List(elem) => foo(Ty::List(elem)), | ~~~~~~~~~~~~~~ r? ``@davidtwco``
2 parents 4c49db3 + d93f7f9 commit 1d9fe9c

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

compiler/rustc_typeck/src/check/demand.rs

+18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2929
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
3030
) {
3131
self.annotate_expected_due_to_let_ty(err, expr);
32+
self.suggest_box_deref(err, expr, expected, expr_ty);
3233
self.suggest_compatible_variants(err, expr, expected, expr_ty);
3334
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
3435
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
@@ -167,6 +168,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
167168
}
168169
}
169170

171+
fn suggest_box_deref(
172+
&self,
173+
err: &mut DiagnosticBuilder<'_>,
174+
expr: &hir::Expr<'_>,
175+
expected: Ty<'tcx>,
176+
expr_ty: Ty<'tcx>,
177+
) {
178+
if expr_ty.is_box() && expr_ty.boxed_ty() == expected {
179+
err.span_suggestion_verbose(
180+
expr.span.shrink_to_lo(),
181+
"try dereferencing the `Box`",
182+
"*".to_string(),
183+
Applicability::MachineApplicable,
184+
);
185+
}
186+
}
187+
170188
/// If the expected type is an enum (Issue #55250) with any variants whose
171189
/// sole field is of the found type, suggest such variants. (Issue #42764)
172190
fn suggest_compatible_variants(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
enum Ty {
2+
Unit,
3+
List(Box<Ty>),
4+
}
5+
6+
fn foo(x: Ty) -> Ty {
7+
match x {
8+
Ty::Unit => Ty::Unit,
9+
Ty::List(elem) => foo(elem),
10+
//~^ ERROR mismatched types
11+
//~| HELP try dereferencing the `Box`
12+
//~| HELP try using a variant of the expected enum
13+
}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/boxed-variant-field.rs:9:31
3+
|
4+
LL | Ty::List(elem) => foo(elem),
5+
| ^^^^ expected enum `Ty`, found struct `Box`
6+
|
7+
= note: expected enum `Ty`
8+
found struct `Box<Ty>`
9+
help: try dereferencing the `Box`
10+
|
11+
LL | Ty::List(elem) => foo(*elem),
12+
| +
13+
help: try using a variant of the expected enum
14+
|
15+
LL | Ty::List(elem) => foo(Ty::List(elem)),
16+
| ~~~~~~~~~~~~~~
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/terr-sorts.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ LL | want_foo(b);
66
|
77
= note: expected struct `Foo`
88
found struct `Box<Foo>`
9+
help: try dereferencing the `Box`
10+
|
11+
LL | want_foo(*b);
12+
| +
913

1014
error: aborting due to previous error
1115

0 commit comments

Comments
 (0)