Implement the unsafe-fields RFC.

Co-Authored-By: Jacob Pratt <jacob@jhpratt.dev>
This commit is contained in:
Luca Versari 2024-10-27 01:35:33 +02:00
parent 75703c1a78
commit 9022bb2d6f
38 changed files with 793 additions and 85 deletions

View file

@ -1791,6 +1791,17 @@ impl<'a> Parser<'a> {
Ok((fields, recovered))
}
fn parse_unsafe_field(&mut self) -> Safety {
// not using parse_safety as that also accepts `safe`.
if self.eat_keyword(kw::Unsafe) {
let span = self.prev_token.span;
self.psess.gated_spans.gate(sym::unsafe_fields, span);
Safety::Unsafe(span)
} else {
Safety::Default
}
}
pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
// Unit like structs are handled in parse_item_struct function
@ -1814,6 +1825,8 @@ impl<'a> Parser<'a> {
return Err(err);
}
};
// Unsafe fields are not supported in tuple structs, as doing so would result in a
// parsing ambiguity for `struct X(unsafe fn())`.
let ty = match p.parse_ty() {
Ok(ty) => ty,
Err(err) => {
@ -1828,6 +1841,7 @@ impl<'a> Parser<'a> {
FieldDef {
span: lo.to(ty.span),
vis,
safety: Safety::Default,
ident: None,
id: DUMMY_NODE_ID,
ty,
@ -1850,7 +1864,8 @@ impl<'a> Parser<'a> {
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span;
let vis = this.parse_visibility(FollowedByType::No)?;
this.parse_single_struct_field(adt_ty, lo, vis, attrs)
let safety = this.parse_unsafe_field();
this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs)
.map(|field| (field, Trailing::No, UsePreAttrPos::No))
})
}
@ -1861,10 +1876,11 @@ impl<'a> Parser<'a> {
adt_ty: &str,
lo: Span,
vis: Visibility,
safety: Safety,
attrs: AttrVec,
) -> PResult<'a, FieldDef> {
let mut seen_comma: bool = false;
let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?;
let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?;
if self.token == token::Comma {
seen_comma = true;
}
@ -1992,6 +2008,7 @@ impl<'a> Parser<'a> {
adt_ty: &str,
lo: Span,
vis: Visibility,
safety: Safety,
attrs: AttrVec,
) -> PResult<'a, FieldDef> {
let name = self.parse_field_ident(adt_ty, lo)?;
@ -2017,6 +2034,7 @@ impl<'a> Parser<'a> {
span: lo.to(self.prev_token.span),
ident: Some(name),
vis,
safety,
id: DUMMY_NODE_ID,
ty,
attrs,