1
Fork 0

Rollup merge of #134274 - fmease:amp-raw-is-a-normal-borrow, r=Noratrieb

Add check-pass test for `&raw`

`&raw` denotes a normal/non-raw borrow of the path `raw`, not the start of raw borrow since it's not followed by either `const` or `mut`. Ensure this (and variants) will never regress!

When I saw the open diagnostic issue https://github.com/rust-lang/rust/issues/133231 (better parse error (recovery) on `&raw <expr>`), it made me think that we have to make sure that we will never commit too early/overzealously(†) when encountering the sequence `&raw`, even during parse error recovery!

Modifying the parser to eagerly treat `&raw` as the start of a raw borrow expr only lead to a single UI test failing, namely [tests/ui/enum-discriminant/ptr_niche.rs](4847d6a9d0/tests/ui/enum-discriminant/ptr_niche.rs). However, this is just coincidental — it didn't *intentionally* test this edge case of the grammar.

---

†: With "eager" I mean something like:

```patch
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0904a42d8a4..68d690fd602 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
`@@` -873,11 +873,16 `@@` fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {

     /// Parse `mut?` or `raw [ const | mut ]`.
     fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
-        if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) {
+        if self.eat_keyword(kw::Raw) {
             // `raw [ const | mut ]`.
-            let found_raw = self.eat_keyword(kw::Raw);
-            assert!(found_raw);
-            let mutability = self.parse_const_or_mut().unwrap();
+            let mutability = self.parse_const_or_mut().unwrap_or_else(|| {
+                let span = self.prev_token.span;
+                self.dcx().emit_err(ExpectedMutOrConstInRawBorrowExpr {
+                    span,
+                    after_ampersand: span.shrink_to_hi(),
+                });
+                ast::Mutability::Not
+            });
             (ast::BorrowKind::Raw, mutability)
         } else {
             // `mut?`
```

---

r? compiler
This commit is contained in:
Matthias Krüger 2024-12-14 04:09:37 +01:00 committed by GitHub
commit 4efa98cf2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -0,0 +1,30 @@
//! The token sequence `&raw` *only* starts a raw borrow expr if it's immediately
//! followed by either `const` or `mut`. If that's not the case, the `&` denotes
//! the start of a normal borrow expr where `raw` is interpreted as a regular
//! identifier and thus denotes the start of a path expr.
//!
//! This test ensures that we never commit too early/overzealously in the parser
//! when encountering the sequence `&raw` (even during parse error recovery) so
//! as not to regress preexisting code.
//@ check-pass
fn main() { // the odd formatting in here is intentional
let raw = 0;
let _ = &raw;
let raw = 0;
let local = 1;
let _: i32 = &raw *local;
let raw = |_| ();
let local = [0];
let () = &raw (local[0]);
}
macro_rules! check {
($e:expr) => { compile_error!("expr"); };
(&raw $e:expr) => {};
}
check!(&raw local);