diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-06-14 12:56:49 +0000 |
|---|---|---|
| committer | lrh2000 <lrh2000@pku.edu.cn> | 2021-06-26 23:11:04 +0800 |
| commit | d837c00d1008c2ab13bf80117b81f5e482fc9edb (patch) | |
| tree | f17ee6f36f349b76ad8b54e360812a392604b01d | |
| parent | 40fb2e97053e2655016688264ff19160741c1dbb (diff) | |
| download | rust-d837c00d1008c2ab13bf80117b81f5e482fc9edb.tar.gz rust-d837c00d1008c2ab13bf80117b81f5e482fc9edb.zip | |
Add migration lint for reserved prefixes.
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/mod.rs | 23 |
4 files changed, 63 insertions, 7 deletions
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 2dc04d57d1e..933f7e47c3e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -723,6 +723,15 @@ pub trait LintContext: Sized { BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => { db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable); } + BuiltinLintDiagnostics::ReservedPrefix(span) => { + db.span_label(span, "unknown prefix"); + db.span_suggestion_verbose( + span.shrink_to_hi(), + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + " ".into(), + Applicability::MachineApplicable, + ); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 53970b485ee..ba8a8c3d8c9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2973,6 +2973,7 @@ declare_lint_pass! { OR_PATTERNS_BACK_COMPAT, LARGE_ASSIGNMENTS, FUTURE_PRELUDE_COLLISION, + RESERVED_PREFIX, ] } @@ -3263,3 +3264,39 @@ declare_lint! { reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), }; } + +declare_lint! { + /// The `reserved_prefix` lint detects identifiers that will be parsed as a + /// prefix instead in Rust 2021. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(reserved_prefix)] + /// + /// macro_rules! m { + /// (z $x:expr) => (); + /// } + /// + /// m!(z"hey"); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In Rust 2015 and 2018, `z"hey"` is two tokens: the identifier `z` + /// followed by the string literal `"hey"`. In Rust 2021, the `z` is + /// considered a prefix for `"hey"`. + /// + /// This lint suggests to add whitespace between the `z` and `"hey"` tokens + /// to keep them separated in Rust 2021. + pub RESERVED_PREFIX, + Allow, + "identifiers that will be parsed as a prefix in Rust 2021", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #84978 <https://github.com/rust-lang/rust/issues/84978>", + edition: Some(Edition::Edition2021), + }; + crate_level_only +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index b3d98747dcf..3372bc716d2 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -300,6 +300,7 @@ pub enum BuiltinLintDiagnostics { ExternDepSpec(String, ExternDepSpec), ProcMacroBackCompat(String), OrPatternsBackCompat(Span, String), + ReservedPrefix(Span), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f5eba5056ea..f50e8a8db01 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,9 +1,11 @@ -use rustc_ast::ast::AttrStyle; +use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; +use rustc_session::lint::builtin::RESERVED_PREFIX; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; @@ -498,17 +500,24 @@ impl<'a> StringReader<'a> { FatalError.raise() } + // See RFC 3101. fn report_reserved_prefix(&self, start: BytePos) { - // See RFC 3101. + let prefix_span = self.mk_sp(start, self.pos); + let msg = format!("prefix `{}` is unknown", self.str_from_to(start, self.pos)); + if self.sess.edition < Edition::Edition2021 { + self.sess.buffer_lint_with_diagnostic( + &RESERVED_PREFIX, + prefix_span, + ast::CRATE_NODE_ID, + &msg, + BuiltinLintDiagnostics::ReservedPrefix(prefix_span), + ); return; } - let mut err = self.sess.span_diagnostic.struct_span_err( - self.mk_sp(start, self.pos), - &format!("prefix `{}` is unknown", self.str_from_to(start, self.pos)), - ); - err.span_label(self.mk_sp(start, self.pos), "unknown prefix"); + let mut err = self.sess.span_diagnostic.struct_span_err(prefix_span, &msg); + err.span_label(prefix_span, "unknown prefix"); err.span_suggestion_verbose( self.mk_sp(self.pos, self.pos), "consider inserting whitespace here", |
