Auto merge of #131045 - compiler-errors:remove-unnamed_fields, r=wesleywiser

Retire the `unnamed_fields` feature for now

`#![feature(unnamed_fields)]` was implemented in part in #115131 and #115367, however work on that feature has (afaict) stalled and in the mean time there have been some concerns raised (e.g.[^1][^2]) about whether `unnamed_fields` is worthwhile to have in the language, especially in its current desugaring. Because it represents a compiler implementation burden including a new kind of anonymous ADT and additional complication to field selection, and is quite prone to bugs today, I'm choosing to remove the feature.

However, since I'm not one to really write a bunch of words, I'm specifically *not* going to de-RFC this feature. This PR essentially *rolls back* the state of this feature to "RFC accepted but not yet implemented"; however if anyone wants to formally unapprove the RFC from the t-lang side, then please be my guest. I'm just not totally willing to summarize the various language-facing reasons for why this feature is or is not worthwhile, since I'm coming from the compiler side mostly.

Fixes #117942
Fixes #121161
Fixes #121263
Fixes #121299
Fixes #121722
Fixes #121799
Fixes #126969
Fixes #131041

Tracking:
* https://github.com/rust-lang/rust/issues/49804

[^1]: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Unnamed.20struct.2Funion.20fields
[^2]: https://github.com/rust-lang/rust/issues/49804#issuecomment-1972619108
This commit is contained in:
bors 2024-10-11 13:11:13 +00:00
commit f4966590d8
66 changed files with 32 additions and 3708 deletions

View File

@ -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`.
///
@ -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.

View File

@ -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);

View File

@ -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,
}
}
}

View File

@ -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()
}

View File

@ -1259,46 +1259,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) => {

View File

@ -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
@ -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

View File

@ -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),
}
}
@ -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);
@ -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;
@ -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;

View File

@ -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 {

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!(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");

View File

@ -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);

View File

@ -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,

View File

@ -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)]);

View File

@ -220,6 +220,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),

View File

@ -623,8 +623,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)),

View File

@ -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
@ -538,19 +536,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

View File

@ -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) {
@ -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.

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(
@ -1090,20 +1017,13 @@ fn lower_variant(
def: &hir::VariantData<'_>,
adt_kind: ty::AdtKind,
parent_did: LocalDefId,
is_anonymous: bool,
) -> ty::VariantDef {
let mut has_unnamed_fields = false;
let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
let fields = def
.fields()
.iter()
.inspect(|f| {
has_unnamed_fields |= f.ident.name == kw::Underscore;
// 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);
}
.inspect(|field| {
field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
})
.map(|f| ty::FieldDef {
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)
|| variant_did
.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");
};
let is_anonymous = item.ident.name == kw::Empty;
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 repr = tcx.repr_options_of_def(def_id);
let (kind, variants) = match &item.kind {
ItemKind::Enum(def, _) => {
let mut distance_from_explicit = 0;
@ -1175,7 +1081,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
&v.data,
AdtKind::Enum,
def_id,
is_anonymous,
)
})
.collect();
@ -1195,7 +1100,6 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
def,
adt_kind,
def_id,
is_anonymous,
))
.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),
};
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 {

View File

@ -734,13 +734,6 @@ pub(crate) struct InvalidUnionField {
pub note: (),
}
#[derive(Diagnostic)]
#[diag(hir_analysis_invalid_unnamed_field_ty)]
pub(crate) struct InvalidUnnamedFieldTy {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
@ -1598,41 +1591,6 @@ pub(crate) struct UnconstrainedGenericParameter {
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)]
#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)]
pub(crate) struct OpaqueCapturesHigherRankedLifetime {

View File

@ -36,7 +36,6 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_target::abi::{FIRST_VARIANT, FieldIdx};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use smallvec::SmallVec;
use tracing::{debug, instrument, trace};
use {rustc_ast as ast, rustc_hir as hir};
@ -1907,8 +1906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
// FIXME: handle nested fields
self.write_field_index(field.hir_id, i, Vec::new());
self.write_field_index(field.hir_id, i);
// We don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not
@ -2552,35 +2550,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
base_def: ty::AdtDef<'tcx>,
ident: Ident,
nested_fields: &mut SmallVec<[(FieldIdx, &'tcx ty::FieldDef); 1]>,
) -> bool {
) -> Option<(FieldIdx, &'tcx ty::FieldDef)> {
// No way to find a field in an enum.
if base_def.is_enum() {
return false;
return None;
}
for (field_idx, field) in base_def.non_enum_variant().fields.iter_enumerated() {
if field.is_unnamed() {
// 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 {
if field.ident(self.tcx).normalize_to_macros_2_0() == ident {
// We found the field we wanted.
nested_fields.push((field_idx, field));
return true;
return Some((field_idx, field));
}
}
false
None
}
// Check field access expressions
@ -2610,34 +2593,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ty::new_error(self.tcx(), guar);
}
let mut field_path = SmallVec::new();
if self.find_adt_field(*base_def, ident, &mut field_path) {
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);
if let Some((idx, field)) = self.find_adt_field(*base_def, ident) {
self.write_field_index(expr.hir_id, idx);
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.register_predicates(autoderef.into_obligations());
self.tcx.check_stability(
last_field.did,
Some(expr.hir_id),
expr.span,
None,
);
return self.field_ty(expr.span, last_field, args);
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
return self.field_ty(expr.span, field, args);
}
// The field is not accessible, fall through to error reporting.
@ -2652,11 +2617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.apply_adjustments(base, adjustments);
self.register_predicates(autoderef.into_obligations());
self.write_field_index(
expr.hir_id,
FieldIdx::from_usize(index),
Vec::new(),
);
self.write_field_index(expr.hir_id, FieldIdx::from_usize(index));
return field_ty;
}
}

View File

@ -165,16 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
pub(crate) fn write_field_index(
&self,
hir_id: HirId,
index: FieldIdx,
nested_fields: Vec<(Ty<'tcx>, FieldIdx)>,
) {
pub(crate) fn write_field_index(&self, hir_id: HirId, index: FieldIdx) {
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))]

View File

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

View File

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

View File

@ -259,12 +259,8 @@ impl AdtDefData {
kind: AdtKind,
variants: IndexVec<VariantIdx, VariantDef>,
repr: ReprOptions,
is_anonymous: bool,
) -> Self {
debug!(
"AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})",
did, kind, variants, repr, is_anonymous
);
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
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) {
flags |= AdtFlags::IS_UNSAFE_CELL;
}
if is_anonymous {
flags |= AdtFlags::IS_ANONYMOUS;
}
AdtDefData { did, variants, flags, repr }
}

View File

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

View File

@ -1155,8 +1155,6 @@ bitflags::bitflags! {
const NO_VARIANT_FLAGS = 0;
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
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 }
@ -1209,12 +1207,11 @@ impl VariantDef {
parent_did: DefId,
recover_tainted: Option<ErrorGuaranteed>,
is_field_list_non_exhaustive: bool,
has_unnamed_fields: bool,
) -> Self {
debug!(
"VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})",
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,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@ -1222,10 +1219,6 @@ impl VariantDef {
flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
}
if has_unnamed_fields {
flags |= VariantFlags::HAS_UNNAMED_FIELDS;
}
VariantDef {
def_id: variant_did.unwrap_or(parent_did),
ctor,
@ -1243,12 +1236,6 @@ impl VariantDef {
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`
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
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 {
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)]

View File

@ -42,12 +42,6 @@ pub struct TypeckResults<'tcx> {
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
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
/// is not guaranteed to be populated outside inference. See
/// typeck::check::fn_ctxt for details.
@ -225,7 +219,6 @@ impl<'tcx> TypeckResults<'tcx> {
hir_owner,
type_dependent_defs: Default::default(),
field_indices: Default::default(),
nested_fields: Default::default(),
user_provided_types: Default::default(),
user_provided_sigs: Default::default(),
node_types: Default::default(),
@ -299,18 +292,6 @@ impl<'tcx> TypeckResults<'tcx> {
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>> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
}

View File

@ -808,21 +808,11 @@ impl<'tcx> Cx<'tcx> {
});
ExprKind::Loop { body }
}
hir::ExprKind::Field(source, ..) => {
let mut kind = ExprKind::Field {
hir::ExprKind::Field(source, ..) => ExprKind::Field {
lhs: self.mirror_expr(source),
variant_index: FIRST_VARIANT,
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) => {
// Check for a user-given type annotation on this `cast`
let user_provided_types = self.typeck_results.user_provided_types();

View File

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

View File

@ -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.
@ -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.
@ -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()

View File

@ -582,8 +582,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
BareFn,
Never,
Tup,
AnonStruct,
AnonUnion,
Path,
Pat,
TraitObject,

View File

@ -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.

View File

@ -105,22 +105,6 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
let def = self.create_def(field.id, name, DefKind::Field, field.span);
self.with_parent(def, |this| visit::walk_field_def(this, field));
self.visit_anon_adt(&field.ty);
}
}
fn visit_anon_adt(&mut self, ty: &'a Ty) {
let def_kind = match &ty.kind {
TyKind::AnonStruct(..) => DefKind::Struct,
TyKind::AnonUnion(..) => DefKind::Union,
_ => return,
};
match &ty.kind {
TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => {
let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span);
self.with_parent(def_id, |this| visit::walk_ty(this, ty));
}
_ => {}
}
}
@ -476,8 +460,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
fn visit_ty(&mut self, ty: &'a Ty) {
match &ty.kind {
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
// Anonymous structs or unions are visited later after defined.
TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
TyKind::ImplTrait(id, _) => {
// HACK: pprust breaks strings with newlines when the type
// gets too long. We don't want these to show up in compiler

View File

@ -1,10 +0,0 @@
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
#[repr(C)]
struct Foo {
_: struct {
},
}
fn main() {}

View File

@ -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)
}

View File

@ -1,31 +0,0 @@
// Test for issue 85480
// Pretty print anonymous struct and union types
// pp-exact
// pretty-compare-only
struct Foo {
_: union {
_: struct {
a: u8,
b: u16,
},
c: u32,
},
d: u64,
e: f32,
}
// Test for https://github.com/rust-lang/rust/issues/117942
struct Foo {
_: union {
#[rustfmt::skip]
f: String,
},
#[rustfmt::skip]
_: struct {
g: i32,
},
}
fn main() {}

View File

@ -1,7 +0,0 @@
//@ known-bug: #117942
struct Foo {
_: union {
#[rustfmt::skip]
f: String
},
}

View File

@ -1,12 +0,0 @@
//@ known-bug: #121161
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
#[derive(Eq)]
#[repr(C)]
struct Bar {
_: union {
a: u8,
},
}

View File

@ -1,6 +0,0 @@
//@ known-bug: #121263
#[repr(C)]
#[derive(Debug)]
struct L {
_: MyI32,
}

View File

@ -1,9 +0,0 @@
//@ known-bug: #121263
#[repr(C)]
#[repr(C)]
#[derive(Debug)]
struct L {
_: i32,
_: MyI32,
_: BadEnum,
}

View File

@ -1,6 +0,0 @@
//@ known-bug: #121299
#[derive(Eq)]
struct D {
_: union {
},
}

View File

@ -1,10 +0,0 @@
//@ known-bug: #121722
#[repr(C)]
struct Foo {
_: u8,
}
#[repr(C)]
struct D {
_: Foo,
}

View File

@ -1,11 +0,0 @@
//@ known-bug: #121799
struct S {
_: str
}
fn func(a: S)
{
let _x = a.f;
}
fn main() {}

View File

@ -1,9 +0,0 @@
//@ known-bug: rust-lang/rust#126969
struct S<T> {
_: union { t: T },
}
fn f(S::<&i8> { .. }: S<&i8>) {}
fn main() {}

View File

@ -1,59 +0,0 @@
// MIR for `bar` after SimplifyCfg-initial
fn bar(_1: Bar) -> () {
debug bar => _1;
let mut _0: ();
let _2: ();
let mut _3: u8;
let _4: ();
let mut _5: i8;
let _6: ();
let mut _7: bool;
let _8: ();
let mut _9: [u8; 1];
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = copy (_1.0: u8);
_2 = access::<u8>(move _3) -> [return: bb1, unwind: bb5];
}
bb1: {
StorageDead(_3);
StorageDead(_2);
StorageLive(_4);
StorageLive(_5);
_5 = copy ((_1.1: Bar::{anon_adt#0}).0: i8);
_4 = access::<i8>(move _5) -> [return: bb2, unwind: bb5];
}
bb2: {
StorageDead(_5);
StorageDead(_4);
StorageLive(_6);
StorageLive(_7);
_7 = copy ((_1.1: Bar::{anon_adt#0}).1: bool);
_6 = access::<bool>(move _7) -> [return: bb3, unwind: bb5];
}
bb3: {
StorageDead(_7);
StorageDead(_6);
StorageLive(_8);
StorageLive(_9);
_9 = copy (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]);
_8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5];
}
bb4: {
StorageDead(_9);
StorageDead(_8);
_0 = const ();
return;
}
bb5 (cleanup): {
resume;
}
}

View File

@ -1,59 +0,0 @@
// MIR for `foo` after SimplifyCfg-initial
fn foo(_1: Foo) -> () {
debug foo => _1;
let mut _0: ();
let _2: ();
let mut _3: u8;
let _4: ();
let mut _5: i8;
let _6: ();
let mut _7: bool;
let _8: ();
let mut _9: [u8; 1];
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = copy (_1.0: u8);
_2 = access::<u8>(move _3) -> [return: bb1, unwind: bb5];
}
bb1: {
StorageDead(_3);
StorageDead(_2);
StorageLive(_4);
StorageLive(_5);
_5 = copy ((_1.1: Foo::{anon_adt#0}).0: i8);
_4 = access::<i8>(move _5) -> [return: bb2, unwind: bb5];
}
bb2: {
StorageDead(_5);
StorageDead(_4);
StorageLive(_6);
StorageLive(_7);
_7 = copy ((_1.1: Foo::{anon_adt#0}).1: bool);
_6 = access::<bool>(move _7) -> [return: bb3, unwind: bb5];
}
bb3: {
StorageDead(_7);
StorageDead(_6);
StorageLive(_8);
StorageLive(_9);
_9 = copy (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]);
_8 = access::<[u8; 1]>(move _9) -> [return: bb4, unwind: bb5];
}
bb4: {
StorageDead(_9);
StorageDead(_8);
_0 = const ();
return;
}
bb5 (cleanup): {
resume;
}
}

View File

@ -1,73 +0,0 @@
// Tests the correct handling of unnamed fields within structs and unions marked with #[repr(C)].
// EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir
// EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir
#![allow(incomplete_features)]
#![feature(unnamed_fields)]
#[repr(C)]
struct Foo {
a: u8,
_: struct {
b: i8,
c: bool,
},
_: struct {
_: struct {
d: [u8; 1],
}
},
}
#[repr(C)]
union Bar {
a: u8,
_: union {
b: i8,
c: bool,
},
_: union {
_: union {
d: [u8; 1],
}
},
}
fn access<T>(_: T) {}
// CHECK-LABEL: fn foo(
fn foo(foo: Foo) {
// CHECK [[a:_.*]] = (_1.0: u8);
// CHECK _.* = access::<u8>(move [[a]]) -> [return: bb1, unwind: bb5];
access(foo.a);
// CHECK [[b:_.*]] = ((_1.1: Foo::{anon_adt#0}).0: i8);
// CHECK _.* = access::<i8>(move [[b]]) -> [return: bb2, unwind: bb5];
access(foo.b);
// CHECK [[c:_.*]] = ((_1.1: Foo::{anon_adt#0}).1: bool);
// CHECK _.* = access::<bool>(move [[c]]) -> [return: bb3, unwind: bb5];
access(foo.c);
// CHECK [[d:_.*]] = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]);
// CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5];
access(foo.d);
}
// CHECK-LABEL: fn bar(
fn bar(bar: Bar) {
unsafe {
// CHECK [[a:_.*]] = (_1.0: u8);
// CHECK _.* = access::<u8>(move [[a]]) -> [return: bb1, unwind: bb5];
access(bar.a);
// CHECK [[b:_.*]] = ((_1.1: Bar::{anon_adt#0}).0: i8);
// CHECK _.* = access::<i8>(move [[b]]) -> [return: bb2, unwind: bb5];
access(bar.b);
// CHECK [[c:_.*]] = ((_1.1: Bar::{anon_adt#0}).1: bool);
// CHECK _.* = access::<bool>(move [[c]]) -> [return: bb3, unwind: bb5];
access(bar.c);
// CHECK [[d:_.*]] = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]);
// CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5];
access(bar.d);
}
}
fn main() {}

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

@ -23,7 +23,6 @@
#![feature(trace_macros)]
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(unnamed_fields)]
#![feature(yeet_expr)]
#![allow(incomplete_features)]
@ -786,20 +785,6 @@ mod types {
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
fn ty_path() {
let _: T;

View File

@ -24,7 +24,6 @@
#![feature(trace_macros)]
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(unnamed_fields)]
#![feature(yeet_expr)]
#![allow(incomplete_features)]
#[prelude_import]
@ -361,8 +360,6 @@ mod expressions {
@ -636,22 +633,6 @@ mod types {
fn ty_never() { let _: !; }
/// TyKind::Tup
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
fn ty_path() {
let _: T;