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
|
@ -136,6 +136,17 @@ impl<'a> Parser<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Parse a type suitable for a field defintion.
|
||||
/// 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<Ty>> {
|
||||
if self.can_begin_anon_struct_or_union() {
|
||||
self.parse_anon_struct_or_union()
|
||||
} else {
|
||||
self.parse_ty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a type suitable for a function or function pointer parameter.
|
||||
/// The difference from `parse_ty` is that this version allows `...`
|
||||
/// (`CVarArgs`) at the top level of the type.
|
||||
|
@ -336,6 +347,36 @@ impl<'a> Parser<'a> {
|
|||
if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
|
||||
}
|
||||
|
||||
/// 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<Ty>> {
|
||||
assert!(self.token.is_keyword(kw::Union) || self.token.is_keyword(kw::Struct));
|
||||
let is_union = self.token.is_keyword(kw::Union);
|
||||
|
||||
let lo = self.token.span;
|
||||
self.bump();
|
||||
|
||||
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:
|
||||
/// - `(TYPE)`, a parenthesized type.
|
||||
/// - `(TYPE,)`, a tuple with a single field of type TYPE.
|
||||
|
@ -696,6 +737,11 @@ impl<'a> Parser<'a> {
|
|||
Ok(bounds)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/// Can the current token begin a bound?
|
||||
fn can_begin_bound(&mut self) -> bool {
|
||||
// This needs to be synchronized with `TokenKind::can_begin_bound`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue