From ea6c448c5f80e87bf282b026b9c40b8da418b241 Mon Sep 17 00:00:00 2001 From: Frank King Date: Wed, 23 Aug 2023 20:21:18 +0800 Subject: [PATCH] Disable the recovery of anonymous structs or unions --- .../rustc_ast_passes/src/ast_validation.rs | 6 - compiler/rustc_parse/src/parser/item.rs | 33 +- compiler/rustc_parse/src/parser/ty.rs | 300 +++--------------- .../restrict_anonymous_structs.rs | 40 +-- .../restrict_anonymous_structs.stderr | 170 +--------- .../restrict_anonymous_unions.rs | 39 +-- .../restrict_anonymous_unions.stderr | 170 +--------- 7 files changed, 73 insertions(+), 685 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9e05ec36bd956..371ae7947ca0a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -220,9 +220,7 @@ impl<'a> AstValidator<'a> { } } TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => { - // self.with_banned_assoc_ty_bound(|this| { walk_list!(self, visit_field_def, fields) - // }); } _ => visit::walk_ty(self, t), } @@ -1059,9 +1057,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); - // self.with_banned_assoc_ty_bound(|this| { walk_list!(self, visit_struct_field_def, fields); - // }); walk_list!(self, visit_attribute, &item.attrs); return; } @@ -1076,9 +1072,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); - // self.with_banned_assoc_ty_bound(|this| { walk_list!(self, visit_struct_field_def, fields); - // }); walk_list!(self, visit_attribute, &item.attrs); return; } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0723d663f8b29..138e41e00b9de 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,5 +1,5 @@ use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; -use super::ty::{AllowAnonStructOrUnion, AllowPlus, RecoverQPath, RecoverReturnSign}; +use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; use crate::errors::{self, MacroExpandsToAdtField}; use crate::fluent_generated as fluent; @@ -590,7 +590,7 @@ impl<'a> Parser<'a> { self.bump(); // `..`, do not add it to expected tokens Some(self.mk_ty(self.prev_token.span, TyKind::Err)) } else if has_for || self.token.can_begin_type() { - Some(self.parse_second_ty_for_item_impl()?) + Some(self.parse_ty()?) } else { None }; @@ -1595,26 +1595,11 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn parse_record_struct_body( + pub(crate) fn parse_record_struct_body( &mut self, adt_ty: &str, ident_span: Span, parsed_where: bool, - ) -> PResult<'a, (ThinVec, /* recovered */ bool)> { - self.parse_record_struct_body_common( - adt_ty, - ident_span, - parsed_where, - AllowAnonStructOrUnion::Yes, - ) - } - - pub(crate) fn parse_record_struct_body_common( - &mut self, - adt_ty: &str, - ident_span: Span, - parsed_where: bool, - allow_anon_struct_or_union: AllowAnonStructOrUnion<'a>, ) -> PResult<'a, (ThinVec, /* recovered */ bool)> { let mut fields = ThinVec::new(); let mut recovered = false; @@ -1628,18 +1613,6 @@ impl<'a> Parser<'a> { match field { Ok(field) => fields.push(field), Err(mut err) => { - // When recovering the anonymous structs or unions, we should't emit the error - // immediately, because it may also be a type path `union` followed by a block, - // such as `impl union { fn foo() {} }`. Here we are actaully not parsing a - // record struct body but an `impl` body. - // - // Instead, the error should be thrown and handled by the caller - // `parse_anon_struct_or_union`. - if let AllowAnonStructOrUnion::RecoverNonEmptyOrElse(_) = - allow_anon_struct_or_union - { - return Err(err); - } err.span_label(ident_span, format!("while parsing this {adt_ty}")); err.emit(); break; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 022ab34a074b6..3fc9bbf96ff3a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -62,100 +62,6 @@ pub(super) enum RecoverQuestionMark { No, } -/// Whether allowed to parse or recover an anonymous struct or union. -#[derive(Debug, Clone, Copy)] -pub(crate) enum AllowAnonStructOrUnion<'a> { - /// Parse the anonymous structs or unions regularly. - /// - /// It is always okay to parse it in fields definitions, and nice to - /// recover. - /// ```ignore (feature-not-ready) - /// #[repr(C)] - /// struct Foo { - /// _: struct { - /// a: u32, - /// b: u64, - /// _: union { - /// c: f64, - /// d: char, - /// } - /// }, - /// } - /// ``` - /// Similarly, for types of parameters, where there is no second way to parse - /// the anonymous structs or unions, we can parse it and report an error that - /// anonymous structs or unions are not allowed here. - Yes, - /// Recover an anonymous struct or union for diagnostic, but be more - /// conservative than `Yes` if there are other ways to parse it. - /// - /// This mode is preferred where types are allowed to be followed by a block - /// `{` ... `}`, where the block cannot contain field definitions. Such as: - /// - `impl $(Trait for)? Type {}` - /// - `fn foo() -> Type {}` - /// - /// Except for some special cases (will discuss below), anonymous structs or - /// unions with empty fields are always ambiguous since the empty block `{}` - /// can also be valid `impl` bodies or `fn` bodies, so we usually shouldn't - /// allow recovery of empty anonymous structs or unions. - /// - /// # Examples - /// ## Empty blocks - /// ``` - /// # #![allow(non_camel_case_types)] - /// # trait Foo {} - /// # struct union {} - /// impl union {} - /// impl Foo for union {} - /// fn foo() -> union { - /// union {} - /// } - /// ``` - /// ## Non-empty blocks - /// ```compile_fail - /// // This will be recovered as an anonymous struct - /// impl struct { foo: Foo } { - /// fn foo() {} - /// } - /// // This will be first recovered as an anonymous union (but will fail) - /// // and then parsed as a type named `union` followed by an `fn` block. - /// fn bar() -> union { - /// let _i = 0; - /// } - /// ``` - /// # A Special Case - /// In `impl` items, even if for an anonymous struct or union with - /// empty fields, we can still allow recovering it as long as it is followed by - /// some tokens such as `where`, `for`, or `{`. - /// ```compile_fail - /// impl union {} for union {} where union: union {} - /// ``` - RecoverNonEmptyOrElse(/* allow_followed_by */ Option) -> bool>), - /// Disallow parsing of anonymous structs or unions. - /// - /// Generally, we should avoid parsing or recovering anonymous structs or unions - /// if we have no information of what can appear in a block `{` ... `}` followed - /// by a type, (such as a `$ty:ty { /* any macro rules */ }` in macros), or - /// otherwise the following codes will be broken. - /// ``` - /// macro_rules! ty { - /// ($ty:ty { $($field:ident : $field_ty:ty)* }) => {}; - /// } - /// ty!(union { union: union }); - /// ty!(union {}); - /// ``` - No, -} - -impl<'a> AllowAnonStructOrUnion<'a> { - fn recover_non_empty_or_else(allow_followed_by: fn(&Parser<'a>) -> bool) -> Self { - Self::RecoverNonEmptyOrElse(Some(allow_followed_by)) - } - fn recover_non_empty() -> Self { - Self::RecoverNonEmptyOrElse(None) - } -} - /// Signals whether parsing a type should recover `->`. /// /// More specifically, when parsing a function like: @@ -213,29 +119,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::recover_non_empty(), - ) - } - - fn can_follow_first_ty_in_item_impl(&self) -> bool { - self.token.is_keyword(kw::For) || self.can_follow_second_ty_in_item_impl() - } - - fn can_follow_second_ty_in_item_impl(&self) -> bool { - self.token.is_keyword(kw::Where) || self.token == token::OpenDelim(Delimiter::Brace) - } - - pub(super) fn parse_second_ty_for_item_impl(&mut self) -> PResult<'a, P> { - self.parse_ty_common( - AllowPlus::Yes, - AllowCVariadic::No, - RecoverQPath::Yes, - RecoverReturnSign::Yes, - None, - RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::recover_non_empty_or_else( - Self::can_follow_second_ty_in_item_impl, - ), ) } @@ -250,9 +133,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, Some(ty_params), RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::recover_non_empty_or_else( - Self::can_follow_first_ty_in_item_impl, - ), ) } @@ -260,15 +140,18 @@ impl<'a> Parser<'a> { /// The difference from `parse_ty` is that this version /// allows anonymous structs and unions. pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P> { - self.parse_ty_common( - AllowPlus::Yes, - AllowCVariadic::No, - RecoverQPath::Yes, - RecoverReturnSign::Yes, - None, - RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::Yes, - ) + if self.can_begin_anon_struct_or_union() { + self.parse_anon_struct_or_union() + } else { + self.parse_ty_common( + AllowPlus::Yes, + AllowCVariadic::No, + RecoverQPath::Yes, + RecoverReturnSign::Yes, + None, + RecoverQuestionMark::Yes, + ) + } } /// Parse a type suitable for a function or function pointer parameter. @@ -282,7 +165,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::Yes, ) } @@ -300,7 +182,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::Yes, - AllowAnonStructOrUnion::No, ) } @@ -314,7 +195,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - AllowAnonStructOrUnion::No, ) } @@ -326,8 +206,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::Yes, None, RecoverQuestionMark::No, - // Disable the entry of parsing `$ty:ty` in macros - AllowAnonStructOrUnion::No, ) } @@ -340,8 +218,6 @@ impl<'a> Parser<'a> { RecoverReturnSign::OnlyFatArrow, None, RecoverQuestionMark::Yes, - // The `where` clause can be followed by a valid empty block `{}`. - AllowAnonStructOrUnion::recover_non_empty(), ) } @@ -361,8 +237,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - // Return types can be followed by a valid empty block `{}`. - AllowAnonStructOrUnion::recover_non_empty(), )?; FnRetTy::Ty(ty) } else if recover_return_sign.can_recover(&self.token.kind) { @@ -377,8 +251,6 @@ impl<'a> Parser<'a> { recover_return_sign, None, RecoverQuestionMark::Yes, - // Return types can be followed by a valid empty block `{}`. - AllowAnonStructOrUnion::recover_non_empty(), )?; FnRetTy::Ty(ty) } else { @@ -394,7 +266,6 @@ impl<'a> Parser<'a> { recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, - allow_anon_struct_or_union: AllowAnonStructOrUnion<'a>, ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); @@ -449,13 +320,7 @@ impl<'a> Parser<'a> { let (qself, path) = self.parse_qpath(PathStyle::Type)?; TyKind::Path(Some(qself), path) } else if self.check_path() { - // `union` is a weak keyword, so it can possibly be a path - if self.can_start_anon_union() - && let Some(ty_kind) = self.parse_anon_struct_or_union(lo, allow_anon_struct_or_union)? { - ty_kind - } else { - self.parse_path_start_ty(lo, allow_plus, ty_generics)? - } + self.parse_path_start_ty(lo, allow_plus, ty_generics)? } else if self.can_begin_bound() { self.parse_bare_trait_object(lo, allow_plus)? } else if self.eat(&token::DotDotDot) { @@ -469,15 +334,10 @@ impl<'a> Parser<'a> { } } } else { - if self.can_start_anon_struct() - && let Some(ty_kind) = self.parse_anon_struct_or_union(lo, allow_anon_struct_or_union)? { - ty_kind - } else { - let msg = format!("expected type, found {}", super::token_descr(&self.token)); - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected type"); - return Err(err); - } + let msg = format!("expected type, found {}", super::token_descr(&self.token)); + let mut err = self.struct_span_err(self.token.span, msg); + err.span_label(self.token.span, "expected type"); + return Err(err); }; let span = lo.to(self.prev_token.span); @@ -494,105 +354,34 @@ impl<'a> Parser<'a> { if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } - /// Parse an anonymous struct or union, and returns: - /// - `Ok(Some(ty_kind))`, when successful. - /// - `Ok(None)`, when failed and recovery is diabled. - /// - `Err(err)`, a parse error which should be handled by the caller. - /// This will only happen when we are actually parsing instead of recovering - /// from an anonymous struct or union. - /// - /// See also [`AllowAnonStructOrUnion`]. - fn parse_anon_struct_or_union( - &mut self, - lo: Span, - allow_anon_struct_or_union: AllowAnonStructOrUnion<'a>, - ) -> PResult<'a, Option> { - if let AllowAnonStructOrUnion::No = allow_anon_struct_or_union { - return Ok(None); - } + /// 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> { assert!(self.token.is_keyword(kw::Union) || self.token.is_keyword(kw::Struct)); let is_union = self.token.is_keyword(kw::Union); - let snapshot = self.create_snapshot_for_diagnostic(); - let span = self.token.span; + let lo = self.token.span; self.bump(); - // FIXME(performance): the struct body will be parsed twice when we restore the snapshot. - match self.parse_anon_struct_or_union_body( - if is_union { "union" } else { "struct" }, - span, - allow_anon_struct_or_union, - ) { - Ok(fields) => match allow_anon_struct_or_union { - // Don't recover an anonymous struct or union followed by an empty block - AllowAnonStructOrUnion::RecoverNonEmptyOrElse(None) if fields.is_empty() => { - self.restore_snapshot(snapshot); - Ok(None) - } - // Don't recover an anonymous struct or union followed by an empty block, - // except it is followed by some specific tokens. - AllowAnonStructOrUnion::RecoverNonEmptyOrElse(Some(allow_followed_by)) - if fields.is_empty() && !allow_followed_by(self) => - { - self.restore_snapshot(snapshot); - Ok(None) - } - // Parse the anonymous struct or union and return. - _ => { - let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::unnamed_fields, span); - // These can be rejected during AST validation in `deny_anon_struct_or_union`. - if is_union { - Ok(Some(TyKind::AnonUnion(fields))) - } else { - Ok(Some(TyKind::AnonStruct(fields))) - } - } - }, - Err(err) => { - // Don't recover an anonymous struct or union with errors. - if let AllowAnonStructOrUnion::RecoverNonEmptyOrElse(_) = allow_anon_struct_or_union - { - err.cancel(); - self.restore_snapshot(snapshot); - Ok(None) - } else { - Err(err) - } - } - } - } - - fn parse_anon_struct_or_union_body( - &mut self, - adt_ty: &str, - ident_span: Span, - allow_anon_struct_or_union: AllowAnonStructOrUnion<'a>, - ) -> PResult<'a, ThinVec> { - self.parse_record_struct_body_common( - adt_ty, - ident_span, - false, - allow_anon_struct_or_union, - ) - .map(|(mut fields, recovered)| { - // Don't recover an anonymous struct or union if it is already recovered. - // - // If it is a recovered struct or union, we should not accept it in case that - // the non-empty block happens to be a valid block. e.g.: - // ``` - // type union = u32; - // static union: union = 0; - // fn foo() -> union { - // union - // } - // ``` - // here the `union { union }` will be recovered as a single field union. - if let AllowAnonStructOrUnion::RecoverNonEmptyOrElse(_) = allow_anon_struct_or_union && recovered { - fields.clear(); - } - fields - }) + 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.sess.gated_spans.gate(sym::unnamed_fields, span); + // These can be rejected during AST validation in `deny_anon_struct_or_union`. + let kind = if is_union { TyKind::AnonUnion(fields) } else { TyKind::AnonStruct(fields) }; + Ok(self.mk_ty(span, kind)) } /// Parses either: @@ -955,13 +744,8 @@ impl<'a> Parser<'a> { Ok(bounds) } - pub(super) fn can_start_anon_union(&mut self) -> bool { - self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)) - } - - pub(super) fn can_start_anon_struct(&mut self) -> bool { - self.token.is_keyword(kw::Struct) + 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)) } diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs index e6539b387a76a..192bbba5a5b3a 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.rs @@ -1,13 +1,6 @@ #![allow(incomplete_features)] #![feature(unnamed_fields)] -fn f() -> struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -fn f2(a: struct { field: u8 } ) {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - - struct F { field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields //~^ ERROR anonymous structs are unimplemented @@ -30,12 +23,7 @@ union I { _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types } -struct J(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - enum K { - L(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented 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 @@ -46,30 +34,4 @@ enum K { } } -const L: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -static M: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -type N = struct { field: u8 }; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -impl struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -trait Foo {} - -impl Foo for struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous structs are unimplemented - -fn main() { - let p: [struct { field: u8 }; 1]; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - - let q: (struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented - - let c = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous structs are unimplemented -} +fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr index 3c7383b1a2d5a..fd731766c01ff 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_structs.stderr @@ -1,53 +1,29 @@ error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:4:11 - | -LL | fn f() -> struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:7:10 - | -LL | fn f2(a: struct { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:12:12 + --> $DIR/restrict_anonymous_structs.rs:5:12 | LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:19:5 + --> $DIR/restrict_anonymous_structs.rs:12: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:23:12 + --> $DIR/restrict_anonymous_structs.rs:16:12 | LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_structs.rs:30:5 + --> $DIR/restrict_anonymous_structs.rs:23: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:33:10 - | -LL | struct J(struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:37:7 - | -LL | L(struct { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_structs.rs:40:9 + --> $DIR/restrict_anonymous_structs.rs:28:9 | LL | _ : struct { field: u8 }, | -^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,168 +31,48 @@ 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:40:13 + --> $DIR/restrict_anonymous_structs.rs:28: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:45:9 + --> $DIR/restrict_anonymous_structs.rs:33:9 | LL | _ : u8, | -^^^^^ | | | unnamed field declared here -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:49:10 - | -LL | const L: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:52:11 - | -LL | static M: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:55:10 - | -LL | type N = struct { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:58:6 - | -LL | impl struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:63:14 - | -LL | impl Foo for struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:67:13 - | -LL | let p: [struct { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:70:13 - | -LL | let q: (struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - -error: anonymous structs are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_structs.rs:73:19 - | -LL | let c = || -> struct { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here - error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:4:11 - | -LL | fn f() -> struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:7:10 - | -LL | fn f2(a: struct { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:12:12 + --> $DIR/restrict_anonymous_structs.rs:5:12 | LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:14:8 + --> $DIR/restrict_anonymous_structs.rs:7:8 | LL | _: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:23:12 + --> $DIR/restrict_anonymous_structs.rs:16:12 | LL | field: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:25:8 + --> $DIR/restrict_anonymous_structs.rs:18:8 | LL | _: struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:33:10 - | -LL | struct J(struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:37:7 - | -LL | L(struct { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:40:13 + --> $DIR/restrict_anonymous_structs.rs:28:13 | LL | _ : struct { field: u8 }, | ^^^^^^^^^^^^^^^^^^^^ -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:49:10 - | -LL | const L: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:52:11 - | -LL | static M: struct { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:55:10 - | -LL | type N = struct { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:58:6 - | -LL | impl struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:63:14 - | -LL | impl Foo for struct { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:67:13 - | -LL | let p: [struct { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:70:13 - | -LL | let q: (struct { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^^ - -error: anonymous structs are unimplemented - --> $DIR/restrict_anonymous_structs.rs:73:19 - | -LL | let c = || -> struct { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 36 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs index 8d68b106b9f4d..c69266089bba5 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.rs @@ -1,12 +1,6 @@ #![allow(incomplete_features)] #![feature(unnamed_fields)] -fn f() -> union { field: u8 } {} //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -fn f2(a: union { field: u8 } ) {} //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - struct F { field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields //~^ ERROR anonymous unions are unimplemented @@ -29,12 +23,7 @@ union I { _: (u8, u8), //~ ERROR unnamed fields can only have struct or union types } -struct J(union { field: u8 }, u8); //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - enum K { - L(union { field: u8 }), //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented 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 @@ -45,30 +34,4 @@ enum K { } } -const L: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -static M: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -type N = union { field: u8 }; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -impl union { field: u8 } {} //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -// //~^ ERROR anonymous unions are unimplemented - -trait Foo {} - -impl Foo for union { field: u8 } {} //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields -//~^ ERROR anonymous unions are unimplemented - -fn main() { - let p: [union { field: u8 }; 1]; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented - - let q: (union { field: u8 }, u8); //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented - - let c = || -> union { field: u8 } {}; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields - //~^ ERROR anonymous unions are unimplemented -} +fn main() {} diff --git a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr index 473c800dde9cf..c65cad775a90c 100644 --- a/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr +++ b/tests/ui/union/unnamed-fields/restrict_anonymous_unions.stderr @@ -1,53 +1,29 @@ error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:4:11 - | -LL | fn f() -> union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:7:10 - | -LL | fn f2(a: union { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:11:12 + --> $DIR/restrict_anonymous_unions.rs:5:12 | LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:18:5 + --> $DIR/restrict_anonymous_unions.rs:12: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:22:12 + --> $DIR/restrict_anonymous_unions.rs:16:12 | LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here error: unnamed fields can only have struct or union types - --> $DIR/restrict_anonymous_unions.rs:29:5 + --> $DIR/restrict_anonymous_unions.rs:23: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:32:10 - | -LL | struct J(union { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:36:7 - | -LL | L(union { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - error: unnamed fields are not allowed outside of structs or unions - --> $DIR/restrict_anonymous_unions.rs:39:9 + --> $DIR/restrict_anonymous_unions.rs:28:9 | LL | _ : union { field: u8 }, | -^^^^^^^^^^^^^^^^^^^^^^ @@ -55,168 +31,48 @@ 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:39:13 + --> $DIR/restrict_anonymous_unions.rs:28: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:44:9 + --> $DIR/restrict_anonymous_unions.rs:33:9 | LL | _ : u8, | -^^^^^ | | | unnamed field declared here -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:48:10 - | -LL | const L: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:51:11 - | -LL | static M: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:54:10 - | -LL | type N = union { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:57:6 - | -LL | impl union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:62:14 - | -LL | impl Foo for union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:66:13 - | -LL | let p: [union { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:69:13 - | -LL | let q: (union { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - -error: anonymous unions are not allowed outside of unnamed struct or union fields - --> $DIR/restrict_anonymous_unions.rs:72:19 - | -LL | let c = || -> union { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here - error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:4:11 - | -LL | fn f() -> union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:7:10 - | -LL | fn f2(a: union { field: u8 } ) {} - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:11:12 + --> $DIR/restrict_anonymous_unions.rs:5:12 | LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:13:8 + --> $DIR/restrict_anonymous_unions.rs:7:8 | LL | _: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:22:12 + --> $DIR/restrict_anonymous_unions.rs:16:12 | LL | field: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:24:8 + --> $DIR/restrict_anonymous_unions.rs:18:8 | LL | _: union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:32:10 - | -LL | struct J(union { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:36:7 - | -LL | L(union { field: u8 }), - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:39:13 + --> $DIR/restrict_anonymous_unions.rs:28:13 | LL | _ : union { field: u8 }, | ^^^^^^^^^^^^^^^^^^^ -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:48:10 - | -LL | const L: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:51:11 - | -LL | static M: union { field: u8 } = 0; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:54:10 - | -LL | type N = union { field: u8 }; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:57:6 - | -LL | impl union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:62:14 - | -LL | impl Foo for union { field: u8 } {} - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:66:13 - | -LL | let p: [union { field: u8 }; 1]; - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:69:13 - | -LL | let q: (union { field: u8 }, u8); - | ^^^^^^^^^^^^^^^^^^^ - -error: anonymous unions are unimplemented - --> $DIR/restrict_anonymous_unions.rs:72:19 - | -LL | let c = || -> union { field: u8 } {}; - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 36 previous errors +error: aborting due to 12 previous errors