coalesce lint suggestions that can intersect

This commit is contained in:
Ding Xiang Fei 2024-09-06 03:03:10 +08:00
parent f93df1f7dc
commit e2120a7c38
No known key found for this signature in database
GPG Key ID: 3CD748647EEF6359
8 changed files with 572 additions and 161 deletions

View File

@ -337,7 +337,9 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024
.label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
.help = the value is now dropped here in Edition 2024 .help = the value is now dropped here in Edition 2024
.suggestion = rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021
lint_if_let_rescope_suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021
.suggestion = rewrite this `if let` into `match`
lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level

View File

@ -1,11 +1,16 @@
use std::iter::repeat;
use std::ops::ControlFlow; use std::ops::ControlFlow;
use hir::intravisit::Visitor; use hir::intravisit::Visitor;
use rustc_ast::Recovered; use rustc_ast::Recovered;
use rustc_hir as hir; use rustc_errors::{
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
};
use rustc_hir::{self as hir, HirIdSet};
use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_session::lint::FutureIncompatibilityReason; use rustc_middle::ty::TyCtxt;
use rustc_session::{declare_lint, declare_lint_pass}; use rustc_session::lint::{FutureIncompatibilityReason, Level};
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::Span; use rustc_span::Span;
@ -84,17 +89,49 @@
}; };
} }
declare_lint_pass!(
/// Lint for potential change in program semantics of `if let`s /// Lint for potential change in program semantics of `if let`s
IfLetRescope => [IF_LET_RESCOPE] #[derive(Default)]
); pub(crate) struct IfLetRescope {
skip: HirIdSet,
}
impl<'tcx> LateLintPass<'tcx> for IfLetRescope { fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(hir_id).next() else {
if !expr.span.edition().at_least_rust_2021() || !cx.tcx.features().if_let_rescope { return false;
};
let hir::ExprKind::If(_cond, _conseq, Some(alt)) = expr.kind else { return false };
alt.hir_id == hir_id
}
fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else {
return false;
};
let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false };
expr.hir_id == hir_id
}
fn match_head_needs_bracket(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> bool {
expr_parent_is_else(tcx, expr.hir_id) && matches!(expr.kind, hir::ExprKind::If(..))
}
impl IfLetRescope {
fn probe_if_cascade<'tcx>(&mut self, cx: &LateContext<'tcx>, mut expr: &'tcx hir::Expr<'tcx>) {
if self.skip.contains(&expr.hir_id) {
return; return;
} }
let hir::ExprKind::If(cond, conseq, alt) = expr.kind else { return }; let tcx = cx.tcx;
let source_map = tcx.sess.source_map();
let expr_end = expr.span.shrink_to_hi();
let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr);
let mut closing_brackets = 0;
let mut alt_heads = vec![];
let mut match_heads = vec![];
let mut consequent_heads = vec![];
let mut first_if_to_rewrite = None;
let mut empty_alt = false;
while let hir::ExprKind::If(cond, conseq, alt) = expr.kind {
self.skip.insert(expr.hir_id);
let hir::ExprKind::Let(&hir::LetExpr { let hir::ExprKind::Let(&hir::LetExpr {
span, span,
pat, pat,
@ -103,25 +140,29 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
recovered: Recovered::No, recovered: Recovered::No,
}) = cond.kind }) = cond.kind
else { else {
return; if let Some(alt) = alt {
add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..));
expr = alt;
continue;
} else {
// finalize and emit span
break;
}
}; };
let source_map = cx.tcx.sess.source_map();
let expr_end = expr.span.shrink_to_hi();
let if_let_pat = expr.span.shrink_to_lo().between(init.span); let if_let_pat = expr.span.shrink_to_lo().between(init.span);
// the consequent fragment is always a block
let before_conseq = conseq.span.shrink_to_lo(); let before_conseq = conseq.span.shrink_to_lo();
let lifetime_end = source_map.end_point(conseq.span); let lifetime_end = source_map.end_point(conseq.span);
if let ControlFlow::Break(significant_dropper) = if let ControlFlow::Break(significant_dropper) =
(FindSignificantDropper { cx }).visit_expr(init) (FindSignificantDropper { cx }).visit_expr(init)
{ {
let lint_without_suggestion = || { tcx.emit_node_span_lint(
cx.tcx.emit_node_span_lint(
IF_LET_RESCOPE, IF_LET_RESCOPE,
expr.hir_id, expr.hir_id,
span, span,
IfLetRescopeRewrite { significant_dropper, lifetime_end, sugg: None }, IfLetRescopeLint { significant_dropper, lifetime_end },
) );
};
if ty_ascription.is_some() if ty_ascription.is_some()
|| !expr.span.can_be_used_for_suggestions() || !expr.span.can_be_used_for_suggestions()
|| !pat.span.can_be_used_for_suggestions() || !pat.span.can_be_used_for_suggestions()
@ -131,91 +172,153 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
// Alternatively when the span comes from proc macro expansion, // Alternatively when the span comes from proc macro expansion,
// we will also bail. // we will also bail.
// FIXME(#101728): change this when type ascription syntax is stabilized again // FIXME(#101728): change this when type ascription syntax is stabilized again
lint_without_suggestion(); } else if let Ok(pat) = source_map.span_to_snippet(pat.span) {
let emit_suggestion = || {
first_if_to_rewrite =
first_if_to_rewrite.or_else(|| Some((expr.span, expr.hir_id)));
if add_bracket_to_match_head {
closing_brackets += 2;
match_heads.push(SingleArmMatchBegin::WithOpenBracket(if_let_pat));
} else { } else {
let Ok(pat) = source_map.span_to_snippet(pat.span) else { // It has to be a block
lint_without_suggestion(); closing_brackets += 1;
return; match_heads.push(SingleArmMatchBegin::WithoutOpenBracket(if_let_pat));
}
consequent_heads.push(ConsequentRewrite { span: before_conseq, pat });
}; };
if let Some(alt) = alt { if let Some(alt) = alt {
let alt_start = conseq.span.between(alt.span); let alt_head = conseq.span.between(alt.span);
if !alt_start.can_be_used_for_suggestions() { if alt_head.can_be_used_for_suggestions() {
lint_without_suggestion(); // lint
emit_suggestion();
alt_heads.push(AltHead(alt_head));
}
} else {
emit_suggestion();
empty_alt = true;
break;
}
}
}
if let Some(alt) = alt {
add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..));
expr = alt;
} else {
break;
}
}
if let Some((span, hir_id)) = first_if_to_rewrite {
tcx.emit_node_span_lint(
IF_LET_RESCOPE,
hir_id,
span,
IfLetRescopeRewrite {
match_heads,
consequent_heads,
closing_brackets: ClosingBrackets {
span: expr_end,
count: closing_brackets,
empty_alt,
},
alt_heads,
},
);
}
}
}
impl_lint_pass!(
IfLetRescope => [IF_LET_RESCOPE]
);
impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope {
return; return;
} }
cx.tcx.emit_node_span_lint( if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {
IF_LET_RESCOPE, return;
expr.hir_id,
span,
IfLetRescopeRewrite {
significant_dropper,
lifetime_end,
sugg: Some(IfLetRescopeRewriteSuggestion::WithElse {
if_let_pat,
before_conseq,
pat,
expr_end,
alt_start,
}),
},
);
} else {
cx.tcx.emit_node_span_lint(
IF_LET_RESCOPE,
expr.hir_id,
span,
IfLetRescopeRewrite {
significant_dropper,
lifetime_end,
sugg: Some(IfLetRescopeRewriteSuggestion::WithoutElse {
if_let_pat,
before_conseq,
pat,
expr_end,
}),
},
);
}
} }
if expr_parent_is_stmt(cx.tcx, expr.hir_id)
&& matches!(expr.kind, hir::ExprKind::If(_cond, _conseq, None))
{
// `if let` statement without an `else` branch has no observable change
// so we can skip linting it
return;
} }
self.probe_if_cascade(cx, expr);
} }
} }
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(lint_if_let_rescope)] #[diag(lint_if_let_rescope)]
struct IfLetRescopeRewrite { struct IfLetRescopeLint {
#[label] #[label]
significant_dropper: Span, significant_dropper: Span,
#[help] #[help]
lifetime_end: Span, lifetime_end: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_if_let_rescope_suggestion)]
struct IfLetRescopeRewrite {
#[subdiagnostic] #[subdiagnostic]
sugg: Option<IfLetRescopeRewriteSuggestion>, match_heads: Vec<SingleArmMatchBegin>,
#[subdiagnostic]
consequent_heads: Vec<ConsequentRewrite>,
#[subdiagnostic]
closing_brackets: ClosingBrackets,
#[subdiagnostic]
alt_heads: Vec<AltHead>,
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
enum IfLetRescopeRewriteSuggestion {
#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
WithElse { struct AltHead(#[suggestion_part(code = " _ => ")] Span);
#[suggestion_part(code = "match ")]
if_let_pat: Span, #[derive(Subdiagnostic)]
#[suggestion_part(code = " {{ {pat} => ")]
before_conseq: Span,
pat: String,
#[suggestion_part(code = "}}")]
expr_end: Span,
#[suggestion_part(code = " _ => ")]
alt_start: Span,
},
#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
WithoutElse { struct ConsequentRewrite {
#[suggestion_part(code = "match ")]
if_let_pat: Span,
#[suggestion_part(code = "{{ {pat} => ")] #[suggestion_part(code = "{{ {pat} => ")]
before_conseq: Span, span: Span,
pat: String, pat: String,
#[suggestion_part(code = " _ => {{}} }}")] }
expr_end: Span,
}, struct ClosingBrackets {
span: Span,
count: usize,
empty_alt: bool,
}
impl Subdiagnostic for ClosingBrackets {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
f: &F,
) {
let code: String = self
.empty_alt
.then_some(" _ => {}".chars())
.into_iter()
.flatten()
.chain(repeat('}').take(self.count))
.collect();
let msg = f(diag, crate::fluent_generated::lint_suggestion.into());
diag.multipart_suggestion_with_style(
msg,
vec![(self.span, code)],
Applicability::MachineApplicable,
SuggestionStyle::ShowCode,
);
}
}
#[derive(Subdiagnostic)]
enum SingleArmMatchBegin {
#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
WithOpenBracket(#[suggestion_part(code = "{{ match ")] Span),
#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
WithoutOpenBracket(#[suggestion_part(code = "match ")] Span),
} }
struct FindSignificantDropper<'tcx, 'a> { struct FindSignificantDropper<'tcx, 'a> {

View File

@ -245,7 +245,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
NonLocalDefinitions: NonLocalDefinitions::default(), NonLocalDefinitions: NonLocalDefinitions::default(),
ImplTraitOvercaptures: ImplTraitOvercaptures, ImplTraitOvercaptures: ImplTraitOvercaptures,
TailExprDropOrder: TailExprDropOrder, TailExprDropOrder: TailExprDropOrder,
IfLetRescope: IfLetRescope, IfLetRescope: IfLetRescope::default(),
] ]
] ]
); );

View File

@ -26,6 +26,9 @@ fn get(&self) -> Option<u8> {
fn main() { fn main() {
if let Some(_value) = Droppy.get() { if let Some(_value) = Droppy.get() {
//[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//[with_feature_gate]~| ERROR: a `match` with a single arm can preserve the drop order up to Edition 2021
//[with_feature_gate]~| WARN: this changes meaning in Rust 2024 //[with_feature_gate]~| WARN: this changes meaning in Rust 2024
}; //[with_feature_gate]~| WARN: this changes meaning in Rust 2024
} else {
}
} }

View File

@ -9,22 +9,46 @@ LL | if let Some(_value) = Droppy.get() {
= warning: this changes meaning in Rust 2024 = warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024 help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope-gated.rs:30:5 --> $DIR/lint-if-let-rescope-gated.rs:32:5
| |
LL | }; LL | } else {
| ^ | ^
note: the lint level is defined here note: the lint level is defined here
--> $DIR/lint-if-let-rescope-gated.rs:11:9 --> $DIR/lint-if-let-rescope-gated.rs:11:9
| |
LL | #![deny(if_let_rescope)] LL | #![deny(if_let_rescope)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021
|
LL ~ match Droppy.get() { Some(_value) => {
LL |
LL |
LL ~ } _ => {} };
|
error: aborting due to 1 previous error error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope-gated.rs:27:5
|
LL | / if let Some(_value) = Droppy.get() {
LL | |
LL | |
LL | |
LL | |
LL | | } else {
LL | | }
| |_____^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | match Droppy.get() {
| ~~~~~
help: rewrite this `if let` into `match`
|
LL | if let Some(_value) = Droppy.get() { Some(_value) => {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | }}
| +
help: rewrite this `if let` into `match`
|
LL | } _ => {
| ~~~~
error: aborting due to 2 previous errors

View File

@ -1,9 +1,7 @@
//@ edition:2024
//@ compile-flags: -Z validate-mir -Zunstable-options
//@ run-rustfix //@ run-rustfix
#![feature(if_let_rescope)]
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![feature(if_let_rescope)]
#![allow(irrefutable_let_patterns)] #![allow(irrefutable_let_patterns)]
fn droppy() -> Droppy { fn droppy() -> Droppy {
@ -22,27 +20,80 @@ impl Droppy {
} }
fn main() { fn main() {
if let Some(_value) = droppy().get() {
// Should not lint
}
match droppy().get() { Some(_value) => { match droppy().get() { Some(_value) => {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something // do something
} _ => { } _ => {
//~^ HELP: the value is now dropped here in Edition 2024 //~^ HELP: the value is now dropped here in Edition 2024
//~| HELP: rewrite this `if let` into `match`
// do something else // do something else
}} }}
//~^ HELP: rewrite this `if let` into `match`
match droppy().get() { Some(_value) => {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| WARN: this changes meaning in Rust 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something
} _ => { match droppy().get() { Some(_value) => {
//~^ HELP: the value is now dropped here in Edition 2024
//~| ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something else
} _ => {}}}}
//~^ HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024
if droppy().get().is_some() {
// Should not lint
} else { match droppy().get() { Some(_value) => {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
} _ => if droppy().get().is_none() {
//~^ HELP: the value is now dropped here in Edition 2024
//~| HELP: rewrite this `if let` into `match`
}}}
//~^ HELP: rewrite this `if let` into `match`
if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024 //~| HELP: the value is now dropped here in Edition 2024
} }
if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024 //~| HELP: the value is now dropped here in Edition 2024
} }
} }

View File

@ -1,9 +1,7 @@
//@ edition:2024
//@ compile-flags: -Z validate-mir -Zunstable-options
//@ run-rustfix //@ run-rustfix
#![feature(if_let_rescope)]
#![deny(if_let_rescope)] #![deny(if_let_rescope)]
#![feature(if_let_rescope)]
#![allow(irrefutable_let_patterns)] #![allow(irrefutable_let_patterns)]
fn droppy() -> Droppy { fn droppy() -> Droppy {
@ -22,27 +20,80 @@ fn get(&self) -> Option<u8> {
} }
fn main() { fn main() {
if let Some(_value) = droppy().get() {
// Should not lint
}
if let Some(_value) = droppy().get() { if let Some(_value) = droppy().get() {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something // do something
} else { } else {
//~^ HELP: the value is now dropped here in Edition 2024 //~^ HELP: the value is now dropped here in Edition 2024
//~| HELP: rewrite this `if let` into `match`
// do something else // do something else
} }
//~^ HELP: rewrite this `if let` into `match`
if let Some(_value) = droppy().get() {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| WARN: this changes meaning in Rust 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something
} else if let Some(_value) = droppy().get() {
//~^ HELP: the value is now dropped here in Edition 2024
//~| ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
// do something else
}
//~^ HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024
if droppy().get().is_some() {
// Should not lint
} else if let Some(_value) = droppy().get() {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024
//~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
} else if droppy().get().is_none() {
//~^ HELP: the value is now dropped here in Edition 2024
//~| HELP: rewrite this `if let` into `match`
}
//~^ HELP: rewrite this `if let` into `match`
if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024 //~| HELP: the value is now dropped here in Edition 2024
} }
if let () = { if let Some(_value) = Droppy.get() {} } { if let () = { if let Some(_value) = Droppy.get() {} } {
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
//~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021
//~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into a `match` //~| WARN: this changes meaning in Rust 2024
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: rewrite this `if let` into `match`
//~| HELP: the value is now dropped here in Edition 2024 //~| HELP: the value is now dropped here in Edition 2024
} }
} }

View File

@ -1,5 +1,5 @@
error: `if let` assigns a shorter lifetime since Edition 2024 error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:25:8 --> $DIR/lint-if-let-rescope.rs:27:8
| |
LL | if let Some(_value) = droppy().get() { LL | if let Some(_value) = droppy().get() {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^ | ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@ -9,29 +9,168 @@ LL | if let Some(_value) = droppy().get() {
= warning: this changes meaning in Rust 2024 = warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024 help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:30:5 --> $DIR/lint-if-let-rescope.rs:35:5
| |
LL | } else { LL | } else {
| ^ | ^
note: the lint level is defined here note: the lint level is defined here
--> $DIR/lint-if-let-rescope.rs:6:9 --> $DIR/lint-if-let-rescope.rs:3:9
| |
LL | #![deny(if_let_rescope)] LL | #![deny(if_let_rescope)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021
error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope.rs:27:5
| |
LL ~ match droppy().get() { Some(_value) => { LL | / if let Some(_value) = droppy().get() {
LL | LL | |
... LL | |
LL | // do something LL | |
LL ~ } _ => { ... |
LL | LL | | // do something else
LL | // do something else LL | | }
LL ~ }} | |_____^
| |
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | match droppy().get() {
| ~~~~~
help: rewrite this `if let` into `match`
|
LL | if let Some(_value) = droppy().get() { Some(_value) => {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | }}
| +
help: rewrite this `if let` into `match`
|
LL | } _ => {
| ~~~~
error: `if let` assigns a shorter lifetime since Edition 2024 error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:35:27 --> $DIR/lint-if-let-rescope.rs:42:8
|
LL | if let Some(_value) = droppy().get() {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
| |
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:50:5
|
LL | } else if let Some(_value) = droppy().get() {
| ^
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:50:15
|
LL | } else if let Some(_value) = droppy().get() {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
| |
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:58:5
|
LL | }
| ^
error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope.rs:42:5
|
LL | / if let Some(_value) = droppy().get() {
LL | |
LL | |
LL | |
... |
LL | | // do something else
LL | | }
| |_____^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | match droppy().get() {
| ~~~~~
help: rewrite this `if let` into `match`
|
LL | } else { match droppy().get() {
| ~~~~~~~
help: rewrite this `if let` into `match`
|
LL | if let Some(_value) = droppy().get() { Some(_value) => {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | } else if let Some(_value) = droppy().get() { Some(_value) => {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | } _ => {}}}}
| ++++++++++
help: rewrite this `if let` into `match`
|
LL | } _ => if let Some(_value) = droppy().get() {
| ~~~~
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:64:15
|
LL | } else if let Some(_value) = droppy().get() {
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
| |
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:71:5
|
LL | } else if droppy().get().is_none() {
| ^
error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope.rs:64:12
|
LL | } else if let Some(_value) = droppy().get() {
| ____________^
LL | |
LL | |
LL | |
... |
LL | |
LL | | }
| |_____^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | } else { match droppy().get() {
| ~~~~~~~
help: rewrite this `if let` into `match`
|
LL | } else if let Some(_value) = droppy().get() { Some(_value) => {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | }}}
| ++
help: rewrite this `if let` into `match`
|
LL | } _ => if droppy().get().is_none() {
| ~~~~
error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:77:27
| |
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } {
| ^^^^^^^^^^^^^^^^^^^------^^^^^^ | ^^^^^^^^^^^^^^^^^^^------^^^^^^
@ -41,17 +180,38 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else
= warning: this changes meaning in Rust 2024 = warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024 help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:35:69 --> $DIR/lint-if-let-rescope.rs:77:69
| |
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } {
| ^ | ^
help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021
error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope.rs:77:24
| |
LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } {
| ~~~~~ +++++++++++++++++ ~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | if let Some(1) = { match Droppy.get() { Some(1) } else { None } } {
| ~~~~~
help: rewrite this `if let` into `match`
|
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(_value) => { Some(1) } else { None } } {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None }} } {
| +
help: rewrite this `if let` into `match`
|
LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } _ => { None } } {
| ~~~~
error: `if let` assigns a shorter lifetime since Edition 2024 error: `if let` assigns a shorter lifetime since Edition 2024
--> $DIR/lint-if-let-rescope.rs:42:22 --> $DIR/lint-if-let-rescope.rs:89:22
| |
LL | if let () = { if let Some(_value) = Droppy.get() {} } { LL | if let () = { if let Some(_value) = Droppy.get() {} } {
| ^^^^^^^^^^^^^^^^^^^------^^^^^^ | ^^^^^^^^^^^^^^^^^^^------^^^^^^
@ -61,14 +221,31 @@ LL | if let () = { if let Some(_value) = Droppy.get() {} } {
= warning: this changes meaning in Rust 2024 = warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085> = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: the value is now dropped here in Edition 2024 help: the value is now dropped here in Edition 2024
--> $DIR/lint-if-let-rescope.rs:42:55 --> $DIR/lint-if-let-rescope.rs:89:55
| |
LL | if let () = { if let Some(_value) = Droppy.get() {} } { LL | if let () = { if let Some(_value) = Droppy.get() {} } {
| ^ | ^
help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021
error: a `match` with a single arm can preserve the drop order up to Edition 2021
--> $DIR/lint-if-let-rescope.rs:89:19
| |
LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { LL | if let () = { if let Some(_value) = Droppy.get() {} } {
| ~~~~~ +++++++++++++++++ +++++++++ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
help: rewrite this `if let` into `match`
|
LL | if let () = { match Droppy.get() {} } {
| ~~~~~
help: rewrite this `if let` into `match`
|
LL | if let () = { if let Some(_value) = Droppy.get() { Some(_value) => {} } {
| +++++++++++++++++
help: rewrite this `if let` into `match`
|
LL | if let () = { if let Some(_value) = Droppy.get() {} _ => {}} } {
| ++++++++
error: aborting due to 3 previous errors error: aborting due to 11 previous errors