diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-11-06 23:12:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-06 23:12:04 +0100 |
| commit | 1d9fe9cd0678ca0dd04573da08cc18503017a3fa (patch) | |
| tree | 69b0579a935e17af7f0ff605883b3d5f2ae8923d | |
| parent | 4c49db35fc671a522dbe07bfbeda8c7e7897108c (diff) | |
| parent | d93f7f93c44a7106071411224c0615c7cfcb2468 (diff) | |
| download | rust-1d9fe9cd0678ca0dd04573da08cc18503017a3fa.tar.gz rust-1d9fe9cd0678ca0dd04573da08cc18503017a3fa.zip | |
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``
| -rw-r--r-- | compiler/rustc_typeck/src/check/demand.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/suggestions/boxed-variant-field.rs | 16 | ||||
| -rw-r--r-- | src/test/ui/suggestions/boxed-variant-field.stderr | 20 | ||||
| -rw-r--r-- | src/test/ui/terr-sorts.stderr | 4 |
4 files changed, 58 insertions, 0 deletions
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 2b3672211e4..0cbbcdd1073 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -29,6 +29,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) { self.annotate_expected_due_to_let_ty(err, expr); + self.suggest_box_deref(err, expr, expected, expr_ty); self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { @@ -167,6 +168,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn suggest_box_deref( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr<'_>, + expected: Ty<'tcx>, + expr_ty: Ty<'tcx>, + ) { + if expr_ty.is_box() && expr_ty.boxed_ty() == expected { + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "try dereferencing the `Box`", + "*".to_string(), + Applicability::MachineApplicable, + ); + } + } + /// If the expected type is an enum (Issue #55250) with any variants whose /// sole field is of the found type, suggest such variants. (Issue #42764) fn suggest_compatible_variants( diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs new file mode 100644 index 00000000000..d8f7fac1513 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -0,0 +1,16 @@ +enum Ty { + Unit, + List(Box<Ty>), +} + +fn foo(x: Ty) -> Ty { + match x { + Ty::Unit => Ty::Unit, + Ty::List(elem) => foo(elem), + //~^ ERROR mismatched types + //~| HELP try dereferencing the `Box` + //~| HELP try using a variant of the expected enum + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr new file mode 100644 index 00000000000..d4ccb2ca490 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/boxed-variant-field.rs:9:31 + | +LL | Ty::List(elem) => foo(elem), + | ^^^^ expected enum `Ty`, found struct `Box` + | + = note: expected enum `Ty` + found struct `Box<Ty>` +help: try dereferencing the `Box` + | +LL | Ty::List(elem) => foo(*elem), + | + +help: try using a variant of the expected enum + | +LL | Ty::List(elem) => foo(Ty::List(elem)), + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/terr-sorts.stderr b/src/test/ui/terr-sorts.stderr index 869b3729659..65d90678040 100644 --- a/src/test/ui/terr-sorts.stderr +++ b/src/test/ui/terr-sorts.stderr @@ -6,6 +6,10 @@ LL | want_foo(b); | = note: expected struct `Foo` found struct `Box<Foo>` +help: try dereferencing the `Box` + | +LL | want_foo(*b); + | + error: aborting due to previous error |
