about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-06 08:14:58 +0000
committerbors <bors@rust-lang.org>2024-06-06 08:14:58 +0000
commit2d28b6384e5e0a2c9d1500a1f65e35423453fbf6 (patch)
tree3a67252345dc7839b6b6e246c16fd2de79fca402 /compiler/rustc_parse/src
parent2b6a34273d820df4140a00984d38d40c745fb565 (diff)
parent525828d5ee9baca7f7e651918df966f6bc38596a (diff)
downloadrust-2d28b6384e5e0a2c9d1500a1f65e35423453fbf6.tar.gz
rust-2d28b6384e5e0a2c9d1500a1f65e35423453fbf6.zip
Auto merge of #124482 - spastorino:unsafe-extern-blocks, r=oli-obk
Unsafe extern blocks

This implements RFC 3484.

Tracking issue #123743 and RFC https://github.com/rust-lang/rfcs/pull/3484

This is better reviewed commit by commit.
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/parser/item.rs39
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
2 files changed, 34 insertions, 7 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 53757c38e8b..37c99958fc8 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -226,10 +226,11 @@ impl<'a> Parser<'a> {
             self.expect_keyword(kw::Extern)?;
             self.parse_item_foreign_mod(attrs, safety)?
         } else if self.is_static_global() {
+            let safety = self.parse_safety(Case::Sensitive);
             // STATIC ITEM
             self.bump(); // `static`
             let mutability = self.parse_mutability();
-            let (ident, item) = self.parse_static_item(mutability)?;
+            let (ident, item) = self.parse_static_item(safety, mutability)?;
             (ident, ItemKind::Static(Box::new(item)))
         } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
             // CONST ITEM
@@ -952,7 +953,7 @@ impl<'a> Parser<'a> {
                 let kind = match AssocItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
-                        ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
+                        ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
                             self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
                             AssocItemKind::Const(Box::new(ConstItem {
                                 defaultness: Defaultness::Final,
@@ -1221,6 +1222,7 @@ impl<'a> Parser<'a> {
                                 ty,
                                 mutability: Mutability::Not,
                                 expr,
+                                safety: Safety::Default,
                             }))
                         }
                         _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
@@ -1258,7 +1260,10 @@ impl<'a> Parser<'a> {
                 matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
             })
         } else {
-            false
+            let quals: &[Symbol] = &[kw::Unsafe, kw::Safe];
+            // `$qual static`
+            quals.iter().any(|&kw| self.check_keyword(kw))
+                && self.look_ahead(1, |t| t.is_keyword(kw::Static))
         }
     }
 
@@ -1319,7 +1324,11 @@ impl<'a> Parser<'a> {
     /// ```ebnf
     /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
     /// ```
-    fn parse_static_item(&mut self, mutability: Mutability) -> PResult<'a, (Ident, StaticItem)> {
+    fn parse_static_item(
+        &mut self,
+        safety: Safety,
+        mutability: Mutability,
+    ) -> PResult<'a, (Ident, StaticItem)> {
         let ident = self.parse_ident()?;
 
         if self.token.kind == TokenKind::Lt && self.may_recover() {
@@ -1340,7 +1349,7 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((ident, StaticItem { ty, mutability, expr }))
+        Ok((ident, StaticItem { ty, safety, mutability, expr }))
     }
 
     /// Parse a constant item with the prefix `"const"` already parsed.
@@ -2400,9 +2409,9 @@ impl<'a> Parser<'a> {
         // `pub` is added in case users got confused with the ordering like `async pub fn`,
         // only if it wasn't preceded by `default` as `default pub` is invalid.
         let quals: &[Symbol] = if check_pub {
-            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
         } else {
-            &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+            &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
         };
         self.check_keyword_case(kw::Fn, case) // Definitely an `fn`.
             // `$qual fn` or `$qual $qual`:
@@ -2537,11 +2546,27 @@ impl<'a> Parser<'a> {
                     } else if self.check_keyword(kw::Unsafe) {
                         match safety {
                             Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
+                            Safety::Safe(sp) => {
+                                recover_safety = Safety::Unsafe(self.token.span);
+                                Some(WrongKw::Misplaced(sp))
+                            }
                             Safety::Default => {
                                 recover_safety = Safety::Unsafe(self.token.span);
                                 Some(WrongKw::Misplaced(ext_start_sp))
                             }
                         }
+                    } else if self.check_keyword(kw::Safe) {
+                        match safety {
+                            Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
+                            Safety::Unsafe(sp) => {
+                                recover_safety = Safety::Safe(self.token.span);
+                                Some(WrongKw::Misplaced(sp))
+                            }
+                            Safety::Default => {
+                                recover_safety = Safety::Safe(self.token.span);
+                                Some(WrongKw::Misplaced(ext_start_sp))
+                            }
+                        }
                     } else {
                         None
                     };
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index bab8b6c06eb..8f733b4fcbb 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1221,6 +1221,8 @@ impl<'a> Parser<'a> {
     fn parse_safety(&mut self, case: Case) -> Safety {
         if self.eat_keyword_case(kw::Unsafe, case) {
             Safety::Unsafe(self.prev_token.uninterpolated_span())
+        } else if self.eat_keyword_case(kw::Safe, case) {
+            Safety::Safe(self.prev_token.uninterpolated_span())
         } else {
             Safety::Default
         }