Add more checks for unnamed_field
during HIR analysis · rust-lang/rust@62b789f (original) (raw)
File tree
8 files changed
lines changed
- tests/ui/union/unnamed-fields
8 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2998,6 +2998,12 @@ impl<'hir> Item<'hir> { | ||
2998 | 2998 | ItemId { owner_id: self.owner_id } |
2999 | 2999 | } |
3000 | 3000 | |
3001 | +/// Check if this is an [`ItemKind::Enum`], [`ItemKind::Struct`] or | |
3002 | + /// [`ItemKind::Union`]. | |
3003 | + pub fn is_adt(&self) -> bool { | |
3004 | +matches!(self.kind, ItemKind::Enum(..) | ItemKind::Struct(..) | |
3005 | +} | |
3006 | + | |
3001 | 3007 | expect_methods_self_kind! { |
3002 | 3008 | expect_extern_crate, Option<Symbol>, ItemKind::ExternCrate(s), *s; |
3003 | 3009 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -198,6 +198,8 @@ hir_analysis_invalid_union_field = | ||
198 | 198 | hir_analysis_invalid_union_field_sugg = |
199 | 199 | wrap the field type in `ManuallyDrop<...>` |
200 | 200 | |
201 | +hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types | |
202 | + | |
201 | 203 | hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl |
202 | 204 | .label = const parameter declared here |
203 | 205 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -129,17 +129,20 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) { | ||
129 | 129 | for field in variant.fields.iter().filter(|f |
130 | 130 | let field_ty = tcx.type_of(field.did).instantiate_identity(); |
131 | 131 | if let Some(adt) = field_ty.ty_adt_def() |
132 | - && !adt.is_anonymous() | |
133 | - && !adt.repr().c() | |
132 | + && !adt.is_enum() | |
134 | 133 | { |
135 | -let field_ty_span = tcx.def_span(adt.did()); | |
136 | - tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { | |
137 | -span: tcx.def_span(field.did), | |
138 | - field_ty_span, | |
139 | - field_ty, | |
140 | -field_adt_kind: adt.descr(), | |
141 | -sugg_span: field_ty_span.shrink_to_lo(), | |
142 | -}); | |
134 | +if !adt.is_anonymous() && !adt.repr().c() { | |
135 | +let field_ty_span = tcx.def_span(adt.did()); | |
136 | + tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC { | |
137 | +span: tcx.def_span(field.did), | |
138 | + field_ty_span, | |
139 | + field_ty, | |
140 | +field_adt_kind: adt.descr(), | |
141 | +sugg_span: field_ty_span.shrink_to_lo(), | |
142 | +}); | |
143 | +} | |
144 | +} else { | |
145 | + tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) }); | |
143 | 146 | } |
144 | 147 | } |
145 | 148 | } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -943,7 +943,15 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { | ||
943 | 943 | } |
944 | 944 | } |
945 | 945 | hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => { |
946 | -self.check_field_in_nested_adt(self.tcx.adt_def(res.def_id()), field.span); | |
946 | +// If this is a direct path to an ADT, we can check it | |
947 | +// If this is a type alias or non-ADT, `check_unnamed_fields` should verify it | |
948 | +if let Some(def_id) = res.opt_def_id() | |
949 | + && let Some(local) = def_id.as_local() | |
950 | + && let Node::Item(item) = self.tcx.hir_node_by_def_id(local) | |
951 | + && item.is_adt() | |
952 | +{ | |
953 | +self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span); | |
954 | +} | |
947 | 955 | } |
948 | 956 | // Abort due to errors (there must be an error if an unnamed field |
949 | 957 | // has any type kind other than an anonymous adt or a named adt) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -661,6 +661,13 @@ pub(crate) struct InvalidUnionField { | ||
661 | 661 | pub note: (), |
662 | 662 | } |
663 | 663 | |
664 | +#[derive(Diagnostic)] | |
665 | +#[diag(hir_analysis_invalid_unnamed_field_ty)] | |
666 | +pub struct InvalidUnnamedFieldTy { | |
667 | +#[primary_span] | |
668 | +pub span: Span, | |
669 | +} | |
670 | + | |
664 | 671 | #[derive(Diagnostic)] |
665 | 672 | #[diag(hir_analysis_return_type_notation_on_non_rpitit)] |
666 | 673 | pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
1 | +#[repr(C)] | |
2 | +pub struct GoodStruct(()); | |
3 | + | |
4 | +pub struct BadStruct(()); | |
5 | + | |
6 | +pub enum BadEnum { | |
7 | +A, | |
8 | +B, | |
9 | +} | |
10 | + | |
11 | +#[repr(C)] | |
12 | +pub enum BadEnum2 { | |
13 | +A, | |
14 | +B, | |
15 | +} | |
16 | + | |
17 | +pub type GoodAlias = GoodStruct; | |
18 | +pub type BadAlias = i32; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
1 | +//@ aux-build:dep.rs | |
2 | + | |
3 | +// test for #121151 | |
4 | + | |
5 | +#![allow(incomplete_features)] | |
6 | +#![feature(unnamed_fields)] | |
7 | + | |
8 | +extern crate dep; | |
9 | + | |
10 | +#[repr(C)] | |
11 | +struct A { | |
12 | +a: u8, | |
13 | +} | |
14 | + | |
15 | +enum BadEnum { | |
16 | +A, | |
17 | +B, | |
18 | +} | |
19 | + | |
20 | +#[repr(C)] | |
21 | +enum BadEnum2 { | |
22 | +A, | |
23 | +B, | |
24 | +} | |
25 | + | |
26 | +type MyStruct = A; | |
27 | +type MyI32 = i32; | |
28 | + | |
29 | +#[repr(C)] | |
30 | +struct L { | |
31 | +_: i32, //~ ERROR unnamed fields can only have struct or union types | |
32 | +_: MyI32, //~ ERROR unnamed fields can only have struct or union types | |
33 | +_: BadEnum, //~ ERROR unnamed fields can only have struct or union types | |
34 | +_: BadEnum2, //~ ERROR unnamed fields can only have struct or union types | |
35 | +_: MyStruct, | |
36 | +_: dep::BadStruct, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation | |
37 | +_: dep::BadEnum, //~ ERROR unnamed fields can only have struct or union types | |
38 | +_: dep::BadEnum2, //~ ERROR unnamed fields can only have struct or union types | |
39 | +_: dep::BadAlias, //~ ERROR unnamed fields can only have struct or union types | |
40 | +_: dep::GoodAlias, | |
41 | +_: dep::GoodStruct, | |
42 | +} | |
43 | + | |
44 | +fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
1 | +error: unnamed fields can only have struct or union types | |
2 | + --> $DIR/restrict_type_hir.rs:31:5 | |
3 | + | | |
4 | +LL | _: i32, | |
5 | + | ^^^^^^ | |
6 | + | |
7 | +error: unnamed fields can only have struct or union types | |
8 | + --> $DIR/restrict_type_hir.rs:32:5 | |
9 | + | | |
10 | +LL | _: MyI32, | |
11 | + | ^^^^^^^^ | |
12 | + | |
13 | +error: unnamed fields can only have struct or union types | |
14 | + --> $DIR/restrict_type_hir.rs:33:5 | |
15 | + | | |
16 | +LL | _: BadEnum, | |
17 | + | ^^^^^^^^^^ | |
18 | + | |
19 | +error: unnamed fields can only have struct or union types | |
20 | + --> $DIR/restrict_type_hir.rs:34:5 | |
21 | + | | |
22 | +LL | _: BadEnum2, | |
23 | + | ^^^^^^^^^^^ | |
24 | + | |
25 | +error: named type of unnamed field must have `#[repr(C)]` representation | |
26 | + --> $DIR/restrict_type_hir.rs:36:5 | |
27 | + | | |
28 | +LL | _: dep::BadStruct, | |
29 | + | ^^^^^^^^^^^^^^^^^ unnamed field defined here | |
30 | + | | |
31 | + ::: $DIR/auxiliary/dep.rs:4:1 | |
32 | + | | |
33 | +LL | pub struct BadStruct(()); | |
34 | + | -------------------- `BadStruct` defined here | |
35 | + | | |
36 | +help: add `#[repr(C)]` to this struct | |
37 | + --> $DIR/auxiliary/dep.rs:4:1 | |
38 | + | | |
39 | +LL + #[repr(C)] | |
40 | +LL | pub struct BadStruct(()); | |
41 | + | | |
42 | + | |
43 | +error: unnamed fields can only have struct or union types | |
44 | + --> $DIR/restrict_type_hir.rs:37:5 | |
45 | + | | |
46 | +LL | _: dep::BadEnum, | |
47 | + | ^^^^^^^^^^^^^^^ | |
48 | + | |
49 | +error: unnamed fields can only have struct or union types | |
50 | + --> $DIR/restrict_type_hir.rs:38:5 | |
51 | + | | |
52 | +LL | _: dep::BadEnum2, | |
53 | + | ^^^^^^^^^^^^^^^^ | |
54 | + | |
55 | +error: unnamed fields can only have struct or union types | |
56 | + --> $DIR/restrict_type_hir.rs:39:5 | |
57 | + | | |
58 | +LL | _: dep::BadAlias, | |
59 | + | ^^^^^^^^^^^^^^^^ | |
60 | + | |
61 | +error: aborting due to 8 previous errors | |
62 | + |