1
Fork 0

Make E0529 a structured error

This commit is contained in:
Esteban Küber 2025-02-18 01:39:08 +00:00
parent 693ed264ce
commit ae3a825faa
5 changed files with 64 additions and 25 deletions

View file

@ -10,6 +10,7 @@ hir_typeck_address_of_temporary_taken = cannot take address of a temporary
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
hir_typeck_as_deref_suggestion = consider using `as_deref` here
hir_typeck_base_expression_double_dot = base expression required after `..`
hir_typeck_base_expression_double_dot_add_expr = add a base expression here
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
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}`
hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}`
hir_typeck_expected_default_return_type = expected `()` because of default return type
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
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
.suggestion = replace `Self` with the actual type
hir_typeck_slicing_suggestion = consider slicing here
hir_typeck_struct_expr_non_exhaustive =
cannot create non-exhaustive {$what} using struct expression

View file

@ -454,6 +454,44 @@ impl HelpUseLatestEdition {
}
}
#[derive(Diagnostic)]
#[diag(hir_typeck_expected_array_or_slice, code = E0529)]
pub(crate) struct ExpectedArrayOrSlice<'tcx> {
#[primary_span]
#[label(hir_typeck_expected_array_or_slice_label)]
pub(crate) span: Span,
pub(crate) ty: Ty<'tcx>,
pub(crate) slice_pat_semantics: bool,
#[subdiagnostic]
pub(crate) as_deref: Option<AsDerefSuggestion>,
#[subdiagnostic]
pub(crate) slicing: Option<SlicingSuggestion>,
}
#[derive(Subdiagnostic)]
#[suggestion(
hir_typeck_as_deref_suggestion,
code = ".as_deref()",
style = "verbose",
applicability = "maybe-incorrect"
)]
pub(crate) struct AsDerefSuggestion {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[suggestion(
hir_typeck_slicing_suggestion,
code = "[..]",
style = "verbose",
applicability = "maybe-incorrect"
)]
pub(crate) struct SlicingSuggestion {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_invalid_callee, code = E0618)]
pub(crate) struct InvalidCallee<'tcx> {

View file

@ -2771,16 +2771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> ErrorGuaranteed {
let PatInfo { top_info: ti, current_depth, .. } = pat_info;
let mut err = struct_span_code_err!(
self.dcx(),
span,
E0529,
"expected an array or slice, found `{expected_ty}`"
);
let mut slice_pat_semantics = false;
let mut as_deref = None;
let mut slicing = None;
if let ty::Ref(_, ty, _) = expected_ty.kind()
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
{
err.help("the semantics of slice patterns changed recently; see issue #62254");
slice_pat_semantics = true;
} else if self
.autoderef(span, expected_ty)
.silence_errors()
@ -2797,28 +2794,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
{
// Slicing won't work here, but `.as_deref()` might (issue #91328).
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider using `as_deref` here",
".as_deref()",
Applicability::MaybeIncorrect,
);
as_deref = Some(errors::AsDerefSuggestion { span: span.shrink_to_hi() });
}
_ => (),
}
let is_top_level = current_depth <= 1;
if is_slice_or_array_or_vector && is_top_level {
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider slicing here",
"[..]",
Applicability::MachineApplicable,
);
slicing = Some(errors::SlicingSuggestion { span: span.shrink_to_hi() });
}
}
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
err.emit()
self.dcx().emit_err(errors::ExpectedArrayOrSlice {
span,
ty: expected_ty,
slice_pat_semantics,
as_deref,
slicing,
})
}
fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {

View file

@ -7,8 +7,8 @@ type C = (B, B, B, B);
type D = (C, C, C, C);
fn foo(x: D) {
let [] = x; //~ ERROR expected an array or slice, found `(
//~^ pattern cannot match with input type `(
let [] = x; //~ ERROR expected an array or slice, found `(...
//~^ pattern cannot match with input type `(...
}
fn main() {}

View file

@ -1,8 +1,11 @@
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))))`
error[E0529]: expected an array or slice, found `(..., ..., ..., ...)`
--> $DIR/long-E0529.rs:10:9
|
LL | let [] = x;
| ^^ 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))))`
| ^^ pattern cannot match with input type `(..., ..., ..., ...)`
|
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error: aborting due to 1 previous error