Skip to content

Commit

Permalink
Remove anon struct and union types
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Oct 1, 2024
1 parent e3a0da1 commit 40465d2
Show file tree
Hide file tree
Showing 19 changed files with 3 additions and 227 deletions.
8 changes: 0 additions & 8 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2167,10 +2167,6 @@ pub enum TyKind {
Never,
/// A tuple (`(A, B, C, D,...)`).
Tup(ThinVec<P<Ty>>),
/// An anonymous struct type i.e. `struct { foo: Type }`.
AnonStruct(NodeId, ThinVec<FieldDef>),
/// An anonymous union type i.e. `union { bar: Type }`.
AnonUnion(NodeId, ThinVec<FieldDef>),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
///
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,10 +519,6 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
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);
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
40 changes: 0 additions & 40 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
@@ -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
Expand Down
17 changes: 0 additions & 17 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/deriving/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<FieldTy>;
super::assert_ty_bounds(cx, &mut stmts, field.ty.clone(), field.span, &[
sym::clone,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_builtin_macros/src/deriving/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ty>;`.
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)]);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
Expand Down
47 changes: 0 additions & 47 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ty>> {
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.
Expand Down Expand Up @@ -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<Ty>> {
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.
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_passes/src/hir_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
BareFn,
Never,
Tup,
AnonStruct,
AnonUnion,
Path,
Pat,
TraitObject,
Expand Down
23 changes: 0 additions & 23 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 0 additions & 18 deletions compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
_ => {}
}
}

Expand Down Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions src/tools/rustfmt/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
31 changes: 0 additions & 31 deletions src/tools/rustfmt/tests/target/anonymous-types.rs

This file was deleted.

0 comments on commit 40465d2

Please sign in to comment.