about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-05-17 12:15:26 +0000
committerbors <bors@rust-lang.org>2021-05-17 12:15:26 +0000
commit9964284fed181676300aad693449f5b751e35ff2 (patch)
tree03eb105fdadb767ef2ab06ddb5c834afb80aa2ff /src
parent44ec846f4ea68ffa6d06e7d68f078bd3cc59d4ec (diff)
parent64acb7d92135ae722dfce89f0ca9d7cf6576de66 (diff)
downloadrust-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.rs27
-rw-r--r--src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr111
-rw-r--r--src/test/ui/unnamed_fields/restrict_anonymous.rs52
-rw-r--r--src/test/ui/unnamed_fields/restrict_anonymous.stderr175
-rw-r--r--src/tools/rustfmt/src/items.rs11
-rw-r--r--src/tools/rustfmt/src/lib.rs7
-rw-r--r--src/tools/rustfmt/src/types.rs57
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)
             }