Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d837c00

Browse files
m-ou-selrh2000
authored andcommitted
Add migration lint for reserved prefixes.
1 parent 40fb2e9 commit d837c00

File tree

4 files changed

+63
-7
lines changed

4 files changed

+63
-7
lines changed

compiler/rustc_lint/src/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,15 @@ pub trait LintContext: Sized {
723723
BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => {
724724
db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable);
725725
}
726+
BuiltinLintDiagnostics::ReservedPrefix(span) => {
727+
db.span_label(span, "unknown prefix");
728+
db.span_suggestion_verbose(
729+
span.shrink_to_hi(),
730+
"insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
731+
" ".into(),
732+
Applicability::MachineApplicable,
733+
);
734+
}
726735
}
727736
// Rewrap `db`, and pass control to the user.
728737
decorate(LintDiagnosticBuilder::new(db));

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,6 +2973,7 @@ declare_lint_pass! {
29732973
OR_PATTERNS_BACK_COMPAT,
29742974
LARGE_ASSIGNMENTS,
29752975
FUTURE_PRELUDE_COLLISION,
2976+
RESERVED_PREFIX,
29762977
]
29772978
}
29782979

@@ -3263,3 +3264,39 @@ declare_lint! {
32633264
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
32643265
};
32653266
}
3267+
3268+
declare_lint! {
3269+
/// The `reserved_prefix` lint detects identifiers that will be parsed as a
3270+
/// prefix instead in Rust 2021.
3271+
///
3272+
/// ### Example
3273+
///
3274+
/// ```rust,compile_fail
3275+
/// #![deny(reserved_prefix)]
3276+
///
3277+
/// macro_rules! m {
3278+
/// (z $x:expr) => ();
3279+
/// }
3280+
///
3281+
/// m!(z"hey");
3282+
/// ```
3283+
///
3284+
/// {{produces}}
3285+
///
3286+
/// ### Explanation
3287+
///
3288+
/// In Rust 2015 and 2018, `z"hey"` is two tokens: the identifier `z`
3289+
/// followed by the string literal `"hey"`. In Rust 2021, the `z` is
3290+
/// considered a prefix for `"hey"`.
3291+
///
3292+
/// This lint suggests to add whitespace between the `z` and `"hey"` tokens
3293+
/// to keep them separated in Rust 2021.
3294+
pub RESERVED_PREFIX,
3295+
Allow,
3296+
"identifiers that will be parsed as a prefix in Rust 2021",
3297+
@future_incompatible = FutureIncompatibleInfo {
3298+
reference: "issue #84978 <https://github.com/rust-lang/rust/issues/84978>",
3299+
edition: Some(Edition::Edition2021),
3300+
};
3301+
crate_level_only
3302+
}

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ pub enum BuiltinLintDiagnostics {
300300
ExternDepSpec(String, ExternDepSpec),
301301
ProcMacroBackCompat(String),
302302
OrPatternsBackCompat(Span, String),
303+
ReservedPrefix(Span),
303304
}
304305

305306
/// Lints that are buffered up early on in the `Session` before the

compiler/rustc_parse/src/lexer/mod.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use rustc_ast::ast::AttrStyle;
1+
use rustc_ast::ast::{self, AttrStyle};
22
use rustc_ast::token::{self, CommentKind, Token, TokenKind};
33
use rustc_ast::tokenstream::{Spacing, TokenStream};
44
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
55
use rustc_lexer::unescape::{self, Mode};
66
use rustc_lexer::{Base, DocStyle, RawStrError};
7+
use rustc_session::lint::builtin::RESERVED_PREFIX;
8+
use rustc_session::lint::BuiltinLintDiagnostics;
79
use rustc_session::parse::ParseSess;
810
use rustc_span::edition::Edition;
911
use rustc_span::symbol::{sym, Symbol};
@@ -498,17 +500,24 @@ impl<'a> StringReader<'a> {
498500
FatalError.raise()
499501
}
500502

503+
// See RFC 3101.
501504
fn report_reserved_prefix(&self, start: BytePos) {
502-
// See RFC 3101.
505+
let prefix_span = self.mk_sp(start, self.pos);
506+
let msg = format!("prefix `{}` is unknown", self.str_from_to(start, self.pos));
507+
503508
if self.sess.edition < Edition::Edition2021 {
509+
self.sess.buffer_lint_with_diagnostic(
510+
&RESERVED_PREFIX,
511+
prefix_span,
512+
ast::CRATE_NODE_ID,
513+
&msg,
514+
BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
515+
);
504516
return;
505517
}
506518

507-
let mut err = self.sess.span_diagnostic.struct_span_err(
508-
self.mk_sp(start, self.pos),
509-
&format!("prefix `{}` is unknown", self.str_from_to(start, self.pos)),
510-
);
511-
err.span_label(self.mk_sp(start, self.pos), "unknown prefix");
519+
let mut err = self.sess.span_diagnostic.struct_span_err(prefix_span, &msg);
520+
err.span_label(prefix_span, "unknown prefix");
512521
err.span_suggestion_verbose(
513522
self.mk_sp(self.pos, self.pos),
514523
"consider inserting whitespace here",

0 commit comments

Comments
 (0)