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));
OR_PATTERNS_BACK_COMPAT,
LARGE_ASSIGNMENTS,
FUTURE_PRELUDE_COLLISION,
+ RESERVED_PREFIX,
]
}
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
+}
-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};
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",