Remove unnamed field feature

This commit is contained in:
Michael Goulet 2024-09-29 22:10:16 -04:00
parent 8dd5cd0bc1
commit e3a0da1863
40 changed files with 30 additions and 3209 deletions

View File

@ -160,14 +160,6 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
.type = inherent impl for this type .type = inherent impl for this type
.only_trait = only trait implementations may be annotated with {$annotation} .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 ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
.suggestion = remove safe from this item .suggestion = remove safe from this item

View File

@ -255,7 +255,6 @@ impl<'a> AstValidator<'a> {
if let Some(ident) = field.ident if let Some(ident) = field.ident
&& ident.name == kw::Underscore && ident.name == kw::Underscore
{ {
self.check_unnamed_field_ty(&field.ty, ident.span);
self.visit_vis(&field.vis); self.visit_vis(&field.vis);
self.visit_ident(ident); self.visit_ident(ident);
self.visit_ty_common(&field.ty); self.visit_ty_common(&field.ty);
@ -294,21 +293,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) { fn deny_anon_struct_or_union(&self, ty: &Ty) {
let struct_or_union = match &ty.kind { let struct_or_union = match &ty.kind {
TyKind::AnonStruct(..) => "struct", TyKind::AnonStruct(..) => "struct",
@ -318,15 +302,6 @@ impl<'a> AstValidator<'a> {
self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); 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) { fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
let Const::Yes(span) = constness else { let Const::Yes(span) = constness else {
return; return;
@ -895,7 +870,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
fn visit_field_def(&mut self, field: &'a FieldDef) { fn visit_field_def(&mut self, field: &'a FieldDef) {
self.deny_unnamed_field(field);
visit::walk_field_def(self, field) visit::walk_field_def(self, field)
} }

View File

@ -814,24 +814,6 @@ pub(crate) struct NegativeBoundWithParentheticalNotation {
pub span: Span, 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)] #[derive(Diagnostic)]
#[diag(ast_passes_anon_struct_or_union_not_allowed)] #[diag(ast_passes_anon_struct_or_union_not_allowed)]
pub(crate) struct AnonStructOrUnionNotAllowed { pub(crate) struct AnonStructOrUnionNotAllowed {

View File

@ -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!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are 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!(fn_delegation, "functions delegation is not yet fully implemented");
gate_all!(postfix_match, "postfix match is experimental"); gate_all!(postfix_match, "postfix match is experimental");
gate_all!(mut_ref, "mutable by-reference bindings are experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental");

View File

@ -216,6 +216,8 @@ declare_features! (
(removed, test_removed_feature, "1.0.0", None, None), (removed, test_removed_feature, "1.0.0", None, None),
/// Allows using items which are missing stability attributes /// Allows using items which are missing stability attributes
(removed, unmarked_api, "1.0.0", None, None), (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, unsafe_no_drop_flag, "1.0.0", None, None), (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. /// 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), (removed, untagged_unions, "1.13.0", Some(55149),

View File

@ -618,8 +618,6 @@ declare_features! (
/// Allows creation of instances of a struct by moving fields that have /// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528) /// not changed from prior instances of the same struct (RFC #2528)
(unstable, type_changing_struct_update, "1.58.0", Some(86555)), (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 /// Allows const generic parameters to be defined with types that
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`. /// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
(incomplete, unsized_const_params, "1.82.0", Some(95174)), (incomplete, unsized_const_params, "1.82.0", Some(95174)),

View File

@ -248,8 +248,6 @@ hir_analysis_invalid_union_field =
hir_analysis_invalid_union_field_sugg = hir_analysis_invalid_union_field_sugg =
wrap the field type in `ManuallyDrop<...>` 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 hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
.label = const parameter declared here .label = const parameter declared here
@ -535,19 +533,6 @@ hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_na
hir_analysis_unconstrained_opaque_type = unconstrained opaque type hir_analysis_unconstrained_opaque_type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same {$what} .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 = hir_analysis_unrecognized_atomic_operation =
unrecognized atomic operation function: `{$op}` unrecognized atomic operation function: `{$op}`
.label = unrecognized atomic operation .label = unrecognized atomic operation

View File

@ -76,7 +76,6 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_transparent(tcx, def); check_transparent(tcx, def);
check_packed(tcx, span, def); check_packed(tcx, span, def);
check_unnamed_fields(tcx, def);
} }
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
@ -86,61 +85,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_transparent(tcx, def); check_transparent(tcx, def);
check_union_fields(tcx, span, def_id); check_union_fields(tcx, span, def_id);
check_packed(tcx, span, def); 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. /// Check that the fields of the `union` do not need dropping.

View File

@ -1007,79 +1007,6 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> {
} }
} }
} }
/// Check the uniqueness of fields across adt where there are
/// nested fields imported from an unnamed field.
fn check_field_in_nested_adt(&mut self, adt_def: ty::AdtDef<'_>, unnamed_field_span: Span) {
for field in adt_def.all_fields() {
if field.is_unnamed() {
// Here we don't care about the generic parameters, so `instantiate_identity` is enough.
match self.tcx.type_of(field.did).instantiate_identity().kind() {
ty::Adt(adt_def, _) => {
self.check_field_in_nested_adt(*adt_def, unnamed_field_span);
}
ty_kind => span_bug!(
self.tcx.def_span(field.did),
"Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}"
),
}
} else {
self.check_field_decl(
field.ident(self.tcx),
NestedSpan {
span: unnamed_field_span,
nested_field_span: self.tcx.def_span(field.did),
}
.into(),
);
}
}
}
/// Check the uniqueness of fields in a struct variant, and recursively
/// check the nested fields if it is an unnamed field with type of an
/// anonymous adt.
fn check_field(&mut self, field: &hir::FieldDef<'_>) {
if field.ident.name != kw::Underscore {
self.check_field_decl(field.ident, field.span.into());
return;
}
match &field.ty.kind {
hir::TyKind::AnonAdt(item_id) => {
match &self.tcx.hir_node(item_id.hir_id()).expect_item().kind {
hir::ItemKind::Struct(variant_data, ..)
| hir::ItemKind::Union(variant_data, ..) => {
variant_data.fields().iter().for_each(|f| self.check_field(f));
}
item_kind => span_bug!(
field.ty.span,
"Unexpected ItemKind in FieldUniquenessCheckContext::check_field(): {item_kind:?}"
),
}
}
hir::TyKind::Path(hir::QPath::Resolved(_, hir::Path { res, .. })) => {
// If this is a direct path to an ADT, we can check it
// If this is a type alias or non-ADT, `check_unnamed_fields` should verify it
if let Some(def_id) = res.opt_def_id()
&& let Some(local) = def_id.as_local()
&& let Node::Item(item) = self.tcx.hir_node_by_def_id(local)
&& item.is_adt()
{
self.check_field_in_nested_adt(self.tcx.adt_def(def_id), field.span);
}
}
// Abort due to errors (there must be an error if an unnamed field
// has any type kind other than an anonymous adt or a named adt)
ty_kind => {
self.tcx.dcx().span_delayed_bug(
field.ty.span,
format!("Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}"),
);
// FIXME: errors during AST validation should abort the compilation before reaching here.
self.tcx.dcx().abort_if_errors();
}
}
}
} }
fn lower_variant( fn lower_variant(
@ -1090,20 +1017,13 @@ fn lower_variant(
def: &hir::VariantData<'_>, def: &hir::VariantData<'_>,
adt_kind: ty::AdtKind, adt_kind: ty::AdtKind,
parent_did: LocalDefId, parent_did: LocalDefId,
is_anonymous: bool,
) -> ty::VariantDef { ) -> ty::VariantDef {
let mut has_unnamed_fields = false;
let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx); let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
let fields = def let fields = def
.fields() .fields()
.iter() .iter()
.inspect(|f| { .inspect(|field| {
has_unnamed_fields |= f.ident.name == kw::Underscore; field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
// We only check named ADT here because anonymous ADTs are checked inside
// the named ADT in which they are defined.
if !is_anonymous {
field_uniqueness_check_ctx.check_field(f);
}
}) })
.map(|f| ty::FieldDef { .map(|f| ty::FieldDef {
did: f.def_id.to_def_id(), did: f.def_id.to_def_id(),
@ -1127,7 +1047,6 @@ fn lower_variant(
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive) adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|| variant_did || variant_did
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)), .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
has_unnamed_fields,
) )
} }
@ -1138,20 +1057,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
bug!("expected ADT to be an item"); bug!("expected ADT to be an item");
}; };
let is_anonymous = item.ident.name == kw::Empty; let repr = tcx.repr_options_of_def(def_id);
let repr = if is_anonymous {
let parent = tcx.local_parent(def_id);
if let Node::Item(item) = tcx.hir_node_by_def_id(parent)
&& item.is_struct_or_union()
{
tcx.adt_def(parent).repr()
} else {
tcx.dcx().span_delayed_bug(item.span, "anonymous field inside non struct/union");
ty::ReprOptions::default()
}
} else {
tcx.repr_options_of_def(def_id)
};
let (kind, variants) = match &item.kind { let (kind, variants) = match &item.kind {
ItemKind::Enum(def, _) => { ItemKind::Enum(def, _) => {
let mut distance_from_explicit = 0; let mut distance_from_explicit = 0;
@ -1175,7 +1081,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
&v.data, &v.data,
AdtKind::Enum, AdtKind::Enum,
def_id, def_id,
is_anonymous,
) )
}) })
.collect(); .collect();
@ -1195,7 +1100,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
def, def,
adt_kind, adt_kind,
def_id, def_id,
is_anonymous,
)) ))
.collect(); .collect();
@ -1203,7 +1107,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
} }
_ => bug!("{:?} is not an ADT", item.owner_id.def_id), _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
}; };
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous) tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
} }
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {

View File

@ -734,13 +734,6 @@ pub(crate) struct InvalidUnionField {
pub note: (), pub note: (),
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_invalid_unnamed_field_ty)]
pub(crate) struct InvalidUnnamedFieldTy {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_return_type_notation_on_non_rpitit)] #[diag(hir_analysis_return_type_notation_on_non_rpitit)]
pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
@ -1598,41 +1591,6 @@ pub(crate) struct UnconstrainedGenericParameter {
pub const_param_note2: bool, pub const_param_note2: bool,
} }
#[derive(Diagnostic)]
pub(crate) enum UnnamedFieldsRepr<'a> {
#[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)]
MissingReprC {
#[primary_span]
#[label]
span: Span,
adt_kind: &'static str,
adt_name: Symbol,
#[subdiagnostic]
unnamed_fields: Vec<UnnamedFieldsReprFieldDefined>,
#[suggestion(code = "#[repr(C)]\n")]
sugg_span: Span,
},
#[diag(hir_analysis_unnamed_fields_repr_field_missing_repr_c)]
FieldMissingReprC {
#[primary_span]
#[label]
span: Span,
#[label(hir_analysis_field_ty_label)]
field_ty_span: Span,
field_ty: Ty<'a>,
field_adt_kind: &'static str,
#[suggestion(code = "#[repr(C)]\n")]
sugg_span: Span,
},
}
#[derive(Subdiagnostic)]
#[note(hir_analysis_unnamed_fields_repr_field_defined)]
pub(crate) struct UnnamedFieldsReprFieldDefined {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] #[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)]
pub(crate) struct OpaqueCapturesHigherRankedLifetime { pub(crate) struct OpaqueCapturesHigherRankedLifetime {

View File

@ -33,7 +33,6 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_target::abi::{FIRST_VARIANT, FieldIdx}; use rustc_target::abi::{FIRST_VARIANT, FieldIdx};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use smallvec::SmallVec;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
use {rustc_ast as ast, rustc_hir as hir}; use {rustc_ast as ast, rustc_hir as hir};
@ -1722,8 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ident = tcx.adjust_ident(field.ident, variant.def_id); let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span); seen_fields.insert(ident, field.span);
// FIXME: handle nested fields self.write_field_index(field.hir_id, i);
self.write_field_index(field.hir_id, i, Vec::new());
// We don't look at stability attributes on // We don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not // struct-like enums (yet...), but it's definitely not
@ -2367,35 +2365,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self, &self,
base_def: ty::AdtDef<'tcx>, base_def: ty::AdtDef<'tcx>,
ident: Ident, ident: Ident,
nested_fields: &mut SmallVec<[(FieldIdx, &'tcx ty::FieldDef); 1]>, ) -> Option<(FieldIdx, &'tcx ty::FieldDef)> {
) -> bool {
// No way to find a field in an enum. // No way to find a field in an enum.
if base_def.is_enum() { if base_def.is_enum() {
return false; return None;
} }
for (field_idx, field) in base_def.non_enum_variant().fields.iter_enumerated() { for (field_idx, field) in base_def.non_enum_variant().fields.iter_enumerated() {
if field.is_unnamed() { if field.ident(self.tcx).normalize_to_macros_2_0() == ident {
// We have an unnamed field, recurse into the nested ADT to find `ident`.
// If we find it there, return immediately, and `nested_fields` will contain the
// correct path.
nested_fields.push((field_idx, field));
let field_ty = self.tcx.type_of(field.did).instantiate_identity();
let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field");
if self.find_adt_field(adt_def, ident, &mut *nested_fields) {
return true;
}
nested_fields.pop();
} else if field.ident(self.tcx).normalize_to_macros_2_0() == ident {
// We found the field we wanted. // We found the field we wanted.
nested_fields.push((field_idx, field)); return Some((field_idx, field));
return true;
} }
} }
false None
} }
// Check field access expressions // Check field access expressions
@ -2425,34 +2408,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ty::new_error(self.tcx(), guar); return Ty::new_error(self.tcx(), guar);
} }
let mut field_path = SmallVec::new(); if let Some((idx, field)) = self.find_adt_field(*base_def, ident) {
if self.find_adt_field(*base_def, ident, &mut field_path) { self.write_field_index(expr.hir_id, idx);
let (first_idx, _) = field_path[0];
let (_, last_field) = field_path.last().unwrap();
// Save the index of all fields regardless of their visibility in case
// of error recovery.
let nested_fields = field_path[..]
.array_windows()
.map(|[(_, outer), (inner_idx, _)]| {
let outer_ty = self.field_ty(expr.span, outer, args);
(outer_ty, *inner_idx)
})
.collect();
self.write_field_index(expr.hir_id, first_idx, nested_fields);
let adjustments = self.adjust_steps(&autoderef); let adjustments = self.adjust_steps(&autoderef);
if last_field.vis.is_accessible_from(def_scope, self.tcx) { if field.vis.is_accessible_from(def_scope, self.tcx) {
self.apply_adjustments(base, adjustments); self.apply_adjustments(base, adjustments);
self.register_predicates(autoderef.into_obligations()); self.register_predicates(autoderef.into_obligations());
self.tcx.check_stability( self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
last_field.did, return self.field_ty(expr.span, field, args);
Some(expr.hir_id),
expr.span,
None,
);
return self.field_ty(expr.span, last_field, args);
} }
// The field is not accessible, fall through to error reporting. // The field is not accessible, fall through to error reporting.
@ -2467,11 +2432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.apply_adjustments(base, adjustments); self.apply_adjustments(base, adjustments);
self.register_predicates(autoderef.into_obligations()); self.register_predicates(autoderef.into_obligations());
self.write_field_index( self.write_field_index(expr.hir_id, FieldIdx::from_usize(index));
expr.hir_id,
FieldIdx::from_usize(index),
Vec::new(),
);
return field_ty; return field_ty;
} }
} }

View File

@ -165,16 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
pub(crate) fn write_field_index( pub(crate) fn write_field_index(&self, hir_id: HirId, index: FieldIdx) {
&self,
hir_id: HirId,
index: FieldIdx,
nested_fields: Vec<(Ty<'tcx>, FieldIdx)>,
) {
self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index);
if !nested_fields.is_empty() {
self.typeck_results.borrow_mut().nested_fields_mut().insert(hir_id, nested_fields);
}
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]

View File

@ -1513,8 +1513,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field_map field_map
.get(&ident) .get(&ident)
.map(|(i, f)| { .map(|(i, f)| {
// FIXME: handle nested fields self.write_field_index(field.hir_id, *i);
self.write_field_index(field.hir_id, *i, Vec::new());
self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); self.tcx.check_stability(f.did, Some(pat.hir_id), span, None);
self.field_ty(span, f, args) self.field_ty(span, f, args)
}) })

View File

@ -588,11 +588,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
{ {
self.typeck_results.field_indices_mut().insert(hir_id, index); self.typeck_results.field_indices_mut().insert(hir_id, index);
} }
if let Some(nested_fields) =
self.fcx.typeck_results.borrow_mut().nested_fields_mut().remove(hir_id)
{
self.typeck_results.nested_fields_mut().insert(hir_id, nested_fields);
}
} }
#[instrument(skip(self, span), level = "debug")] #[instrument(skip(self, span), level = "debug")]

View File

@ -1107,8 +1107,6 @@ impl<'a> CrateMetadataRef<'a> {
parent_did, parent_did,
None, None,
data.is_non_exhaustive, data.is_non_exhaustive,
// FIXME: unnamed fields in crate metadata is unimplemented yet.
false,
), ),
) )
} }
@ -1151,7 +1149,6 @@ impl<'a> CrateMetadataRef<'a> {
adt_kind, adt_kind,
variants.into_iter().map(|(_, variant)| variant).collect(), variants.into_iter().map(|(_, variant)| variant).collect(),
repr, repr,
false,
) )
} }

View File

@ -259,12 +259,8 @@ impl AdtDefData {
kind: AdtKind, kind: AdtKind,
variants: IndexVec<VariantIdx, VariantDef>, variants: IndexVec<VariantIdx, VariantDef>,
repr: ReprOptions, repr: ReprOptions,
is_anonymous: bool,
) -> Self { ) -> Self {
debug!( debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
"AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})",
did, kind, variants, repr, is_anonymous
);
let mut flags = AdtFlags::NO_ADT_FLAGS; let mut flags = AdtFlags::NO_ADT_FLAGS;
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
@ -297,9 +293,6 @@ impl AdtDefData {
if tcx.is_lang_item(did, LangItem::UnsafeCell) { if tcx.is_lang_item(did, LangItem::UnsafeCell) {
flags |= AdtFlags::IS_UNSAFE_CELL; flags |= AdtFlags::IS_UNSAFE_CELL;
} }
if is_anonymous {
flags |= AdtFlags::IS_ANONYMOUS;
}
AdtDefData { did, variants, flags, repr } AdtDefData { did, variants, flags, repr }
} }

View File

@ -1419,16 +1419,8 @@ impl<'tcx> TyCtxt<'tcx> {
kind: AdtKind, kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>, variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions, repr: ReprOptions,
is_anonymous: bool,
) -> ty::AdtDef<'tcx> { ) -> ty::AdtDef<'tcx> {
self.mk_adt_def_from_data(ty::AdtDefData::new( self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
self,
did,
kind,
variants,
repr,
is_anonymous,
))
} }
/// Allocates a read-only byte or string literal for `mir::interpret`. /// Allocates a read-only byte or string literal for `mir::interpret`.

View File

@ -1155,8 +1155,6 @@ bitflags::bitflags! {
const NO_VARIANT_FLAGS = 0; const NO_VARIANT_FLAGS = 0;
/// Indicates whether the field list of this variant is `#[non_exhaustive]`. /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
/// Indicates whether this variant has unnamed fields.
const HAS_UNNAMED_FIELDS = 1 << 1;
} }
} }
rustc_data_structures::external_bitflags_debug! { VariantFlags } rustc_data_structures::external_bitflags_debug! { VariantFlags }
@ -1209,12 +1207,11 @@ impl VariantDef {
parent_did: DefId, parent_did: DefId,
recover_tainted: Option<ErrorGuaranteed>, recover_tainted: Option<ErrorGuaranteed>,
is_field_list_non_exhaustive: bool, is_field_list_non_exhaustive: bool,
has_unnamed_fields: bool,
) -> Self { ) -> Self {
debug!( debug!(
"VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})", fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields, name, variant_did, ctor, discr, fields, adt_kind, parent_did,
); );
let mut flags = VariantFlags::NO_VARIANT_FLAGS; let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@ -1222,10 +1219,6 @@ impl VariantDef {
flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
} }
if has_unnamed_fields {
flags |= VariantFlags::HAS_UNNAMED_FIELDS;
}
VariantDef { VariantDef {
def_id: variant_did.unwrap_or(parent_did), def_id: variant_did.unwrap_or(parent_did),
ctor, ctor,
@ -1243,12 +1236,6 @@ impl VariantDef {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
} }
/// Does this variant contains unnamed fields
#[inline]
pub fn has_unnamed_fields(&self) -> bool {
self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS)
}
/// Computes the `Ident` of this variant by looking up the `Span` /// Computes the `Ident` of this variant by looking up the `Span`
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
@ -1434,11 +1421,6 @@ impl<'tcx> FieldDef {
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
} }
/// Returns whether the field is unnamed
pub fn is_unnamed(&self) -> bool {
self.name == rustc_span::symbol::kw::Underscore
}
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]

View File

@ -42,12 +42,6 @@ pub struct TypeckResults<'tcx> {
/// belongs, but it may not exist if it's a tuple field (`tuple.0`). /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
field_indices: ItemLocalMap<FieldIdx>, field_indices: ItemLocalMap<FieldIdx>,
/// Resolved types and indices for the nested fields' accesses of `obj.field` (expanded
/// to `obj._(1)._(2).field` in THIR). This map only stores the intermediate type
/// of `obj._(1)` and index of `_(1)._(2)`, and the type of `_(1)._(2)`, and the index of
/// `_(2).field`.
nested_fields: ItemLocalMap<Vec<(Ty<'tcx>, FieldIdx)>>,
/// Stores the types for various nodes in the AST. Note that this table /// Stores the types for various nodes in the AST. Note that this table
/// is not guaranteed to be populated outside inference. See /// is not guaranteed to be populated outside inference. See
/// typeck::check::fn_ctxt for details. /// typeck::check::fn_ctxt for details.
@ -225,7 +219,6 @@ impl<'tcx> TypeckResults<'tcx> {
hir_owner, hir_owner,
type_dependent_defs: Default::default(), type_dependent_defs: Default::default(),
field_indices: Default::default(), field_indices: Default::default(),
nested_fields: Default::default(),
user_provided_types: Default::default(), user_provided_types: Default::default(),
user_provided_sigs: Default::default(), user_provided_sigs: Default::default(),
node_types: Default::default(), node_types: Default::default(),
@ -299,18 +292,6 @@ impl<'tcx> TypeckResults<'tcx> {
self.field_indices().get(id).cloned() self.field_indices().get(id).cloned()
} }
pub fn nested_fields(&self) -> LocalTableInContext<'_, Vec<(Ty<'tcx>, FieldIdx)>> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.nested_fields }
}
pub fn nested_fields_mut(&mut self) -> LocalTableInContextMut<'_, Vec<(Ty<'tcx>, FieldIdx)>> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.nested_fields }
}
pub fn nested_field_tys_and_indices(&self, id: HirId) -> &[(Ty<'tcx>, FieldIdx)] {
self.nested_fields().get(id).map_or(&[], Vec::as_slice)
}
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
} }

View File

@ -807,21 +807,11 @@ impl<'tcx> Cx<'tcx> {
}); });
ExprKind::Loop { body } ExprKind::Loop { body }
} }
hir::ExprKind::Field(source, ..) => { hir::ExprKind::Field(source, ..) => ExprKind::Field {
let mut kind = ExprKind::Field { lhs: self.mirror_expr(source),
lhs: self.mirror_expr(source), variant_index: FIRST_VARIANT,
variant_index: FIRST_VARIANT, name: self.typeck_results.field_index(expr.hir_id),
name: self.typeck_results.field_index(expr.hir_id), },
};
let nested_field_tys_and_indices =
self.typeck_results.nested_field_tys_and_indices(expr.hir_id);
for &(ty, idx) in nested_field_tys_and_indices {
let expr = Expr { temp_lifetime, ty, span: source.span, kind };
let lhs = self.thir.exprs.push(expr);
kind = ExprKind::Field { lhs, variant_index: FIRST_VARIANT, name: idx };
}
kind
}
hir::ExprKind::Cast(source, cast_ty) => { hir::ExprKind::Cast(source, cast_ty) => {
// Check for a user-given type annotation on this `cast` // Check for a user-given type annotation on this `cast`
let user_provided_types = self.typeck_results.user_provided_types(); let user_provided_types = self.typeck_results.user_provided_types();

View File

@ -2009,9 +2009,7 @@ impl<'a> Parser<'a> {
/// for better diagnostics and suggestions. /// for better diagnostics and suggestions.
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err(true)?; let (ident, is_raw) = self.ident_or_err(true)?;
if ident.name == kw::Underscore { if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
self.psess.gated_spans.gate(sym::unnamed_fields, lo);
} else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
let snapshot = self.create_snapshot_for_diagnostic(); let snapshot = self.create_snapshot_for_diagnostic();
let err = if self.check_fn_front_matter(false, Case::Sensitive) { let err = if self.check_fn_front_matter(false, Case::Sensitive) {
let inherited_vis = let inherited_vis =

View File

@ -1,29 +0,0 @@
#[repr(C)]
struct Foo {
foo: u8,
_: union { //~ ERROR unnamed fields are not yet fully implemented [E0658]
//~^ ERROR unnamed fields are not yet fully implemented [E0658]
bar: u8,
baz: u16
}
}
#[repr(C)]
union Bar {
foobar: u8,
_: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658]
//~^ ERROR unnamed fields are not yet fully implemented [E0658]
foobaz: u8,
barbaz: u16
}
}
#[repr(C)]
struct S;
#[repr(C)]
struct Baz {
_: S //~ ERROR unnamed fields are not yet fully implemented [E0658]
}
fn main(){}

View File

@ -1,63 +0,0 @@
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/feature-gate-unnamed_fields.rs:4:5
|
LL | _: union {
| ^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/feature-gate-unnamed_fields.rs:4:8
|
LL | _: union {
| ________^
LL | |
LL | | bar: u8,
LL | | baz: u16
LL | | }
| |_____^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/feature-gate-unnamed_fields.rs:14:5
|
LL | _: struct {
| ^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/feature-gate-unnamed_fields.rs:14:8
|
LL | _: struct {
| ________^
LL | |
LL | | foobaz: u8,
LL | | barbaz: u16
LL | | }
| |_____^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/feature-gate-unnamed_fields.rs:26:5
|
LL | _: S
| ^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,11 +0,0 @@
#![crate_type = "lib"]
#![feature(unnamed_fields)]
#![allow(unused, incomplete_features)]
enum K {
M {
_ : struct { field: u8 },
//~^ error: unnamed fields are not allowed outside of structs or unions
//~| error: anonymous structs are not allowed outside of unnamed struct or union fields
}
}

View File

@ -1,16 +0,0 @@
error: unnamed fields are not allowed outside of structs or unions
--> $DIR/anon-struct-in-enum-issue-121446.rs:7:9
|
LL | _ : struct { field: u8 },
| -^^^^^^^^^^^^^^^^^^^^^^^
| |
| unnamed field declared here
error: anonymous structs are not allowed outside of unnamed struct or union fields
--> $DIR/anon-struct-in-enum-issue-121446.rs:7:13
|
LL | _ : struct { field: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: aborting due to 2 previous errors

View File

@ -1,18 +0,0 @@
#[repr(C)]
pub struct GoodStruct(());
pub struct BadStruct(());
pub enum BadEnum {
A,
B,
}
#[repr(C)]
pub enum BadEnum2 {
A,
B,
}
pub type GoodAlias = GoodStruct;
pub type BadAlias = i32;

View File

@ -1,337 +0,0 @@
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
#[derive(Clone, Copy)]
#[repr(C)]
struct Foo {
a: u8,
}
#[derive(Clone, Copy)]
#[repr(C)]
struct Bar {
_: union {
a: u8,
},
}
// duplicated with a normal field
#[derive(Clone, Copy)]
#[repr(C)]
union A {
// referent field
a: u8,
// normal field
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a nested field
#[derive(Clone, Copy)]
#[repr(C)]
struct B {
_: union {
// referent field
a: u8,
// normal field (within the same anonymous adt)
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field (within the same anonymous adt)
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field (within the same anonymous adt)
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt (within the same anonymous adt)
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt (within the same anonymous adt)
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
},
// normal field
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a more nested field
#[derive(Clone, Copy)]
#[repr(C)]
union C {
_: struct {
_: union {
// referent field
a: u8,
// normal field (within the same anonymous adt)
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field (within the same anonymous adt)
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field (within the same anonymous adt)
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt (within the same anonymous adt)
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt (within the same anonymous adt)
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
},
// normal field (within the direct outer anonymous adt)
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field (within the direct outer anonymous adt)
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field (within the direct outer anonymous adt)
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt (within the direct outer anonymous adt)
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt (within the direct outer anonymous adt)
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
},
// normal field
a: u8, //~ ERROR field `a` is already declared [E0124]
// nested field
_: union {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
// more nested field
_: struct {
_: union {
a: u8, //~ ERROR field `a` is already declared [E0124]
},
},
// nested field in a named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: union {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a nested field in a named adt
#[derive(Clone, Copy)]
#[repr(C)]
struct D {
// referent field `a`
_: Foo,
// normal field
a: u8, //~ ERROR field `a` is already declared
// nested field
_: union {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field
_: struct {
_: union {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in another named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: union {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a nested field in a nested field of a named adt
#[derive(Clone, Copy)]
#[repr(C)]
union D2 {
// referent field `a`
_: Bar,
// normal field
a: u8, //~ ERROR field `a` is already declared
// nested field
_: union {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field
_: struct {
_: union {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in another named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: union {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a nested field in a named adt in an anonymous adt
#[derive(Clone, Copy)]
#[repr(C)]
struct E {
_: struct {
// referent field `a`
_: Foo,
// normal field (within the same anonymous adt)
a: u8, //~ ERROR field `a` is already declared
// nested field (within the same anonymous adt)
_: struct {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field (within the same anonymous adt)
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in a named adt (within the same anonymous adt)
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt (within the same anonymous adt)
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
},
// normal field
a: u8, //~ ERROR field `a` is already declared
// nested field
_: union {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field
_: struct {
_: union {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in another named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: union {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
// duplicated with a nested field in a named adt in an anonymous adt
#[repr(C)]
#[derive(Clone, Copy)]
union E2 {
_: struct {
// referent field `a`
_: Bar,
// normal field (within the same anonymous adt)
a: u8, //~ ERROR field `a` is already declared
// nested field (within the same anonymous adt)
_: struct {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field (within the same anonymous adt)
_: union {
_: struct {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in a named adt (within the same anonymous adt)
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt (within the same anonymous adt)
_: struct {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
},
// normal field
a: u8, //~ ERROR field `a` is already declared
// nested field
_: union {
a: u8, //~ ERROR field `a` is already declared
},
// more nested field
_: struct {
_: union {
a: u8, //~ ERROR field `a` is already declared
},
},
// nested field in another named adt
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
// nested field in a named adt in an anoymous adt
_: union {
_: Foo, //~ ERROR field `a` is already declared
_: Bar, //~ ERROR field `a` is already declared
},
}
fn main() {}

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +0,0 @@
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
struct A { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation
//~^ NOTE struct `A` defined here
_: struct { //~ NOTE unnamed field defined here
a: i32,
},
_: struct { //~ NOTE unnamed field defined here
_: struct {
b: i32,
},
},
}
union B { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation
//~^ NOTE union `B` defined here
_: union { //~ NOTE unnamed field defined here
a: i32,
},
_: union { //~ NOTE unnamed field defined here
_: union {
b: i32,
},
},
}
#[derive(Clone, Copy)]
#[repr(C)]
struct Foo {}
#[derive(Clone, Copy)]
struct Bar {}
//~^ `Bar` defined here
//~| `Bar` defined here
//~| `Bar` defined here
//~| `Bar` defined here
struct C { //~ ERROR struct with unnamed fields must have `#[repr(C)]` representation
//~^ NOTE struct `C` defined here
_: Foo, //~ NOTE unnamed field defined here
}
union D { //~ ERROR union with unnamed fields must have `#[repr(C)]` representation
//~^ NOTE union `D` defined here
_: Foo, //~ NOTE unnamed field defined here
}
#[repr(C)]
struct E {
_: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation
//~^ NOTE unnamed field defined here
_: struct {
_: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation
//~^ NOTE unnamed field defined here
},
}
#[repr(C)]
union F {
_: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation
//~^ NOTE unnamed field defined here
_: union {
_: Bar, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation
//~^ NOTE unnamed field defined here
},
}
fn main() {}

View File

@ -1,152 +0,0 @@
error: struct with unnamed fields must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:4:1
|
LL | struct A {
| ^^^^^^^^ struct `A` defined here
|
note: unnamed field defined here
--> $DIR/repr_check.rs:6:5
|
LL | / _: struct {
LL | | a: i32,
LL | | },
| |_____^
note: unnamed field defined here
--> $DIR/repr_check.rs:9:5
|
LL | / _: struct {
LL | | _: struct {
LL | | b: i32,
LL | | },
LL | | },
| |_____^
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct A {
|
error: union with unnamed fields must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:16:1
|
LL | union B {
| ^^^^^^^ union `B` defined here
|
note: unnamed field defined here
--> $DIR/repr_check.rs:18:5
|
LL | / _: union {
LL | | a: i32,
LL | | },
| |_____^
note: unnamed field defined here
--> $DIR/repr_check.rs:21:5
|
LL | / _: union {
LL | | _: union {
LL | | b: i32,
LL | | },
LL | | },
| |_____^
help: add `#[repr(C)]` to this union
|
LL + #[repr(C)]
LL | union B {
|
error: struct with unnamed fields must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:39:1
|
LL | struct C {
| ^^^^^^^^ struct `C` defined here
|
note: unnamed field defined here
--> $DIR/repr_check.rs:41:5
|
LL | _: Foo,
| ^^^^^^
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct C {
|
error: union with unnamed fields must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:44:1
|
LL | union D {
| ^^^^^^^ union `D` defined here
|
note: unnamed field defined here
--> $DIR/repr_check.rs:46:5
|
LL | _: Foo,
| ^^^^^^
help: add `#[repr(C)]` to this union
|
LL + #[repr(C)]
LL | union D {
|
error: named type of unnamed field must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:51:5
|
LL | struct Bar {}
| ---------- `Bar` defined here
...
LL | _: Bar,
| ^^^^^^ unnamed field defined here
|
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct Bar {}
|
error: named type of unnamed field must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:54:9
|
LL | struct Bar {}
| ---------- `Bar` defined here
...
LL | _: Bar,
| ^^^^^^ unnamed field defined here
|
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct Bar {}
|
error: named type of unnamed field must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:61:5
|
LL | struct Bar {}
| ---------- `Bar` defined here
...
LL | _: Bar,
| ^^^^^^ unnamed field defined here
|
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct Bar {}
|
error: named type of unnamed field must have `#[repr(C)]` representation
--> $DIR/repr_check.rs:64:9
|
LL | struct Bar {}
| ---------- `Bar` defined here
...
LL | _: Bar,
| ^^^^^^ unnamed field defined here
|
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct Bar {}
|
error: aborting due to 8 previous errors

View File

@ -1,32 +0,0 @@
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
struct F {
field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
_: struct { field3: u8 },
}
struct G {
_: (u8, u8), //~ ERROR unnamed fields can only have struct or union types
}
union H {
field1: struct { field2: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
_: struct { field3: u8 },
}
union I {
_: (u8, u8), //~ ERROR unnamed fields can only have struct or union types
}
enum K {
M {
_ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
//~^ ERROR unnamed fields are not allowed outside of structs or unions
},
N {
_ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions
}
}
fn main() {}

View File

@ -1,48 +0,0 @@
error: anonymous structs are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_structs.rs:5:13
|
LL | field1: struct { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_structs.rs:10:5
|
LL | _: (u8, u8),
| ^ -------- not a struct or union
error: anonymous structs are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_structs.rs:14:13
|
LL | field1: struct { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_structs.rs:19:5
|
LL | _: (u8, u8),
| ^ -------- not a struct or union
error: unnamed fields are not allowed outside of structs or unions
--> $DIR/restrict_anonymous_structs.rs:24:9
|
LL | _ : struct { field: u8 },
| -^^^^^^^^^^^^^^^^^^^^^^^
| |
| unnamed field declared here
error: anonymous structs are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_structs.rs:24:13
|
LL | _ : struct { field: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
error: unnamed fields are not allowed outside of structs or unions
--> $DIR/restrict_anonymous_structs.rs:28:9
|
LL | _ : u8,
| -^^^^^
| |
| unnamed field declared here
error: aborting due to 7 previous errors

View File

@ -1,32 +0,0 @@
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
struct F {
field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
_: union { field3: u8 },
}
struct G {
_: (u8, u8), //~ ERROR unnamed fields can only have struct or union types
}
union H {
field1: union { field2: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
_: union { field3: u8 },
}
union I {
_: (u8, u8), //~ ERROR unnamed fields can only have struct or union types
}
enum K {
M {
_ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
//~^ ERROR unnamed fields are not allowed outside of structs or unions
},
N {
_ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions
}
}
fn main() {}

View File

@ -1,48 +0,0 @@
error: anonymous unions are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_unions.rs:5:13
|
LL | field1: union { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_unions.rs:10:5
|
LL | _: (u8, u8),
| ^ -------- not a struct or union
error: anonymous unions are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_unions.rs:14:13
|
LL | field1: union { field2: u8 },
| ^^^^^^^^^^^^^^^^^^^^ anonymous union declared here
error: unnamed fields can only have struct or union types
--> $DIR/restrict_anonymous_unions.rs:19:5
|
LL | _: (u8, u8),
| ^ -------- not a struct or union
error: unnamed fields are not allowed outside of structs or unions
--> $DIR/restrict_anonymous_unions.rs:24:9
|
LL | _ : union { field: u8 },
| -^^^^^^^^^^^^^^^^^^^^^^
| |
| unnamed field declared here
error: anonymous unions are not allowed outside of unnamed struct or union fields
--> $DIR/restrict_anonymous_unions.rs:24:13
|
LL | _ : union { field: u8 },
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
error: unnamed fields are not allowed outside of structs or unions
--> $DIR/restrict_anonymous_unions.rs:28:9
|
LL | _ : u8,
| -^^^^^
| |
| unnamed field declared here
error: aborting due to 7 previous errors

View File

@ -1,44 +0,0 @@
//@ aux-build:dep.rs
// test for #121151
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
extern crate dep;
#[repr(C)]
struct A {
a: u8,
}
enum BadEnum {
A,
B,
}
#[repr(C)]
enum BadEnum2 {
A,
B,
}
type MyStruct = A;
type MyI32 = i32;
#[repr(C)]
struct L {
_: i32, //~ ERROR unnamed fields can only have struct or union types
_: MyI32, //~ ERROR unnamed fields can only have struct or union types
_: BadEnum, //~ ERROR unnamed fields can only have struct or union types
_: BadEnum2, //~ ERROR unnamed fields can only have struct or union types
_: MyStruct,
_: dep::BadStruct, //~ ERROR named type of unnamed field must have `#[repr(C)]` representation
_: dep::BadEnum, //~ ERROR unnamed fields can only have struct or union types
_: dep::BadEnum2, //~ ERROR unnamed fields can only have struct or union types
_: dep::BadAlias, //~ ERROR unnamed fields can only have struct or union types
_: dep::GoodAlias,
_: dep::GoodStruct,
}
fn main() {}

View File

@ -1,62 +0,0 @@
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:31:5
|
LL | _: i32,
| ^^^^^^
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:32:5
|
LL | _: MyI32,
| ^^^^^^^^
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:33:5
|
LL | _: BadEnum,
| ^^^^^^^^^^
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:34:5
|
LL | _: BadEnum2,
| ^^^^^^^^^^^
error: named type of unnamed field must have `#[repr(C)]` representation
--> $DIR/restrict_type_hir.rs:36:5
|
LL | _: dep::BadStruct,
| ^^^^^^^^^^^^^^^^^ unnamed field defined here
|
::: $DIR/auxiliary/dep.rs:4:1
|
LL | pub struct BadStruct(());
| -------------------- `BadStruct` defined here
|
help: add `#[repr(C)]` to this struct
--> $DIR/auxiliary/dep.rs:4:1
|
LL + #[repr(C)]
LL | pub struct BadStruct(());
|
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:37:5
|
LL | _: dep::BadEnum,
| ^^^^^^^^^^^^^^^
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:38:5
|
LL | _: dep::BadEnum2,
| ^^^^^^^^^^^^^^^^
error: unnamed fields can only have struct or union types
--> $DIR/restrict_type_hir.rs:39:5
|
LL | _: dep::BadAlias,
| ^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors

View File

@ -1,25 +0,0 @@
type NodeId = u32;
struct Type<'a>(std::marker::PhantomData::<&'a ()>);
type Ast<'ast> = &'ast AstStructure<'ast>;
struct AstStructure<'ast> {
//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation
id: NodeId,
_: AstKind<'ast>
//~^ ERROR unnamed fields are not yet fully implemented [E0658]
//~^^ ERROR unnamed fields can only have struct or union types
}
enum AstKind<'ast> {
ExprInt,
ExprLambda(Ast<'ast>),
}
fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx>
{
match ast.kind {}
//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609]
}
fn main() {}

View File

@ -1,45 +0,0 @@
error[E0658]: unnamed fields are not yet fully implemented
--> $DIR/unnamed-enum-field-issue-121757.rs:9:5
|
LL | _: AstKind<'ast>
| ^
|
= note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: struct with unnamed fields must have `#[repr(C)]` representation
--> $DIR/unnamed-enum-field-issue-121757.rs:6:1
|
LL | struct AstStructure<'ast> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here
|
note: unnamed field defined here
--> $DIR/unnamed-enum-field-issue-121757.rs:9:5
|
LL | _: AstKind<'ast>
| ^^^^^^^^^^^^^^^^
help: add `#[repr(C)]` to this struct
|
LL + #[repr(C)]
LL | struct AstStructure<'ast> {
|
error: unnamed fields can only have struct or union types
--> $DIR/unnamed-enum-field-issue-121757.rs:9:5
|
LL | _: AstKind<'ast>
| ^^^^^^^^^^^^^^^^
error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>`
--> $DIR/unnamed-enum-field-issue-121757.rs:21:15
|
LL | match ast.kind {}
| ^^^^ unknown field
|
= note: available fields are: `id`, `_`
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0609, E0658.
For more information about an error, try `rustc --explain E0609`.

View File

@ -786,20 +786,6 @@ mod types {
let _: (T, T); let _: (T, T);
} }
/// TyKind::AnonStruct
fn ty_anon_struct() {
struct Struct {
_: struct { t: T },
}
}
/// TyKind::AnonUnion
fn ty_anon_union() {
struct Struct {
_: union { t: T },
}
}
/// TyKind::Path /// TyKind::Path
fn ty_path() { fn ty_path() {
let _: T; let _: T;

View File

@ -361,8 +361,6 @@ mod expressions {
@ -636,22 +634,6 @@ mod types {
fn ty_never() { let _: !; } fn ty_never() { let _: !; }
/// TyKind::Tup /// TyKind::Tup
fn ty_tup() { let _: (); let _: (T,); let _: (T, T); } fn ty_tup() { let _: (); let _: (T,); let _: (T, T); }
/// TyKind::AnonStruct
fn ty_anon_struct() {
struct Struct {
_: struct {
t: T,
},
}
}
/// TyKind::AnonUnion
fn ty_anon_union() {
struct Struct {
_: union {
t: T,
},
}
}
/// TyKind::Path /// TyKind::Path
fn ty_path() { fn ty_path() {
let _: T; let _: T;