diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 37f429cce44..4a92cc881fa 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2167,10 +2167,6 @@ pub enum TyKind {
Never,
/// A tuple (`(A, B, C, D,...)`).
Tup(ThinVec
>),
- /// An anonymous struct type i.e. `struct { foo: Type }`.
- AnonStruct(NodeId, ThinVec),
- /// An anonymous union type i.e. `union { bar: Type }`.
- AnonUnion(NodeId, ThinVec),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g., ` as SomeTrait>::SomeType`.
///
@@ -2227,10 +2223,6 @@ impl TyKind {
None
}
}
-
- pub fn is_anon_adt(&self) -> bool {
- matches!(self, TyKind::AnonStruct(..) | TyKind::AnonUnion(..))
- }
}
/// Syntax used to declare a trait object.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 104f84f26e0..a59eed4125c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -519,10 +519,6 @@ pub fn walk_ty(vis: &mut T, ty: &mut P) {
visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl));
}
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
- TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
- vis.visit_id(id);
- fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
- }
}
visit_lazy_tts(vis, tokens);
vis.visit_span(span);
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 1a80a9ccdbf..a517f17c82c 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -287,12 +287,6 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
| ast::TyKind::Pat(..)
| ast::TyKind::Dummy
| ast::TyKind::Err(..) => break None,
-
- // These end in brace, but cannot occur in a let-else statement.
- // They are only parsed as fields of a data structure. For the
- // purpose of denying trailing braces in the expression of a
- // let-else, we can disregard these.
- ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None,
}
}
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 9f9c3d8c392..4dcadb8517e 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -535,9 +535,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
TyKind::Err(_guar) => {}
TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
TyKind::Never | TyKind::CVarArgs => {}
- TyKind::AnonStruct(_id, ref fields) | TyKind::AnonUnion(_id, ref fields) => {
- walk_list!(visitor, visit_field_def, fields);
- }
}
V::Result::output()
}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index c6cb7aa7dd5..e38374281f7 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1264,46 +1264,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err(guar) => hir::TyKind::Err(*guar),
- // Lower the anonymous structs or unions in a nested lowering context.
- //
- // ```
- // struct Foo {
- // _: union {
- // // ^__________________ <-- within the nested lowering context,
- // /* fields */ // | we lower all fields defined into an
- // } // | owner node of struct or union item
- // // ^_____________________|
- // }
- // ```
- TyKind::AnonStruct(node_id, fields) | TyKind::AnonUnion(node_id, fields) => {
- // Here its `def_id` is created in `build_reduced_graph`.
- let def_id = self.local_def_id(*node_id);
- debug!(?def_id);
- let owner_id = hir::OwnerId { def_id };
- self.with_hir_id_owner(*node_id, |this| {
- let fields = this.arena.alloc_from_iter(
- fields.iter().enumerate().map(|f| this.lower_field_def(f)),
- );
- let span = t.span;
- let variant_data =
- hir::VariantData::Struct { fields, recovered: ast::Recovered::No };
- // FIXME: capture the generics from the outer adt.
- let generics = hir::Generics::empty();
- let kind = match t.kind {
- TyKind::AnonStruct(..) => hir::ItemKind::Struct(variant_data, generics),
- TyKind::AnonUnion(..) => hir::ItemKind::Union(variant_data, generics),
- _ => unreachable!(),
- };
- hir::OwnerNode::Item(this.arena.alloc(hir::Item {
- ident: Ident::new(kw::Empty, span),
- owner_id,
- kind,
- span: this.lower_span(span),
- vis_span: this.lower_span(span.shrink_to_lo()),
- }))
- });
- hir::TyKind::AnonAdt(hir::ItemId { owner_id })
- }
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Ref(region, mt) => {
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 0146a8d9082..7cfbd6c6c6c 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -1,7 +1,3 @@
-ast_passes_anon_struct_or_union_not_allowed =
- anonymous {$struct_or_union}s are not allowed outside of unnamed struct or union fields
- .label = anonymous {$struct_or_union} declared here
-
ast_passes_assoc_const_without_body =
associated constant in `impl` without body
.suggestion = provide a definition for the constant
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b3d91d881c4..f99654a9a65 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -244,9 +244,6 @@ impl<'a> AstValidator<'a> {
}
}
}
- TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
- walk_list!(self, visit_struct_field_def, fields)
- }
_ => visit::walk_ty(self, t),
}
}
@@ -293,15 +290,6 @@ impl<'a> AstValidator<'a> {
}
}
- fn deny_anon_struct_or_union(&self, ty: &Ty) {
- let struct_or_union = match &ty.kind {
- TyKind::AnonStruct(..) => "struct",
- TyKind::AnonUnion(..) => "union",
- _ => return,
- };
- self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span });
- }
-
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
let Const::Yes(span) = constness else {
return;
@@ -865,14 +853,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_ty(&mut self, ty: &'a Ty) {
self.visit_ty_common(ty);
- self.deny_anon_struct_or_union(ty);
self.walk_ty(ty)
}
- fn visit_field_def(&mut self, field: &'a FieldDef) {
- visit::walk_field_def(self, field)
- }
-
fn visit_item(&mut self, item: &'a Item) {
if item.attrs.iter().any(|attr| attr.is_proc_macro_attr()) {
self.has_proc_macro_decls = true;
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 07515897c69..c60925b3049 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -814,15 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation {
pub span: Span,
}
-#[derive(Diagnostic)]
-#[diag(ast_passes_anon_struct_or_union_not_allowed)]
-pub(crate) struct AnonStructOrUnionNotAllowed {
- #[primary_span]
- #[label]
- pub span: Span,
- pub struct_or_union: &'static str,
-}
-
#[derive(Diagnostic)]
#[diag(ast_passes_match_arm_with_no_body)]
pub(crate) struct MatchArmWithNoBody {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 7e07ccf28a0..01713a9beca 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1174,14 +1174,6 @@ impl<'a> State<'a> {
}
self.pclose();
}
- ast::TyKind::AnonStruct(_, fields) => {
- self.head("struct");
- self.print_record_struct_body(fields, ty.span);
- }
- ast::TyKind::AnonUnion(_, fields) => {
- self.head("union");
- self.print_record_struct_body(fields, ty.span);
- }
ast::TyKind::Paren(typ) => {
self.popen();
self.print_type(typ);
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index dde696fca61..f79227d52a8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -113,7 +113,7 @@ fn cs_clone_simple(
// Already produced an assertion for this type.
// Anonymous structs or unions must be eliminated as they cannot be
// type parameters.
- } else if !field.ty.kind.is_anon_adt() {
+ } else {
// let _: AssertParamIsClone;
super::assert_ty_bounds(cx, &mut stmts, field.ty.clone(), field.span, &[
sym::clone,
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index d5ee5e430d5..e884c0ec718 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -124,8 +124,6 @@ fn assert_ty_bounds(
span: Span,
assert_path: &[Symbol],
) {
- // Deny anonymous structs or unions to avoid weird errors.
- assert!(!ty.kind.is_anon_adt(), "Anonymous structs or unions cannot be type parameters");
// Generate statement `let _: assert_path;`.
let span = cx.with_def_site_ctxt(span);
let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]);
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 276814dd0d9..85bc1460b3e 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -217,7 +217,7 @@ declare_features! (
/// Allows using items which are missing stability attributes
(removed, unmarked_api, "1.0.0", None, None),
/// Allows unnamed fields of struct and union type
- (removed, unnamed_fields, "1.74.0", Some(49804)),
+ (removed, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), Some("feature needs redesign")),
(removed, unsafe_no_drop_flag, "1.0.0", None, None),
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
(removed, untagged_unions, "1.13.0", Some(55149),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 13681c00f8e..36733726564 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1984,7 +1984,7 @@ impl<'a> Parser<'a> {
}
}
self.expect_field_ty_separator()?;
- let ty = self.parse_ty_for_field_def()?;
+ let ty = self.parse_ty()?;
if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) {
self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span });
}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a8ed8b5df9c..625a4cabdf2 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -128,17 +128,6 @@ impl<'a> Parser<'a> {
)
}
- /// Parse a type suitable for a field definition.
- /// The difference from `parse_ty` is that this version
- /// allows anonymous structs and unions.
- pub(super) fn parse_ty_for_field_def(&mut self) -> PResult<'a, P> {
- if self.can_begin_anon_struct_or_union() {
- self.parse_anon_struct_or_union()
- } else {
- self.parse_ty()
- }
- }
-
/// Parse a type suitable for a function or function pointer parameter.
/// The difference from `parse_ty` is that this version allows `...`
/// (`CVarArgs`) at the top level of the type.
@@ -382,37 +371,6 @@ impl<'a> Parser<'a> {
if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
}
- /// Parse an anonymous struct or union (only for field definitions):
- /// ```ignore (feature-not-ready)
- /// #[repr(C)]
- /// struct Foo {
- /// _: struct { // anonymous struct
- /// x: u32,
- /// y: f64,
- /// }
- /// _: union { // anonymous union
- /// z: u32,
- /// w: f64,
- /// }
- /// }
- /// ```
- fn parse_anon_struct_or_union(&mut self) -> PResult<'a, P> {
- assert!(self.token.is_keyword(kw::Union) || self.token.is_keyword(kw::Struct));
- let is_union = self.token.is_keyword(kw::Union);
-
- let lo = self.token.span;
- self.bump();
-
- let (fields, _recovered) =
- self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?;
- let span = lo.to(self.prev_token.span);
- self.psess.gated_spans.gate(sym::unnamed_fields, span);
- let id = ast::DUMMY_NODE_ID;
- let kind =
- if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) };
- Ok(self.mk_ty(span, kind))
- }
-
/// Parses either:
/// - `(TYPE)`, a parenthesized type.
/// - `(TYPE,)`, a tuple with a single field of type TYPE.
@@ -813,11 +771,6 @@ impl<'a> Parser<'a> {
Ok(bounds)
}
- pub(super) fn can_begin_anon_struct_or_union(&mut self) -> bool {
- (self.token.is_keyword(kw::Struct) || self.token.is_keyword(kw::Union))
- && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace))
- }
-
/// Can the current token begin a bound?
fn can_begin_bound(&mut self) -> bool {
self.check_path()
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 903fb114744..e89838b22ab 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -583,8 +583,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
BareFn,
Never,
Tup,
- AnonStruct,
- AnonUnion,
Path,
Pat,
TraitObject,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a9ea268e51a..ae7389342ec 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -724,29 +724,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
// Record field names for error reporting.
self.insert_field_idents(def_id, fields);
self.insert_field_visibilities_local(def_id.to_def_id(), fields);
-
- for field in fields {
- match &field.ty.kind {
- ast::TyKind::AnonStruct(id, nested_fields)
- | ast::TyKind::AnonUnion(id, nested_fields) => {
- let feed = self.r.feed(*id);
- let local_def_id = feed.key();
- let def_id = local_def_id.to_def_id();
- let def_kind = self.r.tcx.def_kind(local_def_id);
- let res = Res::Def(def_kind, def_id);
- self.build_reduced_graph_for_struct_variant(
- &nested_fields,
- Ident::empty(),
- feed,
- res,
- // Anonymous adts inherit visibility from their parent adts.
- adt_vis,
- field.ty.span,
- );
- }
- _ => {}
- }
- }
}
/// Constructs the reduced graph for one item.
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 98662385434..0047f2c4b51 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -105,22 +105,6 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
let def = self.create_def(field.id, name, DefKind::Field, field.span);
self.with_parent(def, |this| visit::walk_field_def(this, field));
- self.visit_anon_adt(&field.ty);
- }
- }
-
- fn visit_anon_adt(&mut self, ty: &'a Ty) {
- let def_kind = match &ty.kind {
- TyKind::AnonStruct(..) => DefKind::Struct,
- TyKind::AnonUnion(..) => DefKind::Union,
- _ => return,
- };
- match &ty.kind {
- TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => {
- let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span);
- self.with_parent(def_id, |this| visit::walk_ty(this, ty));
- }
- _ => {}
}
}
@@ -476,8 +460,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
fn visit_ty(&mut self, ty: &'a Ty) {
match &ty.kind {
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
- // Anonymous structs or unions are visited later after defined.
- TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
TyKind::ImplTrait(id, _) => {
// HACK: pprust breaks strings with newlines when the type
// gets too long. We don't want these to show up in compiler
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 07b483b2b37..f75c4f0fad7 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -951,8 +951,6 @@ impl Rewrite for ast::Ty {
ast::TyKind::Tup(ref items) => {
rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
}
- ast::TyKind::AnonStruct(..) => Ok(context.snippet(self.span).to_owned()),
- ast::TyKind::AnonUnion(..) => Ok(context.snippet(self.span).to_owned()),
ast::TyKind::Path(ref q_self, ref path) => {
rewrite_path(context, PathContext::Type, q_self, path, shape)
}
diff --git a/src/tools/rustfmt/tests/target/anonymous-types.rs b/src/tools/rustfmt/tests/target/anonymous-types.rs
deleted file mode 100644
index e8c2d83878c..00000000000
--- a/src/tools/rustfmt/tests/target/anonymous-types.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Test for issue 85480
-// Pretty print anonymous struct and union types
-
-// pp-exact
-// pretty-compare-only
-
-struct Foo {
- _: union {
- _: struct {
- a: u8,
- b: u16,
- },
- c: u32,
- },
- d: u64,
- e: f32,
-}
-
-// Test for https://github.com/rust-lang/rust/issues/117942
-struct Foo {
- _: union {
- #[rustfmt::skip]
- f: String,
- },
- #[rustfmt::skip]
- _: struct {
- g: i32,
- },
-}
-
-fn main() {}