mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
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:
commit
f4966590d8
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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)]);
|
||||
|
@ -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),
|
||||
|
@ -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)),
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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))]
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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")]
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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)]
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -808,21 +808,11 @@ impl<'tcx> Cx<'tcx> {
|
||||
});
|
||||
ExprKind::Loop { body }
|
||||
}
|
||||
hir::ExprKind::Field(source, ..) => {
|
||||
let mut kind = 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::Field(source, ..) => ExprKind::Field {
|
||||
lhs: self.mirror_expr(source),
|
||||
variant_index: FIRST_VARIANT,
|
||||
name: self.typeck_results.field_index(expr.hir_id),
|
||||
},
|
||||
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();
|
||||
|
@ -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 =
|
||||
|
@ -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()
|
||||
|
@ -582,8 +582,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
||||
BareFn,
|
||||
Never,
|
||||
Tup,
|
||||
AnonStruct,
|
||||
AnonUnion,
|
||||
Path,
|
||||
Pat,
|
||||
TraitObject,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -1,10 +0,0 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(unnamed_fields)]
|
||||
|
||||
#[repr(C)]
|
||||
struct Foo {
|
||||
_: struct {
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -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)
|
||||
}
|
||||
|
@ -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() {}
|
@ -1,7 +0,0 @@
|
||||
//@ known-bug: #117942
|
||||
struct Foo {
|
||||
_: union {
|
||||
#[rustfmt::skip]
|
||||
f: String
|
||||
},
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
//@ known-bug: #121161
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(unnamed_fields)]
|
||||
|
||||
|
||||
#[derive(Eq)]
|
||||
#[repr(C)]
|
||||
struct Bar {
|
||||
_: union {
|
||||
a: u8,
|
||||
},
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
//@ known-bug: #121263
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct L {
|
||||
_: MyI32,
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
//@ known-bug: #121263
|
||||
#[repr(C)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct L {
|
||||
_: i32,
|
||||
_: MyI32,
|
||||
_: BadEnum,
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
//@ known-bug: #121299
|
||||
#[derive(Eq)]
|
||||
struct D {
|
||||
_: union {
|
||||
},
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
//@ known-bug: #121722
|
||||
#[repr(C)]
|
||||
struct Foo {
|
||||
_: u8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct D {
|
||||
_: Foo,
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
//@ known-bug: #121799
|
||||
struct S {
|
||||
_: str
|
||||
}
|
||||
|
||||
fn func(a: S)
|
||||
{
|
||||
let _x = a.f;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,9 +0,0 @@
|
||||
//@ known-bug: rust-lang/rust#126969
|
||||
|
||||
struct S<T> {
|
||||
_: union { t: T },
|
||||
}
|
||||
|
||||
fn f(S::<&i8> { .. }: S<&i8>) {}
|
||||
|
||||
fn main() {}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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() {}
|
@ -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(){}
|
@ -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`.
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
@ -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
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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`.
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user