From 20061171104f8ce3cf27b994fc094e4f4ca4deaa Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 18 Jan 2025 14:38:27 -0800 Subject: [PATCH 1/3] add ui tests for &raw not followed by const or mut --- tests/ui/raw-ref-op/missing-modifier/let-stmt.rs | 12 ++++++++++++ .../raw-ref-op/missing-modifier/let-stmt.stderr | 13 +++++++++++++ .../missing-modifier/nested-array-expr.rs | 14 ++++++++++++++ .../missing-modifier/nested-array-expr.stderr | 8 ++++++++ .../raw-ref-op/missing-modifier/return-expr.rs | 16 ++++++++++++++++ .../missing-modifier/return-expr.stderr | 8 ++++++++ 6 files changed, 71 insertions(+) create mode 100644 tests/ui/raw-ref-op/missing-modifier/let-stmt.rs create mode 100644 tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr create mode 100644 tests/ui/raw-ref-op/missing-modifier/nested-array-expr.rs create mode 100644 tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr create mode 100644 tests/ui/raw-ref-op/missing-modifier/return-expr.rs create mode 100644 tests/ui/raw-ref-op/missing-modifier/return-expr.stderr diff --git a/tests/ui/raw-ref-op/missing-modifier/let-stmt.rs b/tests/ui/raw-ref-op/missing-modifier/let-stmt.rs new file mode 100644 index 0000000000000..b20e8a0511d93 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/let-stmt.rs @@ -0,0 +1,12 @@ +//! Check that `&raw` that isn't followed by `const` or `mut` produces a +//! helpful error message. +//! +//! Related issue: . + +fn main() { + let foo = 2; + let _ = &raw foo; + //~^ ERROR expected one of + //~| HELP you might have meant to use a raw reference + //~| HELP you might have meant to write a field access +} diff --git a/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr b/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr new file mode 100644 index 0000000000000..922058d6289e0 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `foo` + --> $DIR/let-stmt.rs:8:18 + | +LL | let _ = &raw foo; + | ^^^ expected one of 8 possible tokens + | +help: you might have meant to write a field access + | +LL | let _ = &raw.foo; + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.rs b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.rs new file mode 100644 index 0000000000000..088a169ba56c3 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.rs @@ -0,0 +1,14 @@ +//! Check that `&raw` that isn't followed by `const` or `mut` produces a +//! helpful error message. +//! +//! Related issue: . + +mod foo { + pub static A: i32 = 0; +} + +fn main() { + [&raw foo::A; 3]; + //~^ ERROR expected one of + //~| HELP you might have meant to use a raw reference +} diff --git a/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr new file mode 100644 index 0000000000000..4b9940cd5dcc1 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `,`, `.`, `::`, `;`, `?`, `]`, `{`, or an operator, found `foo` + --> $DIR/nested-array-expr.rs:11:11 + | +LL | [&raw foo::A; 3]; + | ^^^ expected one of 9 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/raw-ref-op/missing-modifier/return-expr.rs b/tests/ui/raw-ref-op/missing-modifier/return-expr.rs new file mode 100644 index 0000000000000..82ec1f29699b1 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/return-expr.rs @@ -0,0 +1,16 @@ +//! Check that `&raw` that isn't followed by `const` or `mut` produces a +//! helpful error message. +//! +//! Related issue: . + +mod foo { + pub static A: i32 = 0; +} + +fn get_ref() -> *const i32 { + &raw foo::A + //~^ ERROR expected one of + //~| HELP you might have meant to use a raw reference +} + +fn main() {} diff --git a/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr b/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr new file mode 100644 index 0000000000000..e2313e115a5c4 --- /dev/null +++ b/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `foo` + --> $DIR/return-expr.rs:11:10 + | +LL | &raw foo::A + | ^^^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + From 4ff7aff52a29d94968a9c428f5bfac84bc2e867c Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 19 Jan 2025 17:51:57 -0800 Subject: [PATCH 2/3] add suggestion to add `mut` or `const` after `&raw` --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/parser/diagnostics.rs | 16 ++++++++++++++++ compiler/rustc_parse/src/parser/expr.rs | 5 ++++- compiler/rustc_parse/src/parser/stmt.rs | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index d50bd18a1d7d8..7cd053a2fa245 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -764,6 +764,8 @@ parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attri parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding +parse_sugg_add_mut_or_const_in_raw_ref = you might have meant to use a raw reference + parse_sugg_add_semi = add `;` here parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 9ee6c2fae1ac0..3c084bd3ae6c8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1303,6 +1303,22 @@ impl<'a> Parser<'a> { Err(e) } + /// When writing `&raw` that is missing the following `mut` or `const`, we will + /// encounter a parse error when encountering the next expression. + pub(super) fn suggest_add_mut_or_const_in_raw_ref(&mut self, e: &mut Diag<'_>, expr: &P) { + if let ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, r) = &expr.kind + && let ast::ExprKind::Path(_, p) = &r.kind + && *p == Symbol::intern("raw") + { + e.span_suggestions( + expr.span.shrink_to_hi(), + fluent::parse_sugg_add_mut_or_const_in_raw_ref, + [" mut".to_string(), " const".to_string()], + Applicability::HasPlaceholders, + ); + } + } + /// Suggest add the missing `let` before the identifier in stmt /// `a: Ty = 1` -> `let a: Ty = 1` pub(super) fn suggest_add_missing_let_for_stmt(&mut self, err: &mut Diag<'a>) { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7533e75ffe261..9497c0a0d307c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1581,7 +1581,10 @@ impl<'a> Parser<'a> { ExprKind::Array(exprs) } else { // Vector with one element - self.expect(close)?; + self.expect(close).map_err(|mut e| { + self.suggest_add_mut_or_const_in_raw_ref(&mut e, &first_expr); + e + })?; ExprKind::Array(thin_vec![first_expr]) } }; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1ddb5fc0a1169..ff3990961a727 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -897,6 +897,7 @@ impl<'a> Parser<'a> { res? } else { res.unwrap_or_else(|mut e| { + self.suggest_add_mut_or_const_in_raw_ref(&mut e, expr); self.recover_missing_dot(&mut e); let guar = e.emit(); self.recover_stmt(); @@ -920,6 +921,7 @@ impl<'a> Parser<'a> { LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => { self.check_mistyped_turbofish_with_multiple_type_params(e, expr).map_err( |mut e| { + self.suggest_add_mut_or_const_in_raw_ref(&mut e, expr); self.recover_missing_dot(&mut e); e }, From 762772f215477dd834ee63ebf2926f6a4cf4fe41 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 19 Jan 2025 17:53:22 -0800 Subject: [PATCH 3/3] re-bless tests --- tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr | 6 ++++++ .../raw-ref-op/missing-modifier/nested-array-expr.stderr | 7 +++++++ tests/ui/raw-ref-op/missing-modifier/return-expr.stderr | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr b/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr index 922058d6289e0..ef2ce3758c680 100644 --- a/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr +++ b/tests/ui/raw-ref-op/missing-modifier/let-stmt.stderr @@ -4,6 +4,12 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo LL | let _ = &raw foo; | ^^^ expected one of 8 possible tokens | +help: you might have meant to use a raw reference + | +LL | let _ = &raw mut foo; + | +++ +LL | let _ = &raw const foo; + | +++++ help: you might have meant to write a field access | LL | let _ = &raw.foo; diff --git a/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr index 4b9940cd5dcc1..9fddef26787c5 100644 --- a/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr +++ b/tests/ui/raw-ref-op/missing-modifier/nested-array-expr.stderr @@ -3,6 +3,13 @@ error: expected one of `!`, `,`, `.`, `::`, `;`, `?`, `]`, `{`, or an operator, | LL | [&raw foo::A; 3]; | ^^^ expected one of 9 possible tokens + | +help: you might have meant to use a raw reference + | +LL | [&raw mut foo::A; 3]; + | +++ +LL | [&raw const foo::A; 3]; + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr b/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr index e2313e115a5c4..2371312af6a12 100644 --- a/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr +++ b/tests/ui/raw-ref-op/missing-modifier/return-expr.stderr @@ -3,6 +3,13 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found | LL | &raw foo::A | ^^^ expected one of 8 possible tokens + | +help: you might have meant to use a raw reference + | +LL | &raw mut foo::A + | +++ +LL | &raw const foo::A + | +++++ error: aborting due to 1 previous error