mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Deny gen keyword in edition_2024_compat lints
This commit is contained in:
parent
7f2fc33da6
commit
7789874e6e
@ -1769,13 +1769,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `keyword_idents` lint detects edition keywords being used as an
|
||||
/// The `keyword_idents_2018` lint detects edition keywords being used as an
|
||||
/// identifier.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,edition2015,compile_fail
|
||||
/// #![deny(keyword_idents)]
|
||||
/// #![deny(keyword_idents_2018)]
|
||||
/// // edition 2015
|
||||
/// fn dyn() {}
|
||||
/// ```
|
||||
@ -1804,7 +1804,7 @@ declare_lint! {
|
||||
/// [editions]: https://doc.rust-lang.org/edition-guide/
|
||||
/// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
|
||||
/// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
|
||||
pub KEYWORD_IDENTS,
|
||||
pub KEYWORD_IDENTS_2018,
|
||||
Allow,
|
||||
"detects edition keywords being used as an identifier",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
@ -1813,9 +1813,54 @@ declare_lint! {
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `keyword_idents_2024` lint detects edition keywords being used as an
|
||||
/// identifier.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,edition2015,compile_fail
|
||||
/// #![deny(keyword_idents_2024)]
|
||||
/// // edition 2015
|
||||
/// fn gen() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Rust [editions] allow the language to evolve without breaking
|
||||
/// backwards compatibility. This lint catches code that uses new keywords
|
||||
/// that are added to the language that are used as identifiers (such as a
|
||||
/// variable name, function name, etc.). If you switch the compiler to a
|
||||
/// new edition without updating the code, then it will fail to compile if
|
||||
/// you are using a new keyword as an identifier.
|
||||
///
|
||||
/// You can manually change the identifiers to a non-keyword, or use a
|
||||
/// [raw identifier], for example `r#gen`, to transition to a new edition.
|
||||
///
|
||||
/// This lint solves the problem automatically. It is "allow" by default
|
||||
/// because the code is perfectly valid in older editions. The [`cargo
|
||||
/// fix`] tool with the `--edition` flag will switch this lint to "warn"
|
||||
/// and automatically apply the suggested fix from the compiler (which is
|
||||
/// to use a raw identifier). This provides a completely automated way to
|
||||
/// update old code for a new edition.
|
||||
///
|
||||
/// [editions]: https://doc.rust-lang.org/edition-guide/
|
||||
/// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
|
||||
/// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
|
||||
pub KEYWORD_IDENTS_2024,
|
||||
Allow,
|
||||
"detects edition keywords being used as an identifier",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
|
||||
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
/// Check for uses of edition keywords used as an identifier.
|
||||
KeywordIdents => [KEYWORD_IDENTS]
|
||||
KeywordIdents => [KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024]
|
||||
);
|
||||
|
||||
struct UnderMacro(bool);
|
||||
@ -1841,42 +1886,39 @@ impl KeywordIdents {
|
||||
UnderMacro(under_macro): UnderMacro,
|
||||
ident: Ident,
|
||||
) {
|
||||
let next_edition = match cx.sess().edition() {
|
||||
Edition::Edition2015 => {
|
||||
match ident.name {
|
||||
kw::Async | kw::Await | kw::Try => Edition::Edition2018,
|
||||
let (lint, edition) = match ident.name {
|
||||
kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),
|
||||
|
||||
// rust-lang/rust#56327: Conservatively do not
|
||||
// attempt to report occurrences of `dyn` within
|
||||
// macro definitions or invocations, because `dyn`
|
||||
// can legitimately occur as a contextual keyword
|
||||
// in 2015 code denoting its 2018 meaning, and we
|
||||
// do not want rustfix to inject bugs into working
|
||||
// code by rewriting such occurrences.
|
||||
//
|
||||
// But if we see `dyn` outside of a macro, we know
|
||||
// its precise role in the parsed AST and thus are
|
||||
// assured this is truly an attempt to use it as
|
||||
// an identifier.
|
||||
kw::Dyn if !under_macro => Edition::Edition2018,
|
||||
// rust-lang/rust#56327: Conservatively do not
|
||||
// attempt to report occurrences of `dyn` within
|
||||
// macro definitions or invocations, because `dyn`
|
||||
// can legitimately occur as a contextual keyword
|
||||
// in 2015 code denoting its 2018 meaning, and we
|
||||
// do not want rustfix to inject bugs into working
|
||||
// code by rewriting such occurrences.
|
||||
//
|
||||
// But if we see `dyn` outside of a macro, we know
|
||||
// its precise role in the parsed AST and thus are
|
||||
// assured this is truly an attempt to use it as
|
||||
// an identifier.
|
||||
kw::Dyn if !under_macro => (KEYWORD_IDENTS_2018, Edition::Edition2018),
|
||||
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
kw::Gen => (KEYWORD_IDENTS_2024, Edition::Edition2024),
|
||||
|
||||
// There are no new keywords yet for the 2018 edition and beyond.
|
||||
_ => return,
|
||||
};
|
||||
|
||||
// Don't lint `r#foo`.
|
||||
if cx.sess().psess.raw_identifier_spans.contains(ident.span) {
|
||||
if ident.span.edition() >= edition
|
||||
|| cx.sess().psess.raw_identifier_spans.contains(ident.span)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cx.emit_span_lint(
|
||||
KEYWORD_IDENTS,
|
||||
lint,
|
||||
ident.span,
|
||||
BuiltinKeywordIdents { kw: ident, next: next_edition, suggestion: ident.span },
|
||||
BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -313,6 +313,8 @@ fn register_builtins(store: &mut LintStore) {
|
||||
// MACRO_USE_EXTERN_CRATE
|
||||
);
|
||||
|
||||
add_lint_group!("keyword_idents", KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024);
|
||||
|
||||
add_lint_group!(
|
||||
"refining_impl_trait",
|
||||
REFINING_IMPL_TRAIT_REACHABLE,
|
||||
@ -325,7 +327,7 @@ fn register_builtins(store: &mut LintStore) {
|
||||
store.register_renamed("bare_trait_object", "bare_trait_objects");
|
||||
store.register_renamed("unstable_name_collision", "unstable_name_collisions");
|
||||
store.register_renamed("unused_doc_comment", "unused_doc_comments");
|
||||
store.register_renamed("async_idents", "keyword_idents");
|
||||
store.register_renamed("async_idents", "keyword_idents_2018");
|
||||
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
|
||||
store.register_renamed("redundant_semicolon", "redundant_semicolons");
|
||||
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
|
||||
|
@ -20,6 +20,10 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
|
||||
"refining-impl-trait",
|
||||
"Detects refinement of `impl Trait` return types by trait implementations",
|
||||
),
|
||||
(
|
||||
"keyword-idents",
|
||||
"Lints that detect identifiers which will be come keywords in later editions",
|
||||
),
|
||||
];
|
||||
|
||||
type LintGroups = BTreeMap<String, BTreeSet<String>>;
|
||||
|
@ -25,6 +25,7 @@ static RENAMES: &[(Level, &[(&str, &str)])] = &[
|
||||
("elided-lifetime-in-path", "elided-lifetimes-in-paths"),
|
||||
("async-idents", "keyword-idents"),
|
||||
("disjoint-capture-migration", "rust-2021-incompatible-closure-captures"),
|
||||
("keyword-idents", "keyword-idents-2018"),
|
||||
("or-patterns-back-compat", "rust-2021-incompatible-or-patterns"),
|
||||
],
|
||||
),
|
||||
|
@ -11,6 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: `await` is a keyword in the 2018 edition
|
||||
--> $DIR/2015-edition-error-various-positions.rs:7:20
|
||||
|
@ -11,6 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: `await` is a keyword in the 2018 edition
|
||||
--> $DIR/2015-edition-warning.rs:10:20
|
||||
|
@ -11,6 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: `dyn` is a keyword in the 2018 edition
|
||||
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20
|
||||
|
@ -6,8 +6,8 @@ LL | pub fn try() {}
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
|
||||
= note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
|
||||
= help: to override `-W rust-2018-compatibility` add `#[allow(keyword_idents)]`
|
||||
= note: `-W keyword-idents-2018` implied by `-W rust-2018-compatibility`
|
||||
= help: to override `-W rust-2018-compatibility` add `#[allow(keyword_idents_2018)]`
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -11,7 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(rust_2018_compatibility)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]`
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(rust_2018_compatibility)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -11,6 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: `async` is a keyword in the 2018 edition
|
||||
--> $DIR/async-ident.rs:12:7
|
||||
|
@ -11,6 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -11,7 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![warn(rust_2018_compatibility)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
|
||||
= note: `#[warn(keyword_idents_2018)]` implied by `#[warn(rust_2018_compatibility)]`
|
||||
|
||||
warning: `try` is a keyword in the 2018 edition
|
||||
--> $DIR/try-ident.rs:12:4
|
||||
|
@ -11,7 +11,7 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![warn(rust_2018_compatibility)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
|
||||
= note: `#[warn(keyword_idents_2018)]` implied by `#[warn(rust_2018_compatibility)]`
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
26
tests/ui/rust-2024/gen-kw.e2015.stderr
Normal file
26
tests/ui/rust-2024/gen-kw.e2015.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: `gen` is a keyword in the 2024 edition
|
||||
--> $DIR/gen-kw.rs:6:4
|
||||
|
|
||||
LL | fn gen() {}
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/gen-kw.rs:4:9
|
||||
|
|
||||
LL | #![deny(rust_2024_compatibility)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2024)]` implied by `#[deny(rust_2024_compatibility)]`
|
||||
|
||||
error: `gen` is a keyword in the 2024 edition
|
||||
--> $DIR/gen-kw.rs:12:9
|
||||
|
|
||||
LL | let gen = r#gen;
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
26
tests/ui/rust-2024/gen-kw.e2018.stderr
Normal file
26
tests/ui/rust-2024/gen-kw.e2018.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: `gen` is a keyword in the 2024 edition
|
||||
--> $DIR/gen-kw.rs:6:4
|
||||
|
|
||||
LL | fn gen() {}
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
|
||||
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/gen-kw.rs:4:9
|
||||
|
|
||||
LL | #![deny(rust_2024_compatibility)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2024)]` implied by `#[deny(rust_2024_compatibility)]`
|
||||
|
||||
error: `gen` is a keyword in the 2024 edition
|
||||
--> $DIR/gen-kw.rs:12:9
|
||||
|
|
||||
LL | let gen = r#gen;
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
|
||||
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
16
tests/ui/rust-2024/gen-kw.rs
Normal file
16
tests/ui/rust-2024/gen-kw.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ revisions: e2015 e2018
|
||||
//@[e2018] edition: 2018
|
||||
|
||||
#![deny(rust_2024_compatibility)]
|
||||
|
||||
fn gen() {}
|
||||
//~^ ERROR `gen` is a keyword in the 2024 edition
|
||||
//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
|
||||
|
||||
fn main() {
|
||||
let gen = r#gen;
|
||||
//~^ ERROR `gen` is a keyword in the 2024 edition
|
||||
//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
|
||||
}
|
Loading…
Reference in New Issue
Block a user