1
Fork 0

Add additional context for non-sructural type constant used in pattern

- Point at type that should derive `PartialEq` to be structural.
- Point at manual `impl PartialEq`, explaining that it is not sufficient to be structural.

```
error: constant of non-structural type `MyType` in a pattern
  --> $DIR/const-partial_eq-fallback-ice.rs:14:12
   |
LL | struct MyType;
   | ------------- `MyType` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const CONSTANT: &&MyType = &&MyType;
   | ------------------------ constant defined here
...
LL |     if let CONSTANT = &&MyType {
   |            ^^^^^^^^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/const-partial_eq-fallback-ice.rs:5:1
   |
LL | impl PartialEq<usize> for MyType {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
This commit is contained in:
Esteban Küber 2024-11-20 04:30:35 +00:00
parent fb2f6a44c0
commit 335d05aee5
33 changed files with 343 additions and 175 deletions

View file

@ -322,12 +322,12 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
*[other] them
} into the body
mir_build_type_not_structural =
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
mir_build_type_not_structural = constant of non-structural type `{$non_sm_ty}` in a pattern
.label = constant of non-structural type
mir_build_type_not_structural_def = `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
mir_build_type_not_structural_tip =
the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
mir_build_unconditional_recursion = function cannot return without recursing
.label = cannot return without recursing

View file

@ -882,12 +882,17 @@ pub(crate) struct UnionPattern {
#[derive(Diagnostic)]
#[diag(mir_build_type_not_structural)]
#[note(mir_build_type_not_structural_tip)]
#[note(mir_build_type_not_structural_more_info)]
pub(crate) struct TypeNotStructural<'tcx> {
#[primary_span]
#[label]
pub(crate) span: Span,
#[label(mir_build_type_not_structural_def)]
pub(crate) ty_def_span: Span,
pub(crate) non_sm_ty: Ty<'tcx>,
#[note(mir_build_type_not_structural_tip)]
pub(crate) manual_partialeq_impl_span: Option<Span>,
#[note(mir_build_type_not_structural_more_info)]
pub(crate) manual_partialeq_impl_note: bool,
}
#[derive(Diagnostic)]

View file

@ -254,7 +254,22 @@ impl<'tcx> ConstToPat<'tcx> {
// Extremely important check for all ADTs! Make sure they opted-in to be used in
// patterns.
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
let err = TypeNotStructural { span, non_sm_ty: ty };
let ty_def_span = tcx.def_span(adt_def.did());
let mut manual_partialeq_impl_span = None;
let partial_eq_trait_id =
tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
tcx.for_each_relevant_impl(partial_eq_trait_id, ty, |def_id| {
if def_id.is_local() {
manual_partialeq_impl_span = Some(tcx.def_span(def_id));
}
});
let err = TypeNotStructural {
span,
non_sm_ty: ty,
ty_def_span,
manual_partialeq_impl_span,
manual_partialeq_impl_note: manual_partialeq_impl_span.is_none(),
};
return Err(tcx.dcx().create_err(err));
}
ty::Adt(adt_def, args) if adt_def.is_enum() => {
@ -269,7 +284,7 @@ impl<'tcx> ConstToPat<'tcx> {
adt_def.variants()[variant_index]
.fields
.iter()
.map(|field| field.ty(self.tcx, args)),
.map(|field| field.ty(tcx, args)),
),
),
}
@ -278,7 +293,7 @@ impl<'tcx> ConstToPat<'tcx> {
assert!(!def.is_union()); // Valtree construction would never succeed for unions.
PatKind::Leaf {
subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)),
def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)),
)),
}
}
@ -377,7 +392,7 @@ impl<'tcx> ConstToPat<'tcx> {
let err = InvalidPattern {
span,
non_sm_ty: ty,
prefix: ty.prefix_string(self.tcx).to_string(),
prefix: ty.prefix_string(tcx).to_string(),
};
return Err(tcx.dcx().create_err(err));
}