Skip to content

Commit e3a0da1

Browse files
Remove unnamed field feature
1 parent 8dd5cd0 commit e3a0da1

40 files changed

+30
-3209
lines changed

Diff for: compiler/rustc_ast_passes/messages.ftl

-8
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
160160
.type = inherent impl for this type
161161
.only_trait = only trait implementations may be annotated with {$annotation}
162162
163-
ast_passes_invalid_unnamed_field =
164-
unnamed fields are not allowed outside of structs or unions
165-
.label = unnamed field declared here
166-
167-
ast_passes_invalid_unnamed_field_ty =
168-
unnamed fields can only have struct or union types
169-
.label = not a struct or union
170-
171163
ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
172164
.suggestion = remove safe from this item
173165

Diff for: compiler/rustc_ast_passes/src/ast_validation.rs

-26
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ impl<'a> AstValidator<'a> {
255255
if let Some(ident) = field.ident
256256
&& ident.name == kw::Underscore
257257
{
258-
self.check_unnamed_field_ty(&field.ty, ident.span);
259258
self.visit_vis(&field.vis);
260259
self.visit_ident(ident);
261260
self.visit_ty_common(&field.ty);
@@ -294,21 +293,6 @@ impl<'a> AstValidator<'a> {
294293
}
295294
}
296295

297-
fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) {
298-
if matches!(
299-
&ty.kind,
300-
// We already checked for `kw::Underscore` before calling this function,
301-
// so skip the check
302-
TyKind::AnonStruct(..) | TyKind::AnonUnion(..)
303-
// If the anonymous field contains a Path as type, we can't determine
304-
// if the path is a valid struct or union, so skip the check
305-
| TyKind::Path(..)
306-
) {
307-
return;
308-
}
309-
self.dcx().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span });
310-
}
311-
312296
fn deny_anon_struct_or_union(&self, ty: &Ty) {
313297
let struct_or_union = match &ty.kind {
314298
TyKind::AnonStruct(..) => "struct",
@@ -318,15 +302,6 @@ impl<'a> AstValidator<'a> {
318302
self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span });
319303
}
320304

321-
fn deny_unnamed_field(&self, field: &FieldDef) {
322-
if let Some(ident) = field.ident
323-
&& ident.name == kw::Underscore
324-
{
325-
self.dcx()
326-
.emit_err(errors::InvalidUnnamedField { span: field.span, ident_span: ident.span });
327-
}
328-
}
329-
330305
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
331306
let Const::Yes(span) = constness else {
332307
return;
@@ -895,7 +870,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
895870
}
896871

897872
fn visit_field_def(&mut self, field: &'a FieldDef) {
898-
self.deny_unnamed_field(field);
899873
visit::walk_field_def(self, field)
900874
}
901875

Diff for: compiler/rustc_ast_passes/src/errors.rs

-18
Original file line numberDiff line numberDiff line change
@@ -814,24 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation {
814814
pub span: Span,
815815
}
816816

817-
#[derive(Diagnostic)]
818-
#[diag(ast_passes_invalid_unnamed_field_ty)]
819-
pub(crate) struct InvalidUnnamedFieldTy {
820-
#[primary_span]
821-
pub span: Span,
822-
#[label]
823-
pub ty_span: Span,
824-
}
825-
826-
#[derive(Diagnostic)]
827-
#[diag(ast_passes_invalid_unnamed_field)]
828-
pub(crate) struct InvalidUnnamedField {
829-
#[primary_span]
830-
pub span: Span,
831-
#[label]
832-
pub ident_span: Span,
833-
}
834-
835817
#[derive(Diagnostic)]
836818
#[diag(ast_passes_anon_struct_or_union_not_allowed)]
837819
pub(crate) struct AnonStructOrUnionNotAllowed {

Diff for: compiler/rustc_ast_passes/src/feature_gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
541541
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
542542
gate_all!(explicit_tail_calls, "`become` expression is experimental");
543543
gate_all!(generic_const_items, "generic const items are experimental");
544-
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
545544
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
546545
gate_all!(postfix_match, "postfix match is experimental");
547546
gate_all!(mut_ref, "mutable by-reference bindings are experimental");

Diff for: compiler/rustc_feature/src/removed.rs

+2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ declare_features! (
216216
(removed, test_removed_feature, "1.0.0", None, None),
217217
/// Allows using items which are missing stability attributes
218218
(removed, unmarked_api, "1.0.0", None, None),
219+
/// Allows unnamed fields of struct and union type
220+
(removed, unnamed_fields, "1.74.0", Some(49804)),
219221
(removed, unsafe_no_drop_flag, "1.0.0", None, None),
220222
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
221223
(removed, untagged_unions, "1.13.0", Some(55149),

Diff for: compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,6 @@ declare_features! (
618618
/// Allows creation of instances of a struct by moving fields that have
619619
/// not changed from prior instances of the same struct (RFC #2528)
620620
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
621-
/// Allows unnamed fields of struct and union type
622-
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
623621
/// Allows const generic parameters to be defined with types that
624622
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
625623
(incomplete, unsized_const_params, "1.82.0", Some(95174)),

Diff for: compiler/rustc_hir_analysis/messages.ftl

-15
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ hir_analysis_invalid_union_field =
248248
hir_analysis_invalid_union_field_sugg =
249249
wrap the field type in `ManuallyDrop<...>`
250250
251-
hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types
252-
253251
hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
254252
.label = const parameter declared here
255253
@@ -535,19 +533,6 @@ hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_na
535533
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
536534
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
537535
538-
hir_analysis_unnamed_fields_repr_field_defined = unnamed field defined here
539-
540-
hir_analysis_unnamed_fields_repr_field_missing_repr_c =
541-
named type of unnamed field must have `#[repr(C)]` representation
542-
.label = unnamed field defined here
543-
.field_ty_label = `{$field_ty}` defined here
544-
.suggestion = add `#[repr(C)]` to this {$field_adt_kind}
545-
546-
hir_analysis_unnamed_fields_repr_missing_repr_c =
547-
{$adt_kind} with unnamed fields must have `#[repr(C)]` representation
548-
.label = {$adt_kind} `{$adt_name}` defined here
549-
.suggestion = add `#[repr(C)]` to this {$adt_kind}
550-
551536
hir_analysis_unrecognized_atomic_operation =
552537
unrecognized atomic operation function: `{$op}`
553538
.label = unrecognized atomic operation

Diff for: compiler/rustc_hir_analysis/src/check/check.rs

-56
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
7676

7777
check_transparent(tcx, def);
7878
check_packed(tcx, span, def);
79-
check_unnamed_fields(tcx, def);
8079
}
8180

8281
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
@@ -86,61 +85,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
8685
check_transparent(tcx, def);
8786
check_union_fields(tcx, span, def_id);
8887
check_packed(tcx, span, def);
89-
check_unnamed_fields(tcx, def);
90-
}
91-
92-
/// Check the representation of adts with unnamed fields.
93-
fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) {
94-
if def.is_enum() {
95-
return;
96-
}
97-
let variant = def.non_enum_variant();
98-
if !variant.has_unnamed_fields() {
99-
return;
100-
}
101-
if !def.is_anonymous() {
102-
let adt_kind = def.descr();
103-
let span = tcx.def_span(def.did());
104-
let unnamed_fields = variant
105-
.fields
106-
.iter()
107-
.filter(|f| f.is_unnamed())
108-
.map(|f| {
109-
let span = tcx.def_span(f.did);
110-
errors::UnnamedFieldsReprFieldDefined { span }
111-
})
112-
.collect::<Vec<_>>();
113-
debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt");
114-
let adt_name = tcx.item_name(def.did());
115-
if !def.repr().c() {
116-
tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC {
117-
span,
118-
adt_kind,
119-
adt_name,
120-
unnamed_fields,
121-
sugg_span: span.shrink_to_lo(),
122-
});
123-
}
124-
}
125-
for field in variant.fields.iter().filter(|f| f.is_unnamed()) {
126-
let field_ty = tcx.type_of(field.did).instantiate_identity();
127-
if let Some(adt) = field_ty.ty_adt_def()
128-
&& !adt.is_enum()
129-
{
130-
if !adt.is_anonymous() && !adt.repr().c() {
131-
let field_ty_span = tcx.def_span(adt.did());
132-
tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC {
133-
span: tcx.def_span(field.did),
134-
field_ty_span,
135-
field_ty,
136-
field_adt_kind: adt.descr(),
137-
sugg_span: field_ty_span.shrink_to_lo(),
138-
});
139-
}
140-
} else {
141-
tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) });
142-
}
143-
}
14488
}
14589

14690
/// Check that the fields of the `union` do not need dropping.

Diff for: compiler/rustc_hir_analysis/src/collect.rs

+4-100
Original file line numberDiff line numberDiff line change
@@ -1007,79 +1007,6 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> {
10071007
}
10081008
}
10091009
}
1010-
1011-
/// Check the uniqueness of fields across adt where there are
1012-
/// nested fields imported from an unnamed field.
1013-
fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) {
1014-
for field in adt_def.all_fields() {
1015-
if field.is_unnamed() {
1016-
// Here we don't care about the generic parameters, so `instantiate_identity` is enough.
1017-
match self.tcx.type_of(field.did).instantiate_identity().kind() {
1018-
ty::Adt(adt_def, _) => {
1019-
self.check_field_in_nested_adt(*adt_def, unnamed_field_span);
1020-
}
1021-
ty_kind => span_bug!(
1022-
self.tcx.def_span(field.did),
1023-
"Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}"
1024-
),
1025-
}
1026-
} else {
1027-
self.check_field_decl(
1028-
field.ident(self.tcx),
1029-
NestedSpan {
1030-
span: unnamed_field_span,
1031-
nested_field_span: self.tcx.def_span(field.did),
1032-
}
1033-
.into(),
1034-
);
1035-
}
1036-
}
1037-
}
1038-
1039-
/// Check the uniqueness of fields in a struct variant, and recursively
1040-
/// check the nested fields if it is an unnamed field with type of an
1041-
/// anonymous adt.
1042-
fn check_field(&mut self, field: &hir::FieldDef<'_>) {
1043-
if field.ident.name != kw::Underscore {
1044-
self.check_field_decl(field.ident, field.span.into());
1045-
return;
1046-
}
1047-
match &field.ty.kind {
1048-
hir::TyKind::AnonAdt(item_id) => {
1049-
match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind {
1050-
hir::ItemKind::Struct(variant_data, ..)
1051-
| hir::ItemKind::Union(variant_data, ..) => {
1052-
variant_data.fields().iter().for_each(|f| self.check_field(f));
1053-
}
1054-
item_kind => span_bug!(
1055-
field.ty.span,
1056-
"Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}"
1057-
),
1058-
}
1059-
}
1060-
hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => {
1061-
// If this is a direct path to an ADT, we can check it
1062-
// If this is a type alias or non-ADT, `check_unnamed_fields` should verify it
1063-
if let Some(def_id) = res.opt_def_id()
1064-
&& let Some(local) = def_id.as_local()
1065-
&& let Node::Item(item) = self.tcx.hir_node_by_def_id(local)
1066-
&& item.is_adt()
1067-
{
1068-
self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span);
1069-
}
1070-
}
1071-
// Abort due to errors (there must be an error if an unnamed field
1072-
// has any type kind other than an anonymous adt or a named adt)
1073-
ty_kind => {
1074-
self.tcx.dcx().span_delayed_bug(
1075-
field.ty.span,
1076-
format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"),
1077-
);
1078-
// FIXME: errors during AST validation should abort the compilation before reaching here.
1079-
self.tcx.dcx().abort_if_errors();
1080-
}
1081-
}
1082-
}
10831010
}
10841011

10851012
fn lower_variant(
@@ -1090,20 +1017,13 @@ fn lower_variant(
10901017
def: &hir::VariantData<'_>,
10911018
adt_kind: ty::AdtKind,
10921019
parent_did: LocalDefId,
1093-
is_anonymous: bool,
10941020
) -> ty::VariantDef {
1095-
let mut has_unnamed_fields = false;
10961021
let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
10971022
let fields = def
10981023
.fields()
10991024
.iter()
1100-
.inspect(|f| {
1101-
has_unnamed_fields |= f.ident.name == kw::Underscore;
1102-
// We only check named ADT here because anonymous ADTs are checked inside
1103-
// the named ADT in which they are defined.
1104-
if !is_anonymous {
1105-
field_uniqueness_check_ctx.check_field(f);
1106-
}
1025+
.inspect(|field| {
1026+
field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
11071027
})
11081028
.map(|f| ty::FieldDef {
11091029
did: f.def_id.to_def_id(),
@@ -1127,7 +1047,6 @@ fn lower_variant(
11271047
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
11281048
|| variant_did
11291049
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
1130-
has_unnamed_fields,
11311050
)
11321051
}
11331052

@@ -1138,20 +1057,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
11381057
bug!("expected ADT to be an item");
11391058
};
11401059

1141-
let is_anonymous = item.ident.name == kw::Empty;
1142-
let repr = if is_anonymous {
1143-
let parent = tcx.local_parent(def_id);
1144-
if let Node::Item(item) = tcx.hir_node_by_def_id(parent)
1145-
&& item.is_struct_or_union()
1146-
{
1147-
tcx.adt_def(parent).repr()
1148-
} else {
1149-
tcx.dcx().span_delayed_bug(item.span, "anonymous field inside non struct/union");
1150-
ty::ReprOptions::default()
1151-
}
1152-
} else {
1153-
tcx.repr_options_of_def(def_id)
1154-
};
1060+
let repr = tcx.repr_options_of_def(def_id);
11551061
let (kind, variants) = match &item.kind {
11561062
ItemKind::Enum(def, _) => {
11571063
let mut distance_from_explicit = 0;
@@ -1175,7 +1081,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
11751081
&v.data,
11761082
AdtKind::Enum,
11771083
def_id,
1178-
is_anonymous,
11791084
)
11801085
})
11811086
.collect();
@@ -1195,15 +1100,14 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
11951100
def,
11961101
adt_kind,
11971102
def_id,
1198-
is_anonymous,
11991103
))
12001104
.collect();
12011105

12021106
(adt_kind, variants)
12031107
}
12041108
_ => bug!("{:?} is not an ADT", item.owner_id.def_id),
12051109
};
1206-
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous)
1110+
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
12071111
}
12081112

12091113
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {

0 commit comments

Comments
 (0)