diff options
| author | bors <bors@rust-lang.org> | 2021-05-17 12:15:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-05-17 12:15:26 +0000 |
| commit | 9964284fed181676300aad693449f5b751e35ff2 (patch) | |
| tree | 03eb105fdadb767ef2ab06ddb5c834afb80aa2ff /src | |
| parent | 44ec846f4ea68ffa6d06e7d68f078bd3cc59d4ec (diff) | |
| parent | 64acb7d92135ae722dfce89f0ca9d7cf6576de66 (diff) | |
| download | rust-9964284fed181676300aad693449f5b751e35ff2.tar.gz rust-9964284fed181676300aad693449f5b751e35ff2.zip | |
Auto merge of #84571 - jedel1043:issue-49804-impl, r=petrochenkov
Parse unnamed fields of struct and union type Added the `unnamed_fields` feature gate. This is a prototype of [RFC 2102](https://github.com/rust-lang/rust/issues/49804), so any suggestions are greatly appreciated. r? `@petrochenkov`
Diffstat (limited to 'src')
| -rw-r--r-- | src/test/ui/feature-gates/feature-gate-unnamed_fields.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr | 111 | ||||
| -rw-r--r-- | src/test/ui/unnamed_fields/restrict_anonymous.rs | 52 | ||||
| -rw-r--r-- | src/test/ui/unnamed_fields/restrict_anonymous.stderr | 175 | ||||
| -rw-r--r-- | src/tools/rustfmt/src/items.rs | 11 | ||||
| -rw-r--r-- | src/tools/rustfmt/src/lib.rs | 7 | ||||
| -rw-r--r-- | src/tools/rustfmt/src/types.rs | 57 |
7 files changed, 429 insertions, 11 deletions
diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs b/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs new file mode 100644 index 00000000000..bd815dbcc92 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs @@ -0,0 +1,27 @@ +struct Foo { + foo: u8, + _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658] + //~^ ERROR unnamed fields are not yet fully implemented [E0658] + //~| ERROR anonymous unions are unimplemented + bar: u8, + baz: u16 + } +} + +union Bar { + foobar: u8, + _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658] + //~^ ERROR unnamed fields are not yet fully implemented [E0658] + //~| ERROR anonymous structs are unimplemented + //~| ERROR unions may not contain fields that need dropping [E0740] + foobaz: u8, + barbaz: u16 + } +} + +struct S; +struct Baz { + _: S //~ ERROR unnamed fields are not yet fully implemented [E0658] +} + +fn main(){} diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr b/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr new file mode 100644 index 00000000000..4f3ab85c987 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr @@ -0,0 +1,111 @@ +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:3: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 + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:3:8 + | +LL | _: union { + | ________^ +LL | | +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 + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:13: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 + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:13:8 + | +LL | _: struct { + | ________^ +LL | | +LL | | +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 + +error[E0658]: unnamed fields are not yet fully implemented + --> $DIR/feature-gate-unnamed_fields.rs:24: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 + +error: anonymous unions are unimplemented + --> $DIR/feature-gate-unnamed_fields.rs:3:8 + | +LL | _: union { + | ________^ +LL | | +LL | | +LL | | bar: u8, +LL | | baz: u16 +LL | | } + | |_____^ + +error: anonymous structs are unimplemented + --> $DIR/feature-gate-unnamed_fields.rs:13:8 + | +LL | _: struct { + | ________^ +LL | | +LL | | +LL | | +LL | | foobaz: u8, +LL | | barbaz: u16 +LL | | } + | |_____^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/feature-gate-unnamed_fields.rs:13:5 + | +LL | / _: struct { +LL | | +LL | | +LL | | +LL | | foobaz: u8, +LL | | barbaz: u16 +LL | | } + | |_____^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/feature-gate-unnamed_fields.rs:13:5 + | +LL | / _: struct { +LL | | +LL | | +LL | | +LL | | foobaz: u8, +LL | | barbaz: u16 +LL | | } + | |_____^ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0658, E0740. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.rs b/src/test/ui/unnamed_fields/restrict_anonymous.rs new file mode 100644 index 00000000000..99637d11053 --- /dev/null +++ b/src/test/ui/unnamed_fields/restrict_anonymous.rs @@ -0,0 +1,52 @@ +#![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 + +union G { + field: struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented +} +//~| ERROR unions may not contain fields that need dropping [E0740] + +struct H { _: u8 } // Should error after hir checks + +struct I(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields +//~^ ERROR anonymous structs are unimplemented + +enum J { + K(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented + L { + _ : struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous fields are not allowed outside of structs or unions + //~| ERROR anonymous structs are unimplemented + }, + M { + _ : u8 //~ ERROR anonymous fields are not allowed outside of structs or unions + } +} + +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 + +fn main() { + const O: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented + + 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 cl = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields + //~^ ERROR anonymous structs are unimplemented +} diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.stderr b/src/test/ui/unnamed_fields/restrict_anonymous.stderr new file mode 100644 index 00000000000..efcf544fde4 --- /dev/null +++ b/src/test/ui/unnamed_fields/restrict_anonymous.stderr @@ -0,0 +1,175 @@ +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.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.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.rs:11:12 + | +LL | field: struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:18:10 + | +LL | struct I(struct { field: u8 }, u8); + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:22:7 + | +LL | K(struct { field: u8 }), + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous.rs:25:9 + | +LL | _ : struct { field: u8 } + | -^^^^^^^^^^^^^^^^^^^^^^^ + | | + | anonymous field declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:25:13 + | +LL | _ : struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous fields are not allowed outside of structs or unions + --> $DIR/restrict_anonymous.rs:30:9 + | +LL | _ : u8 + | -^^^^^ + | | + | anonymous field declared here + +error: anonymous unions are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:34: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.rs:37:10 + | +LL | type N = union { field: u8 }; + | ^^^^^^^^^^^^^^^^^^^ anonymous union declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:41:14 + | +LL | const O: struct { field: u8 } = 0; + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/restrict_anonymous.rs:44: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.rs:47: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.rs:50:20 + | +LL | let cl = || -> struct { field: u8 } {}; + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:4:11 + | +LL | fn f() -> struct { field: u8 } {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:7:10 + | +LL | fn f2(a: struct { field: u8 } ) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:11:12 + | +LL | field: struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:18:10 + | +LL | struct I(struct { field: u8 }, u8); + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:22:7 + | +LL | K(struct { field: u8 }), + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:25:13 + | +LL | _ : struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous.rs:34:11 + | +LL | static M: union { field: u8 } = 0; + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous unions are unimplemented + --> $DIR/restrict_anonymous.rs:37:10 + | +LL | type N = union { field: u8 }; + | ^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:44:13 + | +LL | let p: [struct { field: u8 }; 1]; + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:47:13 + | +LL | let q: (struct { field: u8 }, u8); + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:50:20 + | +LL | let cl = || -> struct { field: u8 } {}; + | ^^^^^^^^^^^^^^^^^^^^ + +error: anonymous structs are unimplemented + --> $DIR/restrict_anonymous.rs:41:14 + | +LL | const O: struct { field: u8 } = 0; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/restrict_anonymous.rs:11:5 + | +LL | field: struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/restrict_anonymous.rs:11:5 + | +LL | field: struct { field: u8 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index ecbd0bd12ec..420484c0ba1 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -6,7 +6,7 @@ use std::cmp::{max, min, Ordering}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; +use rustc_span::{symbol, BytePos, Span}; use crate::attr::filter_inline_attrs; use crate::comment::{ @@ -31,12 +31,7 @@ use crate::stmt::Stmt; use crate::utils::*; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; - -const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { - kind: ast::VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, -}; +use crate::DEFAULT_VISIBILITY; fn type_annotation_separator(config: &Config) -> &str { colon_spaces(config) @@ -976,7 +971,7 @@ impl<'a> StructParts<'a> { format_header(context, self.prefix, self.ident, self.vis, offset) } - fn from_variant(variant: &'a ast::Variant) -> Self { + pub(crate) fn from_variant(variant: &'a ast::Variant) -> Self { StructParts { prefix: "", ident: variant.ident, diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 8a798777e0e..cde5d390cf2 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -31,7 +31,7 @@ use std::rc::Rc; use ignore; use rustc_ast::ast; -use rustc_span::symbol; +use rustc_span::{symbol, DUMMY_SP}; use thiserror::Error; use crate::comment::LineClasses; @@ -95,6 +95,11 @@ mod types; mod vertical; pub(crate) mod visitor; +const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { + kind: ast::VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, +}; /// The various errors that can occur during formatting. Note that not all of /// these can currently be propagated to clients. #[derive(Error, Debug)] diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index cda17e13eeb..5597af9ee32 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -2,14 +2,14 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; -use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span}; -use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; use crate::expr::{ format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, }; +use crate::items::StructParts; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; @@ -24,6 +24,11 @@ use crate::utils::{ colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; +use crate::DEFAULT_VISIBILITY; +use crate::{ + comment::{combine_strs_with_missing_comments, contains_comment}, + items::format_struct_struct, +}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum PathContext { @@ -764,6 +769,54 @@ impl Rewrite for ast::Ty { ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) } + ast::TyKind::AnonymousStruct(ref fields, recovered) => { + let ident = Ident::new( + kw::Struct, + mk_sp(self.span.lo(), self.span.lo() + BytePos(6)), + ); + let data = ast::VariantData::Struct(fields.clone(), recovered); + let variant = ast::Variant { + attrs: vec![], + id: self.id, + span: self.span, + vis: DEFAULT_VISIBILITY, + ident, + data, + disr_expr: None, + is_placeholder: false, + }; + format_struct_struct( + &context, + &StructParts::from_variant(&variant), + fields, + shape.indent, + None, + ) + } + ast::TyKind::AnonymousUnion(ref fields, recovered) => { + let ident = Ident::new( + kw::Union, + mk_sp(self.span.lo(), self.span.lo() + BytePos(5)), + ); + let data = ast::VariantData::Struct(fields.clone(), recovered); + let variant = ast::Variant { + attrs: vec![], + id: self.id, + span: self.span, + vis: DEFAULT_VISIBILITY, + ident, + data, + disr_expr: None, + is_placeholder: false, + }; + format_struct_struct( + &context, + &StructParts::from_variant(&variant), + fields, + shape.indent, + None, + ) + } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } |
