Skip to content

Commit 8413388

Browse files
committed
Make E0529 a structured error
1 parent 9884f7b commit 8413388

File tree

5 files changed

+64
-25
lines changed

5 files changed

+64
-25
lines changed

compiler/rustc_hir_typeck/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ hir_typeck_address_of_temporary_taken = cannot take address of a temporary
1010
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
1111
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
1212
13+
hir_typeck_as_deref_suggestion = consider using `as_deref` here
1314
hir_typeck_base_expression_double_dot = base expression required after `..`
1415
hir_typeck_base_expression_double_dot_add_expr = add a base expression here
1516
hir_typeck_base_expression_double_dot_enable_default_field_values =
@@ -72,6 +73,9 @@ hir_typeck_dependency_on_unit_never_type_fallback = this function depends on nev
7273
7374
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
7475
76+
hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}`
77+
hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}`
78+
7579
hir_typeck_expected_default_return_type = expected `()` because of default return type
7680
7781
hir_typeck_expected_return_type = expected `{$expected}` because of return type
@@ -187,6 +191,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o
187191
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
188192
.suggestion = replace `Self` with the actual type
189193
194+
hir_typeck_slicing_suggestion = consider slicing here
195+
190196
hir_typeck_struct_expr_non_exhaustive =
191197
cannot create non-exhaustive {$what} using struct expression
192198

compiler/rustc_hir_typeck/src/errors.rs

+38
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,44 @@ impl HelpUseLatestEdition {
454454
}
455455
}
456456

457+
#[derive(Diagnostic)]
458+
#[diag(hir_typeck_expected_array_or_slice, code = E0529)]
459+
pub(crate) struct ExpectedArrayOrSlice<'tcx> {
460+
#[primary_span]
461+
#[label(hir_typeck_expected_array_or_slice_label)]
462+
pub(crate) span: Span,
463+
pub(crate) ty: Ty<'tcx>,
464+
pub(crate) slice_pat_semantics: bool,
465+
#[subdiagnostic]
466+
pub(crate) as_deref: Option<AsDerefSuggestion>,
467+
#[subdiagnostic]
468+
pub(crate) slicing: Option<SlicingSuggestion>,
469+
}
470+
471+
#[derive(Subdiagnostic)]
472+
#[suggestion(
473+
hir_typeck_as_deref_suggestion,
474+
code = ".as_deref()",
475+
style = "verbose",
476+
applicability = "maybe-incorrect"
477+
)]
478+
pub(crate) struct AsDerefSuggestion {
479+
#[primary_span]
480+
pub(crate) span: Span,
481+
}
482+
483+
#[derive(Subdiagnostic)]
484+
#[suggestion(
485+
hir_typeck_slicing_suggestion,
486+
code = "[..]",
487+
style = "verbose",
488+
applicability = "maybe-incorrect"
489+
)]
490+
pub(crate) struct SlicingSuggestion {
491+
#[primary_span]
492+
pub(crate) span: Span,
493+
}
494+
457495
#[derive(Diagnostic)]
458496
#[diag(hir_typeck_invalid_callee, code = E0618)]
459497
pub(crate) struct InvalidCallee<'tcx> {

compiler/rustc_hir_typeck/src/pat.rs

+13-21
Original file line numberDiff line numberDiff line change
@@ -2712,16 +2712,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27122712
) -> ErrorGuaranteed {
27132713
let PatInfo { top_info: ti, current_depth, .. } = pat_info;
27142714

2715-
let mut err = struct_span_code_err!(
2716-
self.dcx(),
2717-
span,
2718-
E0529,
2719-
"expected an array or slice, found `{expected_ty}`"
2720-
);
2715+
let mut slice_pat_semantics = false;
2716+
let mut as_deref = None;
2717+
let mut slicing = None;
27212718
if let ty::Ref(_, ty, _) = expected_ty.kind()
27222719
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
27232720
{
2724-
err.help("the semantics of slice patterns changed recently; see issue #62254");
2721+
slice_pat_semantics = true;
27252722
} else if self
27262723
.autoderef(span, expected_ty)
27272724
.silence_errors()
@@ -2738,28 +2735,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27382735
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
27392736
{
27402737
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2741-
err.span_suggestion_verbose(
2742-
span.shrink_to_hi(),
2743-
"consider using `as_deref` here",
2744-
".as_deref()",
2745-
Applicability::MaybeIncorrect,
2746-
);
2738+
as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
27472739
}
27482740
_ => (),
27492741
}
27502742

27512743
let is_top_level = current_depth <= 1;
27522744
if is_slice_or_array_or_vector && is_top_level {
2753-
err.span_suggestion_verbose(
2754-
span.shrink_to_hi(),
2755-
"consider slicing here",
2756-
"[..]",
2757-
Applicability::MachineApplicable,
2758-
);
2745+
slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
27592746
}
27602747
}
2761-
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
2762-
err.emit()
2748+
self.dcx().emit_err(errors::ExpectedArrayOrSlice {
2749+
span,
2750+
ty: expected_ty,
2751+
slice_pat_semantics,
2752+
as_deref,
2753+
slicing,
2754+
})
27632755
}
27642756

27652757
fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {

tests/ui/diagnostic-width/long-E0529.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ type C = (B, B, B, B);
77
type D = (C, C, C, C);
88

99
fn foo(x: D) {
10-
let [] = x; //~ ERROR expected an array or slice, found `(
11-
//~^ pattern cannot match with input type `(
10+
let [] = x; //~ ERROR expected an array or slice, found `(...
11+
//~^ pattern cannot match with input type `(...
1212
}
1313

1414
fn main() {}

tests/ui/diagnostic-width/long-E0529.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0529]: expected an array or slice, found `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))`
1+
error[E0529]: expected an array or slice, found `(..., ..., ..., ...)`
22
--> $DIR/long-E0529.rs:10:9
33
|
44
LL | let [] = x;
5-
| ^^ pattern cannot match with input type `((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))`
5+
| ^^ pattern cannot match with input type `(..., ..., ..., ...)`
6+
|
7+
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
8+
= note: consider using `--verbose` to print the full type name to the console
69

710
error: aborting due to 1 previous error
811

0 commit comments

Comments
 (0)