Skip to content

Commit

Permalink
Rollup merge of rust-lang#90627 - camelid:suggest-box-deref, r=davidtwco
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
matthiaskrgr authored Nov 6, 2021
2 parents 1e4e823 + d93f7f9 commit f3f9ec6
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
18 changes: 18 additions & 0 deletions compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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(
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/boxed-variant-field.rs
Original file line number Diff line number Diff line change
@@ -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() {}
20 changes: 20 additions & 0 deletions src/test/ui/suggestions/boxed-variant-field.stderr
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 4 additions & 0 deletions src/test/ui/terr-sorts.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit f3f9ec6

Please sign in to comment.