Auto merge of #115131 - frank-king:feature/unnamed-fields-lite, r=petrochenkov
Parse unnamed fields and anonymous structs or unions (no-recovery) It is part of #114782 which implements #49804. Only parse anonymous structs or unions in struct field definition positions. r? `@petrochenkov`
This commit is contained in:
commit
18be2728bd
25 changed files with 650 additions and 5 deletions
|
@ -223,10 +223,27 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => {
|
||||
walk_list!(self, visit_field_def, fields)
|
||||
}
|
||||
_ => visit::walk_ty(self, t),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
|
||||
if let Some(ident) = field.ident &&
|
||||
ident.name == kw::Underscore {
|
||||
self.check_unnamed_field_ty(&field.ty, ident.span);
|
||||
self.visit_vis(&field.vis);
|
||||
self.visit_ident(ident);
|
||||
self.visit_ty_common(&field.ty);
|
||||
self.walk_ty(&field.ty);
|
||||
walk_list!(self, visit_attribute, &field.attrs);
|
||||
} else {
|
||||
self.visit_field_def(field);
|
||||
}
|
||||
}
|
||||
|
||||
fn err_handler(&self) -> &rustc_errors::Handler {
|
||||
&self.session.diagnostic()
|
||||
}
|
||||
|
@ -264,6 +281,42 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_unnamed_field_ty(&self, ty: &Ty, span: Span) {
|
||||
if matches!(
|
||||
&ty.kind,
|
||||
// We already checked for `kw::Underscore` before calling this function,
|
||||
// so skip the check
|
||||
TyKind::AnonStruct(..) | TyKind::AnonUnion(..)
|
||||
// If the anonymous field contains a Path as type, we can't determine
|
||||
// if the path is a valid struct or union, so skip the check
|
||||
| TyKind::Path(..)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
self.err_handler().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span });
|
||||
}
|
||||
|
||||
fn deny_anon_struct_or_union(&self, ty: &Ty) {
|
||||
let struct_or_union = match &ty.kind {
|
||||
TyKind::AnonStruct(..) => "struct",
|
||||
TyKind::AnonUnion(..) => "union",
|
||||
_ => return,
|
||||
};
|
||||
self.err_handler()
|
||||
.emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span });
|
||||
}
|
||||
|
||||
fn deny_unnamed_field(&self, field: &FieldDef) {
|
||||
if let Some(ident) = field.ident &&
|
||||
ident.name == kw::Underscore {
|
||||
self.err_handler()
|
||||
.emit_err(errors::InvalidUnnamedField {
|
||||
span: field.span,
|
||||
ident_span: ident.span
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const(&self, constness: Const) {
|
||||
if let Const::Yes(span) = constness {
|
||||
self.session.emit_err(errors::TraitFnConst { span });
|
||||
|
@ -789,6 +842,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
self.visit_ty_common(ty);
|
||||
self.deny_anon_struct_or_union(ty);
|
||||
self.walk_ty(ty)
|
||||
}
|
||||
|
||||
|
@ -803,6 +857,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||
self.deny_unnamed_field(field);
|
||||
visit::walk_field_def(self, field)
|
||||
}
|
||||
|
||||
|
@ -995,10 +1050,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_mod_file_item_asciionly(item.ident);
|
||||
}
|
||||
}
|
||||
ItemKind::Union(vdata, ..) => {
|
||||
ItemKind::Struct(vdata, generics) => match vdata {
|
||||
// Duplicating the `Visitor` logic allows catching all cases
|
||||
// of `Anonymous(Struct, Union)` outside of a field struct or union.
|
||||
//
|
||||
// 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(fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
walk_list!(self, visit_struct_field_def, fields);
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
ItemKind::Union(vdata, generics) => {
|
||||
if vdata.fields().is_empty() {
|
||||
self.err_handler().emit_err(errors::FieldlessUnion { span: item.span });
|
||||
}
|
||||
match vdata {
|
||||
VariantData::Struct(fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
walk_list!(self, visit_struct_field_def, fields);
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ItemKind::Const(box ConstItem { defaultness, expr: None, .. }) => {
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue