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`
This commit is contained in:
commit
9964284fed
19 changed files with 707 additions and 112 deletions
|
@ -1861,6 +1861,10 @@ pub enum TyKind {
|
||||||
Never,
|
Never,
|
||||||
/// A tuple (`(A, B, C, D,...)`).
|
/// A tuple (`(A, B, C, D,...)`).
|
||||||
Tup(Vec<P<Ty>>),
|
Tup(Vec<P<Ty>>),
|
||||||
|
/// An anonymous struct type i.e. `struct { foo: Type }`
|
||||||
|
AnonymousStruct(Vec<FieldDef>, bool),
|
||||||
|
/// An anonymous union type i.e. `union { bar: Type }`
|
||||||
|
AnonymousUnion(Vec<FieldDef>, bool),
|
||||||
/// A path (`module::module::...::Type`), optionally
|
/// A path (`module::module::...::Type`), optionally
|
||||||
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
|
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -484,6 +484,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
||||||
}
|
}
|
||||||
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
|
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||||
|
TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => {
|
||||||
|
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
visit_lazy_tts(tokens, vis);
|
visit_lazy_tts(tokens, vis);
|
||||||
|
|
|
@ -404,6 +404,9 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||||
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
|
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
|
||||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
|
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
|
||||||
TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
|
TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
|
||||||
|
TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
|
||||||
|
walk_list!(visitor, visit_field_def, fields)
|
||||||
|
}
|
||||||
TyKind::Never | TyKind::CVarArgs => {}
|
TyKind::Never | TyKind::CVarArgs => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -789,7 +789,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
|
pub(super) fn lower_field_def(
|
||||||
|
&mut self,
|
||||||
|
(index, f): (usize, &FieldDef),
|
||||||
|
) -> hir::FieldDef<'hir> {
|
||||||
let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
|
let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
|
||||||
let t = self.lower_path_ty(
|
let t = self.lower_path_ty(
|
||||||
&f.ty,
|
&f.ty,
|
||||||
|
|
|
@ -1267,6 +1267,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let kind = match t.kind {
|
let kind = match t.kind {
|
||||||
TyKind::Infer => hir::TyKind::Infer,
|
TyKind::Infer => hir::TyKind::Infer,
|
||||||
TyKind::Err => hir::TyKind::Err,
|
TyKind::Err => hir::TyKind::Err,
|
||||||
|
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||||
|
TyKind::AnonymousStruct(ref _fields, _recovered) => {
|
||||||
|
self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit();
|
||||||
|
hir::TyKind::Err
|
||||||
|
}
|
||||||
|
TyKind::AnonymousUnion(ref _fields, _recovered) => {
|
||||||
|
self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit();
|
||||||
|
hir::TyKind::Err
|
||||||
|
}
|
||||||
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
||||||
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
||||||
TyKind::Rptr(ref region, ref mt) => {
|
TyKind::Rptr(ref region, ref mt) => {
|
||||||
|
|
|
@ -175,10 +175,30 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
|
||||||
|
self.with_banned_assoc_ty_bound(|this| {
|
||||||
|
walk_list!(this, visit_struct_field_def, fields)
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => visit::walk_ty(self, t),
|
_ => visit::walk_ty(self, t),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
|
||||||
|
if let Some(ident) = field.ident {
|
||||||
|
if ident.name == kw::Underscore {
|
||||||
|
self.check_anonymous_field(field);
|
||||||
|
self.visit_vis(&field.vis);
|
||||||
|
self.visit_ident(ident);
|
||||||
|
self.visit_ty_common(&field.ty);
|
||||||
|
self.walk_ty(&field.ty);
|
||||||
|
walk_list!(self, visit_attribute, &field.attrs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.visit_field_def(field);
|
||||||
|
}
|
||||||
|
|
||||||
fn err_handler(&self) -> &rustc_errors::Handler {
|
fn err_handler(&self) -> &rustc_errors::Handler {
|
||||||
&self.session.diagnostic()
|
&self.session.diagnostic()
|
||||||
}
|
}
|
||||||
|
@ -213,6 +233,66 @@ impl<'a> AstValidator<'a> {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_anonymous_field(&self, field: &FieldDef) {
|
||||||
|
let FieldDef { ty, .. } = field;
|
||||||
|
match &ty.kind {
|
||||||
|
TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
|
||||||
|
// We already checked for `kw::Underscore` before calling this function,
|
||||||
|
// so skip the check
|
||||||
|
}
|
||||||
|
TyKind::Path(..) => {
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let msg = "unnamed fields can only have struct or union types";
|
||||||
|
let label = "not a struct or union";
|
||||||
|
self.err_handler()
|
||||||
|
.struct_span_err(field.span, msg)
|
||||||
|
.span_label(ty.span, label)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deny_anonymous_struct(&self, ty: &Ty) {
|
||||||
|
match &ty.kind {
|
||||||
|
TyKind::AnonymousStruct(..) => {
|
||||||
|
self.err_handler()
|
||||||
|
.struct_span_err(
|
||||||
|
ty.span,
|
||||||
|
"anonymous structs are not allowed outside of unnamed struct or union fields",
|
||||||
|
)
|
||||||
|
.span_label(ty.span, "anonymous struct declared here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
TyKind::AnonymousUnion(..) => {
|
||||||
|
self.err_handler()
|
||||||
|
.struct_span_err(
|
||||||
|
ty.span,
|
||||||
|
"anonymous unions are not allowed outside of unnamed struct or union fields",
|
||||||
|
)
|
||||||
|
.span_label(ty.span, "anonymous union declared here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deny_anonymous_field(&self, field: &FieldDef) {
|
||||||
|
if let Some(ident) = field.ident {
|
||||||
|
if ident.name == kw::Underscore {
|
||||||
|
self.err_handler()
|
||||||
|
.struct_span_err(
|
||||||
|
field.span,
|
||||||
|
"anonymous fields are not allowed outside of structs or unions",
|
||||||
|
)
|
||||||
|
.span_label(ident.span, "anonymous field declared here")
|
||||||
|
.emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
|
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
|
||||||
for Param { pat, .. } in &decl.inputs {
|
for Param { pat, .. } in &decl.inputs {
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
|
@ -732,6 +812,71 @@ impl<'a> AstValidator<'a> {
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty_common(&mut self, ty: &'a Ty) {
|
||||||
|
match ty.kind {
|
||||||
|
TyKind::BareFn(ref bfty) => {
|
||||||
|
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
|
||||||
|
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
|
||||||
|
struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
span,
|
||||||
|
E0561,
|
||||||
|
"patterns aren't allowed in function pointer types"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
});
|
||||||
|
self.check_late_bound_lifetime_defs(&bfty.generic_params);
|
||||||
|
}
|
||||||
|
TyKind::TraitObject(ref bounds, ..) => {
|
||||||
|
let mut any_lifetime_bounds = false;
|
||||||
|
for bound in bounds {
|
||||||
|
if let GenericBound::Outlives(ref lifetime) = *bound {
|
||||||
|
if any_lifetime_bounds {
|
||||||
|
struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
lifetime.ident.span,
|
||||||
|
E0226,
|
||||||
|
"only a single explicit lifetime bound is permitted"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
any_lifetime_bounds = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.no_questions_in_bounds(bounds, "trait object types", false);
|
||||||
|
}
|
||||||
|
TyKind::ImplTrait(_, ref bounds) => {
|
||||||
|
if self.is_impl_trait_banned {
|
||||||
|
struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
ty.span,
|
||||||
|
E0667,
|
||||||
|
"`impl Trait` is not allowed in path parameters"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
|
||||||
|
struct_span_err!(
|
||||||
|
self.session,
|
||||||
|
ty.span,
|
||||||
|
E0666,
|
||||||
|
"nested `impl Trait` is not allowed"
|
||||||
|
)
|
||||||
|
.span_label(outer_impl_trait_sp, "outer `impl Trait`")
|
||||||
|
.span_label(ty.span, "nested `impl Trait` here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
|
||||||
|
self.err_handler().span_err(ty.span, "at least one trait must be specified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that generic parameters are in the correct order,
|
/// Checks that generic parameters are in the correct order,
|
||||||
|
@ -850,72 +995,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||||
match ty.kind {
|
self.visit_ty_common(ty);
|
||||||
TyKind::BareFn(ref bfty) => {
|
self.deny_anonymous_struct(ty);
|
||||||
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
|
|
||||||
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
|
|
||||||
struct_span_err!(
|
|
||||||
self.session,
|
|
||||||
span,
|
|
||||||
E0561,
|
|
||||||
"patterns aren't allowed in function pointer types"
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
});
|
|
||||||
self.check_late_bound_lifetime_defs(&bfty.generic_params);
|
|
||||||
}
|
|
||||||
TyKind::TraitObject(ref bounds, ..) => {
|
|
||||||
let mut any_lifetime_bounds = false;
|
|
||||||
for bound in bounds {
|
|
||||||
if let GenericBound::Outlives(ref lifetime) = *bound {
|
|
||||||
if any_lifetime_bounds {
|
|
||||||
struct_span_err!(
|
|
||||||
self.session,
|
|
||||||
lifetime.ident.span,
|
|
||||||
E0226,
|
|
||||||
"only a single explicit lifetime bound is permitted"
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
any_lifetime_bounds = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.no_questions_in_bounds(bounds, "trait object types", false);
|
|
||||||
}
|
|
||||||
TyKind::ImplTrait(_, ref bounds) => {
|
|
||||||
if self.is_impl_trait_banned {
|
|
||||||
struct_span_err!(
|
|
||||||
self.session,
|
|
||||||
ty.span,
|
|
||||||
E0667,
|
|
||||||
"`impl Trait` is not allowed in path parameters"
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
|
|
||||||
struct_span_err!(
|
|
||||||
self.session,
|
|
||||||
ty.span,
|
|
||||||
E0666,
|
|
||||||
"nested `impl Trait` is not allowed"
|
|
||||||
)
|
|
||||||
.span_label(outer_impl_trait_sp, "outer `impl Trait`")
|
|
||||||
.span_label(ty.span, "nested `impl Trait` here")
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
|
|
||||||
self.err_handler().span_err(ty.span, "at least one trait must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.walk_ty(ty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.walk_ty(ty)
|
self.walk_ty(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,6 +1010,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
visit::walk_lifetime(self, lifetime);
|
visit::walk_lifetime(self, lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_field_def(&mut self, s: &'a FieldDef) {
|
||||||
|
self.deny_anonymous_field(s);
|
||||||
|
visit::walk_field_def(self, s)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'a Item) {
|
fn visit_item(&mut self, item: &'a Item) {
|
||||||
if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
|
if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
|
||||||
self.has_proc_macro_decls = true;
|
self.has_proc_macro_decls = true;
|
||||||
|
@ -1084,14 +1170,42 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.check_mod_file_item_asciionly(item.ident);
|
self.check_mod_file_item_asciionly(item.ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Union(ref vdata, _) => {
|
ItemKind::Struct(ref vdata, ref generics) => match vdata {
|
||||||
if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
|
// Duplicating the `Visitor` logic allows catching all cases
|
||||||
self.err_handler()
|
// of `Anonymous(Struct, Union)` outside of a field struct or union.
|
||||||
.span_err(item.span, "tuple and unit unions are not permitted");
|
//
|
||||||
|
// Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
|
||||||
|
// encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
|
||||||
|
// it uses `visit_ty_common`, which doesn't contain that specific check.
|
||||||
|
VariantData::Struct(ref fields, ..) => {
|
||||||
|
self.visit_vis(&item.vis);
|
||||||
|
self.visit_ident(item.ident);
|
||||||
|
self.visit_generics(generics);
|
||||||
|
self.with_banned_assoc_ty_bound(|this| {
|
||||||
|
walk_list!(this, visit_struct_field_def, fields);
|
||||||
|
});
|
||||||
|
walk_list!(self, visit_attribute, &item.attrs);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
ItemKind::Union(ref vdata, ref generics) => {
|
||||||
if vdata.fields().is_empty() {
|
if vdata.fields().is_empty() {
|
||||||
self.err_handler().span_err(item.span, "unions cannot have zero fields");
|
self.err_handler().span_err(item.span, "unions cannot have zero fields");
|
||||||
}
|
}
|
||||||
|
match vdata {
|
||||||
|
VariantData::Struct(ref fields, ..) => {
|
||||||
|
self.visit_vis(&item.vis);
|
||||||
|
self.visit_ident(item.ident);
|
||||||
|
self.visit_generics(generics);
|
||||||
|
self.with_banned_assoc_ty_bound(|this| {
|
||||||
|
walk_list!(this, visit_struct_field_def, fields);
|
||||||
|
});
|
||||||
|
walk_list!(self, visit_attribute, &item.attrs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Const(def, .., None) => {
|
ItemKind::Const(def, .., None) => {
|
||||||
self.check_defaultness(item.span, def);
|
self.check_defaultness(item.span, def);
|
||||||
|
|
|
@ -725,6 +725,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||||
// involved, so we only emit errors where there are no other parsing errors.
|
// involved, so we only emit errors where there are no other parsing errors.
|
||||||
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
|
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
|
||||||
}
|
}
|
||||||
|
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||||
|
|
||||||
// All uses of `gate_all!` below this point were added in #65742,
|
// All uses of `gate_all!` below this point were added in #65742,
|
||||||
// and subsequently disabled (with the non-early gating readded).
|
// and subsequently disabled (with the non-early gating readded).
|
||||||
|
|
|
@ -954,6 +954,14 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
self.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
|
ast::TyKind::AnonymousStruct(ref fields, ..) => {
|
||||||
|
self.s.word("struct");
|
||||||
|
self.print_record_struct_body(fields, ty.span);
|
||||||
|
}
|
||||||
|
ast::TyKind::AnonymousUnion(ref fields, ..) => {
|
||||||
|
self.s.word("union");
|
||||||
|
self.print_record_struct_body(fields, ty.span);
|
||||||
|
}
|
||||||
ast::TyKind::Paren(ref typ) => {
|
ast::TyKind::Paren(ref typ) => {
|
||||||
self.popen();
|
self.popen();
|
||||||
self.print_type(typ);
|
self.print_type(typ);
|
||||||
|
@ -1389,6 +1397,29 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn print_record_struct_body(
|
||||||
|
&mut self,
|
||||||
|
fields: &Vec<ast::FieldDef>,
|
||||||
|
span: rustc_span::Span,
|
||||||
|
) {
|
||||||
|
self.nbsp();
|
||||||
|
self.bopen();
|
||||||
|
self.hardbreak_if_not_bol();
|
||||||
|
|
||||||
|
for field in fields {
|
||||||
|
self.hardbreak_if_not_bol();
|
||||||
|
self.maybe_print_comment(field.span.lo());
|
||||||
|
self.print_outer_attributes(&field.attrs);
|
||||||
|
self.print_visibility(&field.vis);
|
||||||
|
self.print_ident(field.ident.unwrap());
|
||||||
|
self.word_nbsp(":");
|
||||||
|
self.print_type(&field.ty);
|
||||||
|
self.s.word(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.bclose(span)
|
||||||
|
}
|
||||||
|
|
||||||
crate fn print_struct(
|
crate fn print_struct(
|
||||||
&mut self,
|
&mut self,
|
||||||
struct_def: &ast::VariantData,
|
struct_def: &ast::VariantData,
|
||||||
|
@ -1418,24 +1449,9 @@ impl<'a> State<'a> {
|
||||||
self.end();
|
self.end();
|
||||||
self.end(); // Close the outer-box.
|
self.end(); // Close the outer-box.
|
||||||
}
|
}
|
||||||
ast::VariantData::Struct(..) => {
|
ast::VariantData::Struct(ref fields, ..) => {
|
||||||
self.print_where_clause(&generics.where_clause);
|
self.print_where_clause(&generics.where_clause);
|
||||||
self.nbsp();
|
self.print_record_struct_body(fields, span);
|
||||||
self.bopen();
|
|
||||||
self.hardbreak_if_not_bol();
|
|
||||||
|
|
||||||
for field in struct_def.fields() {
|
|
||||||
self.hardbreak_if_not_bol();
|
|
||||||
self.maybe_print_comment(field.span.lo());
|
|
||||||
self.print_outer_attributes(&field.attrs);
|
|
||||||
self.print_visibility(&field.vis);
|
|
||||||
self.print_ident(field.ident.unwrap());
|
|
||||||
self.word_nbsp(":");
|
|
||||||
self.print_type(&field.ty);
|
|
||||||
self.s.word(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.bclose(span)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,6 +671,9 @@ declare_features! (
|
||||||
/// Allows specifying the as-needed link modifier
|
/// Allows specifying the as-needed link modifier
|
||||||
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
(active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
|
||||||
|
|
||||||
|
/// Allows unnamed fields of struct and union type
|
||||||
|
(active, unnamed_fields, "1.53.0", Some(49804), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
@ -704,6 +707,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
|
||||||
sym::native_link_modifiers_whole_archive,
|
sym::native_link_modifiers_whole_archive,
|
||||||
sym::native_link_modifiers_as_needed,
|
sym::native_link_modifiers_as_needed,
|
||||||
sym::rustc_insignificant_dtor,
|
sym::rustc_insignificant_dtor,
|
||||||
|
sym::unnamed_fields,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Some features are not allowed to be used together at the same time, if
|
/// Some features are not allowed to be used together at the same time, if
|
||||||
|
|
|
@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok((class_name, ItemKind::Union(vdata, generics)))
|
Ok((class_name, ItemKind::Union(vdata, generics)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_record_struct_body(
|
pub(super) fn parse_record_struct_body(
|
||||||
&mut self,
|
&mut self,
|
||||||
adt_ty: &str,
|
adt_ty: &str,
|
||||||
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
|
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
|
||||||
|
@ -1470,19 +1470,25 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
|
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
|
||||||
let (ident, is_raw) = self.ident_or_err()?;
|
let (ident, is_raw) = self.ident_or_err()?;
|
||||||
if !is_raw && ident.is_reserved() {
|
if !is_raw && ident.is_reserved() {
|
||||||
let err = if self.check_fn_front_matter(false) {
|
if ident.name == kw::Underscore {
|
||||||
let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
|
self.sess.gated_spans.gate(sym::unnamed_fields, lo);
|
||||||
let mut err = self.struct_span_err(
|
|
||||||
lo.to(self.prev_token.span),
|
|
||||||
&format!("functions are not allowed in {} definitions", adt_ty),
|
|
||||||
);
|
|
||||||
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
|
|
||||||
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
|
|
||||||
err
|
|
||||||
} else {
|
} else {
|
||||||
self.expected_ident_found()
|
let err = if self.check_fn_front_matter(false) {
|
||||||
};
|
let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
|
||||||
return Err(err);
|
let mut err = self.struct_span_err(
|
||||||
|
lo.to(self.prev_token.span),
|
||||||
|
&format!("functions are not allowed in {} definitions", adt_ty),
|
||||||
|
);
|
||||||
|
err.help(
|
||||||
|
"unlike in C++, Java, and C#, functions are declared in `impl` blocks",
|
||||||
|
);
|
||||||
|
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
|
||||||
|
err
|
||||||
|
} else {
|
||||||
|
self.expected_ident_found()
|
||||||
|
};
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.bump();
|
self.bump();
|
||||||
Ok(ident)
|
Ok(ident)
|
||||||
|
|
|
@ -226,6 +226,19 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
} else if self.eat_keyword(kw::Impl) {
|
} else if self.eat_keyword(kw::Impl) {
|
||||||
self.parse_impl_ty(&mut impl_dyn_multi)?
|
self.parse_impl_ty(&mut impl_dyn_multi)?
|
||||||
|
} else if self.token.is_keyword(kw::Union)
|
||||||
|
&& self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|
||||||
|
{
|
||||||
|
self.bump();
|
||||||
|
let (fields, recovered) = self.parse_record_struct_body("union")?;
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
self.sess.gated_spans.gate(sym::unnamed_fields, span);
|
||||||
|
TyKind::AnonymousUnion(fields, recovered)
|
||||||
|
} else if self.eat_keyword(kw::Struct) {
|
||||||
|
let (fields, recovered) = self.parse_record_struct_body("struct")?;
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
self.sess.gated_spans.gate(sym::unnamed_fields, span);
|
||||||
|
TyKind::AnonymousStruct(fields, recovered)
|
||||||
} else if self.is_explicit_dyn_type() {
|
} else if self.is_explicit_dyn_type() {
|
||||||
self.parse_dyn_ty(&mut impl_dyn_multi)?
|
self.parse_dyn_ty(&mut impl_dyn_multi)?
|
||||||
} else if self.eat_lt() {
|
} else if self.eat_lt() {
|
||||||
|
|
|
@ -1270,6 +1270,7 @@ symbols! {
|
||||||
unix,
|
unix,
|
||||||
unlikely,
|
unlikely,
|
||||||
unmarked_api,
|
unmarked_api,
|
||||||
|
unnamed_fields,
|
||||||
unpin,
|
unpin,
|
||||||
unreachable,
|
unreachable,
|
||||||
unreachable_code,
|
unreachable_code,
|
||||||
|
|
27
src/test/ui/feature-gates/feature-gate-unnamed_fields.rs
Normal file
27
src/test/ui/feature-gates/feature-gate-unnamed_fields.rs
Normal file
|
@ -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(){}
|
111
src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr
Normal file
111
src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr
Normal file
|
@ -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`.
|
52
src/test/ui/unnamed_fields/restrict_anonymous.rs
Normal file
52
src/test/ui/unnamed_fields/restrict_anonymous.rs
Normal file
|
@ -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
|
||||||
|
}
|
175
src/test/ui/unnamed_fields/restrict_anonymous.stderr
Normal file
175
src/test/ui/unnamed_fields/restrict_anonymous.stderr
Normal file
|
@ -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`.
|
|
@ -6,7 +6,7 @@ use std::cmp::{max, min, Ordering};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustc_ast::visit;
|
use rustc_ast::visit;
|
||||||
use rustc_ast::{ast, ptr};
|
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::attr::filter_inline_attrs;
|
||||||
use crate::comment::{
|
use crate::comment::{
|
||||||
|
@ -31,12 +31,7 @@ use crate::stmt::Stmt;
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
use crate::vertical::rewrite_with_alignment;
|
use crate::vertical::rewrite_with_alignment;
|
||||||
use crate::visitor::FmtVisitor;
|
use crate::visitor::FmtVisitor;
|
||||||
|
use crate::DEFAULT_VISIBILITY;
|
||||||
const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
|
|
||||||
kind: ast::VisibilityKind::Inherited,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
tokens: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn type_annotation_separator(config: &Config) -> &str {
|
fn type_annotation_separator(config: &Config) -> &str {
|
||||||
colon_spaces(config)
|
colon_spaces(config)
|
||||||
|
@ -976,7 +971,7 @@ impl<'a> StructParts<'a> {
|
||||||
format_header(context, self.prefix, self.ident, self.vis, offset)
|
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 {
|
StructParts {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
ident: variant.ident,
|
ident: variant.ident,
|
||||||
|
|
|
@ -31,7 +31,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use ignore;
|
use ignore;
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_span::symbol;
|
use rustc_span::{symbol, DUMMY_SP};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::comment::LineClasses;
|
use crate::comment::LineClasses;
|
||||||
|
@ -95,6 +95,11 @@ mod types;
|
||||||
mod vertical;
|
mod vertical;
|
||||||
pub(crate) mod visitor;
|
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
|
/// The various errors that can occur during formatting. Note that not all of
|
||||||
/// these can currently be propagated to clients.
|
/// these can currently be propagated to clients.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
|
@ -2,14 +2,14 @@ use std::iter::ExactSizeIterator;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_ast::ast::{self, FnRetTy, Mutability};
|
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::lists::*;
|
||||||
use crate::config::{IndentStyle, TypeDensity, Version};
|
use crate::config::{IndentStyle, TypeDensity, Version};
|
||||||
use crate::expr::{
|
use crate::expr::{
|
||||||
format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
|
format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
|
||||||
};
|
};
|
||||||
|
use crate::items::StructParts;
|
||||||
use crate::lists::{
|
use crate::lists::{
|
||||||
definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
|
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,
|
colon_spaces, extra_offset, first_line_width, format_extern, format_mutability,
|
||||||
last_line_extendable, last_line_width, mk_sp, rewrite_ident,
|
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)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub(crate) enum PathContext {
|
pub(crate) enum PathContext {
|
||||||
|
@ -764,6 +769,54 @@ impl Rewrite for ast::Ty {
|
||||||
ast::TyKind::Tup(ref items) => {
|
ast::TyKind::Tup(ref items) => {
|
||||||
rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
|
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) => {
|
ast::TyKind::Path(ref q_self, ref path) => {
|
||||||
rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
|
rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue