From aa8ecd0652afbecd6549d2f6e53c0a5f6aa76d8f Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 26 Dec 2023 18:34:44 -0800 Subject: Suggest quoting unquoted idents in attrs --- compiler/rustc_parse/src/parser/attr.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 02dab95233a..a92609c2c2f 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,4 +1,7 @@ -use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute}; +use crate::errors::{ + InvalidMetaItem, InvalidMetaItemSuggQuoteIdent, InvalidMetaItemUnquotedIdent, + SuffixedLiteralInAttribute, +}; use crate::fluent_generated as fluent; use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; @@ -417,9 +420,26 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(self - .dcx() - .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) + let token = self.token.clone(); + + // Check for unquoted idents in meta items, e.g.: #[cfg(key = foo)] + // `from_expansion()` ensures we don't suggest for cases such as + // `#[cfg(feature = $expr)]` in macros + if self.prev_token == token::Eq && !self.token.span.from_expansion() { + let before = self.token.span.shrink_to_lo(); + while matches!(self.token.kind, token::Ident(..)) { + self.bump(); + } + let after = self.prev_token.span.shrink_to_hi(); + let sugg = InvalidMetaItemSuggQuoteIdent { before, after }; + return Err(self.dcx().create_err(InvalidMetaItemUnquotedIdent { + span: token.span, + token, + sugg, + })); + } + + Err(self.dcx().create_err(InvalidMetaItem { span: token.span, token })) } } -- cgit 1.4.1-3-g733a5 From b9ebeee4da258f1ed8bb93f0273180572a839058 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 17 Jan 2024 21:16:22 +0000 Subject: Remove `box ` recovery --- compiler/rustc_parse/src/parser/expr.rs | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342..a1e4fc7876d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::source_map::{self, Spanned}; -use rustc_span::symbol::kw::PathRoot; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -642,26 +641,13 @@ impl<'a> Parser<'a> { } /// Parse `box expr` - this syntax has been removed, but we still parse this - /// for now to provide an automated way to fix usages of it - fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - let (span, expr) = self.parse_expr_prefix_common(lo)?; - let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap(); - self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() }); - // So typechecking works, parse `box ` as `::std::boxed::Box::new(expr)` - let path = Path { - span, - segments: [ - PathSegment::from_ident(Ident::with_dummy_span(PathRoot)), - PathSegment::from_ident(Ident::with_dummy_span(sym::std)), - PathSegment::from_ident(Ident::from_str("boxed")), - PathSegment::from_ident(Ident::from_str("Box")), - PathSegment::from_ident(Ident::with_dummy_span(sym::new)), - ] - .into(), - tokens: None, - }; - let path = self.mk_expr(span, ExprKind::Path(None, path)); - Ok((span, self.mk_call(path, ThinVec::from([expr])))) + /// for now to provide a more useful error + fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> { + let (span, _) = self.parse_expr_prefix_common(box_kw)?; + let inner_span = span.with_lo(box_kw.hi()); + let code = self.sess.source_map().span_to_snippet(inner_span).unwrap(); + self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() }); + Ok((span, ExprKind::Err)) } fn is_mistaken_not_ident_negation(&self) -> bool { -- cgit 1.4.1-3-g733a5 From ec263df5e440598159f19a42c104c3b5f13888a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 03:01:05 +0000 Subject: Suggest wrapping mac args in parens rather than the whole expression --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 37 ++++++++++++++++++--------- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 15 ++++++++--- tests/ui/parser/bad-let-else-statement.stderr | 12 ++++----- 5 files changed, 45 insertions(+), 23 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index d515e86a182..e3ecd24b6a5 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -722,6 +722,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses +parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro + parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses parse_switch_mut_let_order = diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 34b34a1bad6..8f57b2eb5aa 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: WrapExpressionInParentheses, + pub sub: WrapInParentheses, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, - applicability = "machine-applicable" -)] -pub(crate) struct WrapExpressionInParentheses { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, + +pub(crate) enum WrapInParentheses { + #[multipart_suggestion( + parse_sugg_wrap_expression_in_parentheses, + applicability = "machine-applicable" + )] + Expression { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + parse_sugg_wrap_macro_in_parentheses, + applicability = "machine-applicable" + )] + MacroArgs { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, } #[derive(Diagnostic)] @@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse { pub span: Span, pub operator: &'static str, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] @@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342..f858706805d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1844,7 +1844,7 @@ impl<'a> Parser<'a> { let lexpr = self.parse_expr_labeled(label, true)?; self.dcx().emit_err(errors::LabeledLoopInBreak { span: lexpr.span, - sub: errors::WrapExpressionInParentheses { + sub: errors::WrapInParentheses::Expression { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1a8bbf0a157..1bae5b32240 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -389,7 +389,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.as_str(), - sugg: errors::WrapExpressionInParentheses { + sugg: errors::WrapInParentheses::Expression { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), }, @@ -400,12 +400,19 @@ impl<'a> Parser<'a> { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - self.dcx().emit_err(errors::InvalidCurlyInLetElse { - span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), - sugg: errors::WrapExpressionInParentheses { + let sugg = match &trailing.kind { + ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs { + left: mac.args.dspan.open, + right: mac.args.dspan.close, + }, + _ => errors::WrapInParentheses::Expression { left: trailing.span.shrink_to_lo(), right: trailing.span.shrink_to_hi(), }, + }; + self.dcx().emit_err(errors::InvalidCurlyInLetElse { + span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), + sugg, }); } } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 4ea924ddcb8..887455913d8 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -234,10 +234,10 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let bad = format_args! {""} else { return; }; | ^ | -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let bad = (format_args! {""}) else { return; }; - | + + +LL | let bad = format_args! ("") else { return; }; + | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:181:25 @@ -249,10 +249,10 @@ LL | b!(1); b!(2); | ----- in this macro invocation | = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let x = (a! {}) else { return; }; - | + + +LL | let x = a! () else { return; }; + | ~~ error: aborting due to 19 previous errors -- cgit 1.4.1-3-g733a5