about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_parse/src/parser')
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs62
-rw-r--r--compiler/rustc_parse/src/parser/item.rs22
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs17
3 files changed, 60 insertions, 41 deletions
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 5aebe716b0a..76ecb77d750 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -1,6 +1,7 @@
 use ast::token::Delimiter;
 use rustc_ast::{
-    self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token,
+    self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind,
+    WhereClause, token,
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::Span;
@@ -14,8 +15,8 @@ use crate::errors::{
     WhereClauseBeforeTupleStructBodySugg,
 };
 
-enum PredicateOrStructBody {
-    Predicate(ast::WherePredicate),
+enum PredicateKindOrStructBody {
+    PredicateKind(ast::WherePredicateKind),
     StructBody(ThinVec<ast::FieldDef>),
 }
 
@@ -218,10 +219,11 @@ impl<'a> Parser<'a> {
                 } else if this.token.can_begin_type() {
                     // Trying to write an associated type bound? (#26271)
                     let snapshot = this.create_snapshot_for_diagnostic();
-                    match this.parse_ty_where_predicate() {
-                        Ok(where_predicate) => {
+                    let lo = this.token.span;
+                    match this.parse_ty_where_predicate_kind() {
+                        Ok(_) => {
                             this.dcx().emit_err(errors::BadAssocTypeBounds {
-                                span: where_predicate.span(),
+                                span: lo.to(this.prev_token.span),
                             });
                             // FIXME - try to continue parsing other generics?
                         }
@@ -340,31 +342,33 @@ impl<'a> Parser<'a> {
         loop {
             let where_sp = where_lo.to(self.prev_token.span);
             let pred_lo = self.token.span;
-            if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
+            let kind = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
                 let lifetime = self.expect_lifetime();
                 // Bounds starting with a colon are mandatory, but possibly empty.
                 self.expect(&token::Colon)?;
                 let bounds = self.parse_lt_param_bounds();
-                where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
-                    ast::WhereRegionPredicate {
-                        span: pred_lo.to(self.prev_token.span),
-                        lifetime,
-                        bounds,
-                    },
-                ));
+                ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
+                    lifetime,
+                    bounds,
+                })
             } else if self.check_type() {
-                match self.parse_ty_where_predicate_or_recover_tuple_struct_body(
+                match self.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
                     struct_, pred_lo, where_sp,
                 )? {
-                    PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred),
-                    PredicateOrStructBody::StructBody(body) => {
+                    PredicateKindOrStructBody::PredicateKind(kind) => kind,
+                    PredicateKindOrStructBody::StructBody(body) => {
                         tuple_struct_body = Some(body);
                         break;
                     }
                 }
             } else {
                 break;
-            }
+            };
+            where_clause.predicates.push(ast::WherePredicate {
+                kind,
+                id: DUMMY_NODE_ID,
+                span: pred_lo.to(self.prev_token.span),
+            });
 
             let prev_token = self.prev_token.span;
             let ate_comma = self.eat(&token::Comma);
@@ -384,12 +388,12 @@ impl<'a> Parser<'a> {
         Ok((where_clause, tuple_struct_body))
     }
 
-    fn parse_ty_where_predicate_or_recover_tuple_struct_body(
+    fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
         &mut self,
         struct_: Option<(Ident, Span)>,
         pred_lo: Span,
         where_sp: Span,
-    ) -> PResult<'a, PredicateOrStructBody> {
+    ) -> PResult<'a, PredicateKindOrStructBody> {
         let mut snapshot = None;
 
         if let Some(struct_) = struct_
@@ -399,8 +403,8 @@ impl<'a> Parser<'a> {
             snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
         };
 
-        match self.parse_ty_where_predicate() {
-            Ok(pred) => Ok(PredicateOrStructBody::Predicate(pred)),
+        match self.parse_ty_where_predicate_kind() {
+            Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
             Err(type_err) => {
                 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
                     return Err(type_err);
@@ -436,7 +440,7 @@ impl<'a> Parser<'a> {
                         });
 
                         self.restore_snapshot(snapshot);
-                        Ok(PredicateOrStructBody::StructBody(body))
+                        Ok(PredicateKindOrStructBody::StructBody(body))
                     }
                     Ok(_) => Err(type_err),
                     Err(body_err) => {
@@ -448,8 +452,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> {
-        let lo = self.token.span;
+    fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
         // Parse optional `for<'a, 'b>`.
         // This `for` is parsed greedily and applies to the whole predicate,
         // the bounded type can have its own `for` applying only to it.
@@ -464,8 +467,7 @@ impl<'a> Parser<'a> {
         let ty = self.parse_ty_for_where_clause()?;
         if self.eat(&token::Colon) {
             let bounds = self.parse_generic_bounds()?;
-            Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
-                span: lo.to(self.prev_token.span),
+            Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
                 bound_generic_params: lifetime_defs,
                 bounded_ty: ty,
                 bounds,
@@ -474,11 +476,7 @@ impl<'a> Parser<'a> {
         // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
         } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
             let rhs_ty = self.parse_ty()?;
-            Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
-                span: lo.to(self.prev_token.span),
-                lhs_ty: ty,
-                rhs_ty,
-            }))
+            Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
         } else {
             self.maybe_recover_bounds_doubled_colon(&ty)?;
             self.unexpected_any()
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index fddbf5896ad..26e81b7676b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -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,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index c4326427f67..004b5b34813 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,11 +1,12 @@
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
+use rustc_ast::util::parser::AssocOp;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
-    self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, ExprPrecedence,
-    LocalKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd,
-    RangeSyntax, Stmt, StmtKind,
+    self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall,
+    Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
+    StmtKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
@@ -458,7 +459,7 @@ impl<'a> Parser<'a> {
                 .create_err(UnexpectedExpressionInPattern {
                     span,
                     is_bound,
-                    expr_precedence: expr.precedence().order(),
+                    expr_precedence: expr.precedence(),
                 })
                 .stash(span, StashKey::ExprInPat)
                 .unwrap(),
@@ -545,7 +546,8 @@ impl<'a> Parser<'a> {
                             let expr = match &err.args["expr_precedence"] {
                                 DiagArgValue::Number(expr_precedence) => {
                                     if *expr_precedence
-                                        <= ExprPrecedence::Binary(BinOpKind::Eq).order() as i32
+                                        <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence()
+                                            as i32
                                     {
                                         format!("({expr})")
                                     } else {
@@ -568,8 +570,9 @@ impl<'a> Parser<'a> {
                                 }
                                 Some(guard) => {
                                     // Are parentheses required around the old guard?
-                                    let wrap_guard = guard.precedence().order()
-                                        <= ExprPrecedence::Binary(BinOpKind::And).order();
+                                    let wrap_guard = guard.precedence()
+                                        <= AssocOp::from_ast_binop(BinOpKind::And).precedence()
+                                            as i8;
 
                                     err.subdiagnostic(
                                         UnexpectedExpressionInPatternSugg::UpdateGuard {