Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retire the unnamed_fields feature for now #131045

Merged
merged 3 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
12 changes: 0 additions & 12 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 Expand Up @@ -160,14 +156,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
.type = inherent impl for this type
.only_trait = only trait implementations may be annotated with {$annotation}

ast_passes_invalid_unnamed_field =
unnamed fields are not allowed outside of structs or unions
.label = unnamed field declared here

ast_passes_invalid_unnamed_field_ty =
unnamed fields can only have struct or union types
.label = not a struct or union

ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
.suggestion = remove safe from this item

Expand Down
43 changes: 0 additions & 43 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 All @@ -255,7 +252,6 @@ impl<'a> AstValidator<'a> {
if let Some(ident) = field.ident
&& ident.name == kw::Underscore
{
self.check_unnamed_field_ty(&field.ty, ident.span);
self.visit_vis(&field.vis);
self.visit_ident(ident);
self.visit_ty_common(&field.ty);
Expand Down Expand Up @@ -294,39 +290,6 @@ impl<'a> AstValidator<'a> {
}
}

fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) {
if matches!(
&ty.kind,
// We already checked for `kw::Underscore` before calling this function,
// so skip the check
TyKind::AnonStruct(..) | TyKind::AnonUnion(..)
// If the anonymous field contains a Path as type, we can't determine
// if the path is a valid struct or union, so skip the check
| TyKind::Path(..)
) {
return;
}
self.dcx().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span });
}

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 deny_unnamed_field(&self, field: &FieldDef) {
if let Some(ident) = field.ident
&& ident.name == kw::Underscore
{
self.dcx()
.emit_err(errors::InvalidUnnamedField { span: field.span, ident_span: ident.span });
}
}

fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
let Const::Yes(span) = constness else {
return;
Expand Down Expand Up @@ -890,15 +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) {
self.deny_unnamed_field(field);
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
27 changes: 0 additions & 27 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,33 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_passes_invalid_unnamed_field_ty)]
pub(crate) struct InvalidUnnamedFieldTy {
#[primary_span]
pub span: Span,
#[label]
pub ty_span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_passes_invalid_unnamed_field)]
pub(crate) struct InvalidUnnamedField {
#[primary_span]
pub span: Span,
#[label]
pub ident_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
1 change: 0 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are experimental");
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
gate_all!(postfix_match, "postfix match is experimental");
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
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: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ declare_features! (
(removed, test_removed_feature, "1.0.0", None, None),
/// 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, "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: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,6 @@ declare_features! (
/// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528)
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
/// Allows unnamed fields of struct and union type
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
/// Allows const generic parameters to be defined with types that
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
(incomplete, unsized_const_params, "1.82.0", Some(95174)),
Expand Down
15 changes: 0 additions & 15 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,6 @@ hir_analysis_invalid_union_field =
hir_analysis_invalid_union_field_sugg =
wrap the field type in `ManuallyDrop<...>`

hir_analysis_invalid_unnamed_field_ty = unnamed fields can only have struct or union types

hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
.label = const parameter declared here

Expand Down Expand Up @@ -535,19 +533,6 @@ hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_na
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same {$what}

hir_analysis_unnamed_fields_repr_field_defined = unnamed field defined here

hir_analysis_unnamed_fields_repr_field_missing_repr_c =
named type of unnamed field must have `#[repr(C)]` representation
.label = unnamed field defined here
.field_ty_label = `{$field_ty}` defined here
.suggestion = add `#[repr(C)]` to this {$field_adt_kind}

hir_analysis_unnamed_fields_repr_missing_repr_c =
{$adt_kind} with unnamed fields must have `#[repr(C)]` representation
.label = {$adt_kind} `{$adt_name}` defined here
.suggestion = add `#[repr(C)]` to this {$adt_kind}

hir_analysis_unrecognized_atomic_operation =
unrecognized atomic operation function: `{$op}`
.label = unrecognized atomic operation
Expand Down
56 changes: 0 additions & 56 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {

check_transparent(tcx, def);
check_packed(tcx, span, def);
check_unnamed_fields(tcx, def);
}

fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
Expand All @@ -86,61 +85,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_transparent(tcx, def);
check_union_fields(tcx, span, def_id);
check_packed(tcx, span, def);
check_unnamed_fields(tcx, def);
}

/// Check the representation of adts with unnamed fields.
fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) {
if def.is_enum() {
return;
}
let variant = def.non_enum_variant();
if !variant.has_unnamed_fields() {
return;
}
if !def.is_anonymous() {
let adt_kind = def.descr();
let span = tcx.def_span(def.did());
let unnamed_fields = variant
.fields
.iter()
.filter(|f| f.is_unnamed())
.map(|f| {
let span = tcx.def_span(f.did);
errors::UnnamedFieldsReprFieldDefined { span }
})
.collect::<Vec<_>>();
debug_assert_ne!(unnamed_fields.len(), 0, "expect unnamed fields in this adt");
let adt_name = tcx.item_name(def.did());
if !def.repr().c() {
tcx.dcx().emit_err(errors::UnnamedFieldsRepr::MissingReprC {
span,
adt_kind,
adt_name,
unnamed_fields,
sugg_span: span.shrink_to_lo(),
});
}
}
for field in variant.fields.iter().filter(|f| f.is_unnamed()) {
let field_ty = tcx.type_of(field.did).instantiate_identity();
if let Some(adt) = field_ty.ty_adt_def()
&& !adt.is_enum()
{
if !adt.is_anonymous() && !adt.repr().c() {
let field_ty_span = tcx.def_span(adt.did());
tcx.dcx().emit_err(errors::UnnamedFieldsRepr::FieldMissingReprC {
span: tcx.def_span(field.did),
field_ty_span,
field_ty,
field_adt_kind: adt.descr(),
sugg_span: field_ty_span.shrink_to_lo(),
});
}
} else {
tcx.dcx().emit_err(errors::InvalidUnnamedFieldTy { span: tcx.def_span(field.did) });
}
}
}

/// Check that the fields of the `union` do not need dropping.
Expand Down
Loading
Loading