-
Notifications
You must be signed in to change notification settings - Fork 13.4k
migration lint for expr2024
for the edition 2024
#125627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bors
merged 2 commits into
rust-lang:master
from
vincenzopalazzo:macros/cargo-fix-expr2024
Jul 10, 2024
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
//! Migration code for the `expr_fragment_specifier_2024` | ||
//! rule. | ||
use tracing::debug; | ||
|
||
use rustc_ast::token::Token; | ||
use rustc_ast::token::TokenKind; | ||
use rustc_ast::tokenstream::TokenStream; | ||
use rustc_ast::tokenstream::TokenTree; | ||
use rustc_session::declare_lint; | ||
use rustc_session::declare_lint_pass; | ||
use rustc_session::lint::FutureIncompatibilityReason; | ||
use rustc_span::edition::Edition; | ||
use rustc_span::sym; | ||
|
||
use crate::lints::MacroExprFragment2024; | ||
use crate::EarlyLintPass; | ||
|
||
declare_lint! { | ||
/// The `edition_2024_expr_fragment_specifier` lint detects the use of | ||
/// `expr` fragments in macros during migration to the 2024 edition. | ||
/// | ||
/// The `expr` fragment specifier will accept more expressions in the 2024 | ||
/// edition. To maintain the behavior from the 2021 edition and earlier, use | ||
/// the `expr_2021` fragment specifier. | ||
/// | ||
/// ### Example | ||
/// | ||
/// ```rust,edition2021,compile_fail | ||
/// #![deny(edition_2024_expr_fragment_specifier)] | ||
/// macro_rules! m { | ||
/// ($e:expr) => { | ||
/// $e | ||
/// } | ||
/// } | ||
/// | ||
/// fn main() { | ||
/// m!(1); | ||
/// } | ||
/// ``` | ||
/// | ||
/// {{produces}} | ||
/// | ||
/// ### Explanation | ||
/// | ||
/// Rust [editions] allow the language to evolve without breaking backwards | ||
/// compatibility. This lint catches code that uses [macro matcher fragment | ||
/// specifiers] that have changed meaning in the 2024 edition. If you switch | ||
/// to the new edition without updating the code, your macros may behave | ||
/// differently. | ||
/// | ||
/// In the 2024 edition, the `expr` fragment specifier `expr` will also | ||
/// match `const { ... }` blocks. This means if a macro had a pattern that | ||
/// matched `$e:expr` and another that matches `const { $e: expr }`, for | ||
/// example, that under the 2024 edition the first pattern would match while | ||
/// in the 2021 and earlier editions the second pattern would match. To keep | ||
/// the old behavior, use the `expr_2021` fragment specifier. | ||
/// | ||
/// This lint detects macros whose behavior might change due to the changing | ||
/// meaning of the `expr` fragment specifier. 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. This provides a | ||
/// completely automated way to update old code for a new edition. | ||
/// | ||
/// Using `cargo fix --edition` with this lint will ensure that your code | ||
/// retains the same behavior. This may not be the desired, as macro authors | ||
/// often will want their macros to use the latest grammar for matching | ||
/// expressions. Be sure to carefully review changes introduced by this lint | ||
/// to ensure the macros implement the desired behavior. | ||
/// | ||
/// [editions]: https://doc.rust-lang.org/edition-guide/ | ||
/// [macro matcher fragment specifiers]: https://doc.rust-lang.org/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html | ||
/// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html | ||
pub EDITION_2024_EXPR_FRAGMENT_SPECIFIER, | ||
Allow, | ||
"The `expr` fragment specifier will accept more expressions in the 2024 edition. \ | ||
To keep the existing behavior, use the `expr_2021` fragment specifier.", | ||
@future_incompatible = FutureIncompatibleInfo { | ||
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), | ||
reference: "Migration Guide <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html>", | ||
}; | ||
} | ||
|
||
declare_lint_pass!(Expr2024 => [EDITION_2024_EXPR_FRAGMENT_SPECIFIER,]); | ||
|
||
impl Expr2024 { | ||
fn check_tokens(&mut self, cx: &crate::EarlyContext<'_>, tokens: &TokenStream) { | ||
let mut prev_colon = false; | ||
let mut prev_identifier = false; | ||
let mut prev_dollar = false; | ||
for tt in tokens.trees() { | ||
debug!( | ||
"check_tokens: {:?} - colon {prev_dollar} - ident {prev_identifier} - colon {prev_colon}", | ||
tt | ||
); | ||
match tt { | ||
TokenTree::Token(token, _) => match token.kind { | ||
TokenKind::Dollar => { | ||
prev_dollar = true; | ||
continue; | ||
} | ||
TokenKind::Ident(..) | TokenKind::NtIdent(..) => { | ||
if prev_colon && prev_identifier && prev_dollar { | ||
self.check_ident_token(cx, token); | ||
} else if prev_dollar { | ||
prev_identifier = true; | ||
continue; | ||
} | ||
} | ||
TokenKind::Colon => { | ||
if prev_dollar && prev_identifier { | ||
prev_colon = true; | ||
continue; | ||
} | ||
} | ||
_ => {} | ||
}, | ||
TokenTree::Delimited(.., tts) => self.check_tokens(cx, tts), | ||
} | ||
prev_colon = false; | ||
prev_identifier = false; | ||
prev_dollar = false; | ||
} | ||
} | ||
|
||
fn check_ident_token(&mut self, cx: &crate::EarlyContext<'_>, token: &Token) { | ||
debug!("check_ident_token: {:?}", token); | ||
let (sym, edition) = match token.kind { | ||
TokenKind::Ident(sym, _) => (sym, Edition::Edition2024), | ||
_ => return, | ||
}; | ||
|
||
debug!("token.span.edition(): {:?}", token.span.edition()); | ||
if token.span.edition() >= edition { | ||
return; | ||
} | ||
|
||
if sym != sym::expr { | ||
return; | ||
} | ||
|
||
debug!("emitting lint"); | ||
cx.builder.emit_span_lint( | ||
&EDITION_2024_EXPR_FRAGMENT_SPECIFIER, | ||
token.span.into(), | ||
MacroExprFragment2024 { suggestion: token.span }, | ||
); | ||
} | ||
} | ||
|
||
impl EarlyLintPass for Expr2024 { | ||
fn check_mac_def(&mut self, cx: &crate::EarlyContext<'_>, mc: &rustc_ast::MacroDef) { | ||
self.check_tokens(cx, &mc.body.tokens); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//@ run-rustfix | ||
//@ check-pass | ||
//@ compile-flags: --edition=2021 | ||
#![allow(incomplete_features)] | ||
#![feature(expr_fragment_specifier_2024)] | ||
#![warn(edition_2024_expr_fragment_specifier)] | ||
|
||
macro_rules! m { | ||
($e:expr_2021) => { //~ WARN: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
//~^ WARN: this changes meaning in Rust 2024 | ||
$e | ||
}; | ||
($($i:expr_2021)*) => { }; //~ WARN: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
//~^ WARN: this changes meaning in Rust 2024 | ||
} | ||
|
||
macro_rules! test { | ||
(expr) => {} | ||
} | ||
|
||
fn main() { | ||
m!(()); | ||
test!(expr); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//@ run-rustfix | ||
//@ check-pass | ||
//@ compile-flags: --edition=2021 | ||
#![allow(incomplete_features)] | ||
#![feature(expr_fragment_specifier_2024)] | ||
#![warn(edition_2024_expr_fragment_specifier)] | ||
|
||
macro_rules! m { | ||
($e:expr) => { //~ WARN: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
//~^ WARN: this changes meaning in Rust 2024 | ||
$e | ||
}; | ||
($($i:expr)*) => { }; //~ WARN: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
//~^ WARN: this changes meaning in Rust 2024 | ||
} | ||
|
||
macro_rules! test { | ||
(expr) => {} | ||
} | ||
|
||
fn main() { | ||
m!(()); | ||
test!(expr); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
warning: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
--> $DIR/expr_2021_cargo_fix_edition.rs:9:9 | ||
| | ||
LL | ($e:expr) => { | ||
| ^^^^ | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see Migration Guide <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html> | ||
note: the lint level is defined here | ||
--> $DIR/expr_2021_cargo_fix_edition.rs:6:9 | ||
| | ||
LL | #![warn(edition_2024_expr_fragment_specifier)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
help: to keep the existing behavior, use the `expr_2021` fragment specifier | ||
| | ||
LL | ($e:expr_2021) => { | ||
| ~~~~~~~~~ | ||
|
||
warning: the `expr` fragment specifier will accept more expressions in the 2024 edition | ||
--> $DIR/expr_2021_cargo_fix_edition.rs:13:11 | ||
| | ||
LL | ($($i:expr)*) => { }; | ||
| ^^^^ | ||
| | ||
= warning: this changes meaning in Rust 2024 | ||
= note: for more information, see Migration Guide <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html> | ||
help: to keep the existing behavior, use the `expr_2021` fragment specifier | ||
| | ||
LL | ($($i:expr_2021)*) => { }; | ||
| ~~~~~~~~~ | ||
|
||
warning: 2 warnings emitted | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.