Skip to content

Commit ae3a825

Browse files
committed
Make E0529 a structured error
1 parent 693ed26 commit ae3a825

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
@@ -2771,16 +2771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27712771
) -> ErrorGuaranteed {
27722772
let PatInfo { top_info: ti, current_depth, .. } = pat_info;
27732773

2774-
let mut err = struct_span_code_err!(
2775-
self.dcx(),
2776-
span,
2777-
E0529,
2778-
"expected an array or slice, found `{expected_ty}`"
2779-
);
2774+
let mut slice_pat_semantics = false;
2775+
let mut as_deref = None;
2776+
let mut slicing = None;
27802777
if let ty::Ref(_, ty, _) = expected_ty.kind()
27812778
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
27822779
{
2783-
err.help("the semantics of slice patterns changed recently; see issue #62254");
2780+
slice_pat_semantics = true;
27842781
} else if self
27852782
.autoderef(span, expected_ty)
27862783
.silence_errors()
@@ -2797,28 +2794,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27972794
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
27982795
{
27992796
// Slicing won't work here, but `.as_deref()` might (issue #91328).
2800-
err.span_suggestion_verbose(
2801-
span.shrink_to_hi(),
2802-
"consider using `as_deref` here",
2803-
".as_deref()",
2804-
Applicability::MaybeIncorrect,
2805-
);
2797+
as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
28062798
}
28072799
_ => (),
28082800
}
28092801

28102802
let is_top_level = current_depth <= 1;
28112803
if is_slice_or_array_or_vector && is_top_level {
2812-
err.span_suggestion_verbose(
2813-
span.shrink_to_hi(),
2814-
"consider slicing here",
2815-
"[..]",
2816-
Applicability::MachineApplicable,
2817-
);
2804+
slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
28182805
}
28192806
}
2820-
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
2821-
err.emit()
2807+
self.dcx().emit_err(errors::ExpectedArrayOrSlice {
2808+
span,
2809+
ty: expected_ty,
2810+
slice_pat_semantics,
2811+
as_deref,
2812+
slicing,
2813+
})
28222814
}
28232815

28242816
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)