Skip to content

Commit 62da0af

Browse files
committed
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 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ```
1 parent 9d80797 commit 62da0af

33 files changed

+343
-175
lines changed

compiler/rustc_mir_build/messages.ftl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,12 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
312312
*[other] them
313313
} into the body
314314
315-
mir_build_type_not_structural =
316-
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
317-
315+
mir_build_type_not_structural = constant of non-structural type `{$non_sm_ty}` in a pattern
316+
.label = constant of non-structural type
317+
mir_build_type_not_structural_def = `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
318318
mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
319-
320-
mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
319+
mir_build_type_not_structural_tip =
320+
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
321321
322322
mir_build_unconditional_recursion = function cannot return without recursing
323323
.label = cannot return without recursing

compiler/rustc_mir_build/src/errors.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,12 +793,17 @@ pub(crate) struct UnionPattern {
793793

794794
#[derive(Diagnostic)]
795795
#[diag(mir_build_type_not_structural)]
796-
#[note(mir_build_type_not_structural_tip)]
797-
#[note(mir_build_type_not_structural_more_info)]
798796
pub(crate) struct TypeNotStructural<'tcx> {
799797
#[primary_span]
798+
#[label]
800799
pub(crate) span: Span,
800+
#[label(mir_build_type_not_structural_def)]
801+
pub(crate) ty_def_span: Span,
801802
pub(crate) non_sm_ty: Ty<'tcx>,
803+
#[note(mir_build_type_not_structural_tip)]
804+
pub(crate) manual_partialeq_impl_span: Option<Span>,
805+
#[note(mir_build_type_not_structural_more_info)]
806+
pub(crate) manual_partialeq_impl_note: bool,
802807
}
803808

804809
#[derive(Diagnostic)]

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,22 @@ impl<'tcx> ConstToPat<'tcx> {
254254
// Extremely important check for all ADTs! Make sure they opted-in to be used in
255255
// patterns.
256256
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
257-
let err = TypeNotStructural { span, non_sm_ty: ty };
257+
let ty_def_span = tcx.def_span(adt_def.did());
258+
let mut manual_partialeq_impl_span = None;
259+
let partial_eq_trait_id =
260+
tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
261+
tcx.for_each_relevant_impl(partial_eq_trait_id, ty, |def_id| {
262+
if def_id.is_local() {
263+
manual_partialeq_impl_span = Some(tcx.def_span(def_id));
264+
}
265+
});
266+
let err = TypeNotStructural {
267+
span,
268+
non_sm_ty: ty,
269+
ty_def_span,
270+
manual_partialeq_impl_span,
271+
manual_partialeq_impl_note: manual_partialeq_impl_span.is_none(),
272+
};
258273
return Err(tcx.dcx().create_err(err));
259274
}
260275
ty::Adt(adt_def, args) if adt_def.is_enum() => {
@@ -269,7 +284,7 @@ impl<'tcx> ConstToPat<'tcx> {
269284
adt_def.variants()[variant_index]
270285
.fields
271286
.iter()
272-
.map(|field| field.ty(self.tcx, args)),
287+
.map(|field| field.ty(tcx, args)),
273288
),
274289
),
275290
}
@@ -278,7 +293,7 @@ impl<'tcx> ConstToPat<'tcx> {
278293
assert!(!def.is_union()); // Valtree construction would never succeed for unions.
279294
PatKind::Leaf {
280295
subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
281-
def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)),
296+
def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)),
282297
)),
283298
}
284299
}
@@ -377,7 +392,7 @@ impl<'tcx> ConstToPat<'tcx> {
377392
let err = InvalidPattern {
378393
span,
379394
non_sm_ty: ty,
380-
prefix: ty.prefix_string(self.tcx).to_string(),
395+
prefix: ty.prefix_string(tcx).to_string(),
381396
};
382397
return Err(tcx.dcx().create_err(err));
383398
}

tests/ui/consts/const_in_pattern/cross-crate-fail.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ fn main() {
99
let _ = Defaulted;
1010
match None {
1111
consts::SOME => panic!(),
12-
//~^ must be annotated with `#[derive(PartialEq)]`
13-
12+
//~^ ERROR constant of non-structural type `CustomEq` in a pattern
1413
_ => {}
1514
}
1615

1716
match None {
1817
<Defaulted as consts::AssocConst>::SOME => panic!(),
19-
//~^ must be annotated with `#[derive(PartialEq)]`
20-
18+
//~^ ERROR constant of non-structural type `CustomEq` in a pattern
2119
_ => {}
2220
}
2321
}

tests/ui/consts/const_in_pattern/cross-crate-fail.stderr

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
1-
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]`
1+
error: constant of non-structural type `CustomEq` in a pattern
22
--> $DIR/cross-crate-fail.rs:11:9
33
|
44
LL | consts::SOME => panic!(),
5-
| ^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^ constant of non-structural type
66
|
7-
::: $DIR/auxiliary/consts.rs:11:1
7+
::: $DIR/auxiliary/consts.rs:1:1
88
|
9+
LL | pub struct CustomEq;
10+
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
11+
...
912
LL | pub const SOME: Option<CustomEq> = Some(CustomEq);
1013
| -------------------------------- constant defined here
1114
|
12-
= note: the traits must be derived, manual `impl`s are not sufficient
1315
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
1416

15-
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]`
16-
--> $DIR/cross-crate-fail.rs:18:9
17+
error: constant of non-structural type `CustomEq` in a pattern
18+
--> $DIR/cross-crate-fail.rs:17:9
1719
|
1820
LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
2022
|
21-
::: $DIR/auxiliary/consts.rs:15:5
23+
::: $DIR/auxiliary/consts.rs:1:1
2224
|
25+
LL | pub struct CustomEq;
26+
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
27+
...
2328
LL | const SOME: Option<CustomEq> = Some(CustomEq);
2429
| ---------------------------- constant defined here
2530
|
26-
= note: the traits must be derived, manual `impl`s are not sufficient
2731
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
2832

2933
error: aborting due to 2 previous errors

tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ const BAR_BAZ: Foo = if 42 == 42 {
1616

1717
fn main() {
1818
match Foo::Qux(NoEq) {
19-
BAR_BAZ => panic!(),
20-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
19+
BAR_BAZ => panic!(), //~ ERROR constant of non-structural type `Foo` in a pattern
2120
_ => {}
2221
}
2322
}

tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]`
1+
error: constant of non-structural type `Foo` in a pattern
22
--> $DIR/no-eq-branch-fail.rs:19:9
33
|
4+
LL | enum Foo {
5+
| -------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
6+
...
47
LL | const BAR_BAZ: Foo = if 42 == 42 {
58
| ------------------ constant defined here
69
...
710
LL | BAR_BAZ => panic!(),
8-
| ^^^^^^^
11+
| ^^^^^^^ constant of non-structural type
912
|
10-
= note: the traits must be derived, manual `impl`s are not sufficient
1113
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
1214

1315
error: aborting due to 1 previous error

tests/ui/consts/const_in_pattern/reject_non_structural.rs

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,29 @@ struct NoPartialEq;
1717

1818
#[derive(Copy, Clone, Debug)]
1919
struct NoDerive;
20+
//~^ NOTE must be annotated with `#[derive(PartialEq)]`
21+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
22+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
23+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
24+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
25+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
26+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
27+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
28+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
29+
//~| NOTE must be annotated with `#[derive(PartialEq)]`
2030

2131
// This impl makes `NoDerive` irreflexive.
2232
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
33+
//~^ NOTE StructuralPartialEq.html for details
34+
//~| NOTE StructuralPartialEq.html for details
35+
//~| NOTE StructuralPartialEq.html for details
36+
//~| NOTE StructuralPartialEq.html for details
37+
//~| NOTE StructuralPartialEq.html for details
38+
//~| NOTE StructuralPartialEq.html for details
39+
//~| NOTE StructuralPartialEq.html for details
40+
//~| NOTE StructuralPartialEq.html for details
41+
//~| NOTE StructuralPartialEq.html for details
42+
//~| NOTE StructuralPartialEq.html for details
2343

2444
impl Eq for NoDerive { }
2545

@@ -38,63 +58,53 @@ fn main() {
3858

3959
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive); //~ NOTE constant defined here
4060
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
41-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
42-
//~| NOTE the traits must be derived
43-
//~| NOTE StructuralPartialEq.html for details
61+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
62+
//~| NOTE constant of non-structural type
4463

4564
const FIELD: OND = TrivialEq(Some(NoDerive)).0; //~ NOTE constant defined here
4665
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
47-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
48-
//~| NOTE the traits must be derived
49-
//~| NOTE StructuralPartialEq.html for details
66+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
67+
//~| NOTE constant of non-structural type
5068

5169
const NO_DERIVE_SOME: OND = Some(NoDerive);
5270
const INDIRECT: OND = NO_DERIVE_SOME; //~ NOTE constant defined here
5371
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
54-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
55-
//~| NOTE the traits must be derived
56-
//~| NOTE StructuralPartialEq.html for details
72+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
73+
//~| NOTE constant of non-structural type
5774

5875
const TUPLE: (OND, OND) = (None, Some(NoDerive)); //~ NOTE constant defined here
5976
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
60-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
61-
//~| NOTE the traits must be derived
62-
//~| NOTE StructuralPartialEq.html for details
77+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
78+
//~| NOTE constant of non-structural type
6379

6480
const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); //~ NOTE constant defined here
6581
match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
66-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
67-
//~| NOTE the traits must be derived
68-
//~| NOTE StructuralPartialEq.html for details
82+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
83+
//~| NOTE constant of non-structural type
6984

7085
const ARRAY: [OND; 2] = [None, Some(NoDerive)]; //~ NOTE constant defined here
7186
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
72-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
73-
//~| NOTE the traits must be derived
74-
//~| NOTE StructuralPartialEq.html for details
87+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
88+
//~| NOTE constant of non-structural type
7589

7690
const REPEAT: [OND; 2] = [Some(NoDerive); 2]; //~ NOTE constant defined here
7791
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
78-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
79-
//~| NOTE the traits must be derived
80-
//~| NOTE StructuralPartialEq.html for details
92+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
93+
//~| NOTE constant of non-structural type
8194

8295
trait Trait: Sized { const ASSOC: Option<Self>; } //~ NOTE constant defined here
8396
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
8497
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
85-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
86-
//~| NOTE the traits must be derived
87-
//~| NOTE StructuralPartialEq.html for details
98+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
99+
//~| NOTE constant of non-structural type
88100

89101
const BLOCK: OND = { NoDerive; Some(NoDerive) }; //~ NOTE constant defined here
90102
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
91-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
92-
//~| NOTE the traits must be derived
93-
//~| NOTE StructuralPartialEq.html for details
103+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
104+
//~| NOTE constant of non-structural type
94105

95106
const ADDR_OF: &OND = &Some(NoDerive); //~ NOTE constant defined here
96107
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
97-
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
98-
//~| NOTE the traits must be derived
99-
//~| NOTE StructuralPartialEq.html for details
108+
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
109+
//~| NOTE constant of non-structural type
100110
}

0 commit comments

Comments
 (0)