From 40f33a7a4c3cf928576429a89bca522b94b081cd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 11 Jan 2022 20:57:40 -0800 Subject: [PATCH 1/2] Deduplicate box deref and regular deref suggestions --- compiler/rustc_typeck/src/check/demand.rs | 35 ++++++------------- .../ui/infinite/infinite-autoderef.stderr | 9 +++-- src/test/ui/occurs-check-2.stderr | 9 +++-- src/test/ui/occurs-check.stderr | 9 +++-- src/test/ui/span/coerce-suggestions.stderr | 9 +++-- .../ui/suggestions/boxed-variant-field.rs | 2 +- .../ui/suggestions/boxed-variant-field.stderr | 8 ++--- src/test/ui/terr-sorts.stderr | 2 +- 8 files changed, 40 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index b7e276b69656f..62179821d233d 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -31,7 +31,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: TypeError<'tcx>, ) { self.annotate_expected_due_to_let_ty(err, expr, error); - 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) { @@ -259,23 +258,6 @@ 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( @@ -857,14 +839,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, false, )); - } else if self.infcx.type_is_copy_modulo_regions( - self.param_env, - expected, - sp, - ) { - // For this suggestion to make sense, the type would need to be `Copy`. + } + + // For this suggestion to make sense, the type would need to be `Copy`, + // or we have to be moving out of a `Box` + if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) + || checked_ty.is_box() + { if let Ok(code) = sm.span_to_snippet(expr.span) { - let message = if checked_ty.is_region_ptr() { + let message = if checked_ty.is_box() { + "consider unboxing the value" + } else if checked_ty.is_region_ptr() { "consider dereferencing the borrow" } else { "consider dereferencing the type" diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index 03e4718f5dfef..2d29f0592e14b 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/infinite-autoderef.rs:20:13 | LL | x = Box::new(x); - | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | - | cyclic type of infinite size + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | x = *Box::new(x); + | + error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:5 diff --git a/src/test/ui/occurs-check-2.stderr b/src/test/ui/occurs-check-2.stderr index dcbfc81b4d519..b68c3fa5bcc9c 100644 --- a/src/test/ui/occurs-check-2.stderr +++ b/src/test/ui/occurs-check-2.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/occurs-check-2.rs:7:9 | LL | f = Box::new(g); - | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | - | cyclic type of infinite size + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(g); + | + error: aborting due to previous error diff --git a/src/test/ui/occurs-check.stderr b/src/test/ui/occurs-check.stderr index 3e1ef2e719ad5..fdbbdc3abb377 100644 --- a/src/test/ui/occurs-check.stderr +++ b/src/test/ui/occurs-check.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/occurs-check.rs:5:9 | LL | f = Box::new(f); - | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | - | cyclic type of infinite size + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(f); + | + error: aborting due to previous error diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 74caae8645c1d..5a964c5d5cc66 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -38,9 +38,12 @@ error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:17:9 | LL | f = Box::new(f); - | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | - | cyclic type of infinite size + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(f); + | + error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs index 9b9e70a675fb1..e79be2f6127c1 100644 --- a/src/test/ui/suggestions/boxed-variant-field.rs +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -8,7 +8,7 @@ fn foo(x: Ty) -> Ty { Ty::Unit => Ty::Unit, Ty::List(elem) => foo(elem), //~^ ERROR mismatched types - //~| HELP try dereferencing the `Box` + //~| HELP consider unboxing the value //~| HELP try wrapping } } diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr index e865b993a4c17..4df8e7b20b791 100644 --- a/src/test/ui/suggestions/boxed-variant-field.stderr +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -6,14 +6,14 @@ LL | Ty::List(elem) => foo(elem), | = note: expected enum `Ty` found struct `Box` -help: try dereferencing the `Box` - | -LL | Ty::List(elem) => foo(*elem), - | + help: try wrapping the expression in `Ty::List` | LL | Ty::List(elem) => foo(Ty::List(elem)), | +++++++++ + +help: consider unboxing the value + | +LL | Ty::List(elem) => foo(*elem), + | + error: aborting due to previous error diff --git a/src/test/ui/terr-sorts.stderr b/src/test/ui/terr-sorts.stderr index 65d90678040d5..34d4d9eaded8a 100644 --- a/src/test/ui/terr-sorts.stderr +++ b/src/test/ui/terr-sorts.stderr @@ -6,7 +6,7 @@ LL | want_foo(b); | = note: expected struct `Foo` found struct `Box` -help: try dereferencing the `Box` +help: consider unboxing the value | LL | want_foo(*b); | + From 8568f44fe172b0e7b7d9ce5a66d6e69ad9ffc669 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 12 Jan 2022 12:00:36 -0800 Subject: [PATCH 2/2] suggest deref/unboxing before wrapping variant --- compiler/rustc_typeck/src/check/demand.rs | 2 +- src/test/ui/suggestions/boxed-variant-field.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 62179821d233d..c351a9f70404a 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -31,8 +31,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: TypeError<'tcx>, ) { self.annotate_expected_due_to_let_ty(err, expr, error); - self.suggest_compatible_variants(err, expr, expected, expr_ty); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); + self.suggest_compatible_variants(err, expr, expected, expr_ty); if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { return; } diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr index 4df8e7b20b791..9a31dc89197e3 100644 --- a/src/test/ui/suggestions/boxed-variant-field.stderr +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -6,14 +6,14 @@ LL | Ty::List(elem) => foo(elem), | = note: expected enum `Ty` found struct `Box` -help: try wrapping the expression in `Ty::List` - | -LL | Ty::List(elem) => foo(Ty::List(elem)), - | +++++++++ + help: consider unboxing the value | LL | Ty::List(elem) => foo(*elem), | + +help: try wrapping the expression in `Ty::List` + | +LL | Ty::List(elem) => foo(Ty::List(elem)), + | +++++++++ + error: aborting due to previous error