From bca08d8c93eb0fece501a754231e30d326e8b235 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 8 Apr 2026 09:45:54 -0700 Subject: [PATCH 01/11] Revert "update diagnostic for variables moved by `dbg!`" This reverts commit 1374038f802353d235d89928fd605b271fb3a988. --- .../src/diagnostics/conflict_errors.rs | 40 ++++----- compiler/rustc_span/src/symbol.rs | 1 - src/tools/clippy/clippy_utils/src/sym.rs | 1 + tests/ui/borrowck/dbg-issue-120327.rs | 53 ++++++++---- tests/ui/borrowck/dbg-issue-120327.stderr | 81 +++++++------------ .../dbg-macro-move-semantics.stderr | 4 - 6 files changed, 84 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3e34f2e5896ee..c2c07614bc0dd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -545,6 +545,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } // for dbg!(x) which may take ownership, suggest dbg!(&x) instead + // but here we actually do not check whether the macro name is `dbg!` + // so that we may extend the scope a bit larger to cover more cases fn suggest_ref_for_dbg_args( &self, body: &hir::Expr<'_>, @@ -558,41 +560,29 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }); let Some(var_info) = var_info else { return }; let arg_name = var_info.name; - struct MatchArgFinder<'tcx> { - tcx: TyCtxt<'tcx>, - move_span: Span, + struct MatchArgFinder { + expr_span: Span, + match_arg_span: Option, arg_name: Symbol, - match_arg_span: Option = None, } - impl Visitor<'_> for MatchArgFinder<'_> { + impl Visitor<'_> for MatchArgFinder { fn visit_expr(&mut self, e: &hir::Expr<'_>) { // dbg! is expanded into a match pattern, we need to find the right argument span - if let hir::ExprKind::Match(scrutinee, ..) = &e.kind - && let hir::ExprKind::Tup(args) = scrutinee.kind - && e.span.macro_backtrace().any(|expn| { - expn.macro_def_id.is_some_and(|macro_def_id| { - self.tcx.is_diagnostic_item(sym::dbg_macro, macro_def_id) - }) - }) + if let hir::ExprKind::Match(expr, ..) = &e.kind + && let hir::ExprKind::Path(hir::QPath::Resolved( + _, + path @ Path { segments: [seg], .. }, + )) = &expr.kind + && seg.ident.name == self.arg_name + && self.expr_span.source_callsite().contains(expr.span) { - for arg in args { - if let hir::ExprKind::Path(hir::QPath::Resolved( - _, - path @ Path { segments: [seg], .. }, - )) = &arg.kind - && seg.ident.name == self.arg_name - && self.move_span.source_equal(arg.span) - { - self.match_arg_span = Some(path.span); - return; - } - } + self.match_arg_span = Some(path.span); } hir::intravisit::walk_expr(self, e); } } - let mut finder = MatchArgFinder { tcx: self.infcx.tcx, move_span, arg_name, .. }; + let mut finder = MatchArgFinder { expr_span: move_span, match_arg_span: None, arg_name }; finder.visit_expr(body); if let Some(macro_arg_span) = finder.match_arg_span { err.span_suggestion_verbose( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5b079bcaf0db8..731a838530729 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -763,7 +763,6 @@ symbols! { custom_test_frameworks, d, d32, - dbg_macro, dead_code, dealloc, debug, diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index a7171cff66f90..250e73afd4f00 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -199,6 +199,7 @@ generate! { cx, cycle, cyclomatic_complexity, + dbg_macro, de, debug_struct, deprecated_in_future, diff --git a/tests/ui/borrowck/dbg-issue-120327.rs b/tests/ui/borrowck/dbg-issue-120327.rs index 45605acc34334..2de43f634877a 100644 --- a/tests/ui/borrowck/dbg-issue-120327.rs +++ b/tests/ui/borrowck/dbg-issue-120327.rs @@ -1,44 +1,67 @@ -//! Diagnostic test for : suggest borrowing -//! variables passed to `dbg!` that are later used. -//@ dont-require-annotations: HELP - fn s() -> String { let a = String::new(); - dbg!(a); //~ HELP consider borrowing instead of transferring ownership + dbg!(a); return a; //~ ERROR use of moved value: } fn m() -> String { let a = String::new(); - dbg!(1, 2, a, 1, 2); //~ HELP consider borrowing instead of transferring ownership + dbg!(1, 2, a, 1, 2); return a; //~ ERROR use of moved value: } fn t(a: String) -> String { let b: String = "".to_string(); - dbg!(a, b); //~ HELP consider borrowing instead of transferring ownership + dbg!(a, b); return b; //~ ERROR use of moved value: } fn x(a: String) -> String { let b: String = "".to_string(); - dbg!(a, b); //~ HELP consider borrowing instead of transferring ownership + dbg!(a, b); return a; //~ ERROR use of moved value: } -fn two_of_them(a: String) -> String { - dbg!(a, a); //~ ERROR use of moved value - //~| HELP consider borrowing instead of transferring ownership - //~| HELP consider borrowing instead of transferring ownership - return a; //~ ERROR use of moved value +macro_rules! my_dbg { + () => { + eprintln!("[{}:{}:{}]", file!(), line!(), column!()) + }; + ($val:expr $(,)?) => { + match $val { + tmp => { + eprintln!("[{}:{}:{}] {} = {:#?}", + file!(), line!(), column!(), stringify!($val), &tmp); + tmp + } + } + }; + ($($val:expr),+ $(,)?) => { + ($(my_dbg!($val)),+,) + }; +} + +fn test_my_dbg() -> String { + let b: String = "".to_string(); + my_dbg!(b, 1); + return b; //~ ERROR use of moved value: +} + +fn test_not_macro() -> String { + let a = String::new(); + let _b = match a { + tmp => { + eprintln!("dbg: {}", tmp); + tmp + } + }; + return a; //~ ERROR use of moved value: } fn get_expr(_s: String) {} -// The suggestion is purely syntactic; applying it here will result in a type error. fn test() { let a: String = "".to_string(); - let _res = get_expr(dbg!(a)); //~ HELP consider borrowing instead of transferring ownership + let _res = get_expr(dbg!(a)); let _l = a.len(); //~ ERROR borrow of moved value } diff --git a/tests/ui/borrowck/dbg-issue-120327.stderr b/tests/ui/borrowck/dbg-issue-120327.stderr index e7a7151e541dd..685a530a1fe5b 100644 --- a/tests/ui/borrowck/dbg-issue-120327.stderr +++ b/tests/ui/borrowck/dbg-issue-120327.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a` - --> $DIR/dbg-issue-120327.rs:8:12 + --> $DIR/dbg-issue-120327.rs:4:12 | LL | let a = String::new(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait @@ -12,13 +12,9 @@ help: consider cloning the value if the performance cost is acceptable | LL | dbg!(a.clone()); | ++++++++ -help: consider borrowing instead of transferring ownership - | -LL | dbg!(&a); - | + error[E0382]: use of moved value: `a` - --> $DIR/dbg-issue-120327.rs:14:12 + --> $DIR/dbg-issue-120327.rs:10:12 | LL | let a = String::new(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait @@ -31,13 +27,9 @@ help: consider cloning the value if the performance cost is acceptable | LL | dbg!(1, 2, a.clone(), 1, 2); | ++++++++ -help: consider borrowing instead of transferring ownership - | -LL | dbg!(1, 2, &a, 1, 2); - | + error[E0382]: use of moved value: `b` - --> $DIR/dbg-issue-120327.rs:20:12 + --> $DIR/dbg-issue-120327.rs:16:12 | LL | let b: String = "".to_string(); | - move occurs because `b` has type `String`, which does not implement the `Copy` trait @@ -50,13 +42,9 @@ help: consider cloning the value if the performance cost is acceptable | LL | dbg!(a, b.clone()); | ++++++++ -help: consider borrowing instead of transferring ownership - | -LL | dbg!(a, &b); - | + error[E0382]: use of moved value: `a` - --> $DIR/dbg-issue-120327.rs:26:12 + --> $DIR/dbg-issue-120327.rs:22:12 | LL | fn x(a: String) -> String { | - move occurs because `a` has type `String`, which does not implement the `Copy` trait @@ -70,52 +58,47 @@ help: consider cloning the value if the performance cost is acceptable | LL | dbg!(a.clone(), b); | ++++++++ -help: consider borrowing instead of transferring ownership - | -LL | dbg!(&a, b); - | + -error[E0382]: use of moved value: `a` - --> $DIR/dbg-issue-120327.rs:30:13 - | -LL | fn two_of_them(a: String) -> String { - | - move occurs because `a` has type `String`, which does not implement the `Copy` trait -LL | dbg!(a, a); - | - ^ value used here after move - | | - | value moved here +error[E0382]: use of moved value: `b` + --> $DIR/dbg-issue-120327.rs:46:12 | -help: consider cloning the value if the performance cost is acceptable +LL | tmp => { + | --- value moved here +... +LL | let b: String = "".to_string(); + | - move occurs because `b` has type `String`, which does not implement the `Copy` trait +LL | my_dbg!(b, 1); +LL | return b; + | ^ value used here after move | -LL | dbg!(a.clone(), a); - | ++++++++ help: consider borrowing instead of transferring ownership | -LL | dbg!(&a, a); - | + +LL | my_dbg!(&b, 1); + | + +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref tmp => { + | +++ error[E0382]: use of moved value: `a` - --> $DIR/dbg-issue-120327.rs:33:12 + --> $DIR/dbg-issue-120327.rs:57:12 | -LL | fn two_of_them(a: String) -> String { - | - move occurs because `a` has type `String`, which does not implement the `Copy` trait -LL | dbg!(a, a); - | - value moved here +LL | let a = String::new(); + | - move occurs because `a` has type `String`, which does not implement the `Copy` trait +LL | let _b = match a { +LL | tmp => { + | --- value moved here ... LL | return a; | ^ value used here after move | -help: consider cloning the value if the performance cost is acceptable - | -LL | dbg!(a, a.clone()); - | ++++++++ -help: consider borrowing instead of transferring ownership +help: borrow this binding in the pattern to avoid moving the value | -LL | dbg!(a, &a); - | + +LL | ref tmp => { + | +++ error[E0382]: borrow of moved value: `a` - --> $DIR/dbg-issue-120327.rs:42:14 + --> $DIR/dbg-issue-120327.rs:65:14 | LL | let a: String = "".to_string(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait @@ -128,10 +111,6 @@ help: consider cloning the value if the performance cost is acceptable | LL | let _res = get_expr(dbg!(a.clone())); | ++++++++ -help: consider borrowing instead of transferring ownership - | -LL | let _res = get_expr(dbg!(&a)); - | + error: aborting due to 7 previous errors diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr index 7ce5ebf81e310..76b2d1be27795 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr @@ -16,10 +16,6 @@ LL | struct NoCopy(usize); ... LL | let _ = dbg!(a); | - you could clone this value -help: consider borrowing instead of transferring ownership - | -LL | let _ = dbg!(&a); - | + error: aborting due to 1 previous error From cb5a91376ec496c2b062a99ca258b4d725ea4a33 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 8 Apr 2026 09:45:57 -0700 Subject: [PATCH 02/11] Revert "don't drop arguments' temporaries in `dbg!`" This reverts commit 4f50466be4802fb231200737fb0dc0933f421908. --- library/std/src/macros.rs | 82 +++++++++---------- library/std/src/macros/tests.rs | 13 --- .../clippy/clippy_lints/src/dbg_macro.rs | 47 +++++++++-- .../dangling_primitive.stderr | 2 +- .../return_pointer_on_unwind.stderr | 2 +- tests/ui/borrowck/dbg-issue-120327.stderr | 40 ++++----- tests/ui/liveness/liveness-upvars.rs | 2 +- tests/ui/liveness/liveness-upvars.stderr | 10 +-- .../dbg-macro-move-semantics.stderr | 16 ++-- 9 files changed, 111 insertions(+), 103 deletions(-) delete mode 100644 library/std/src/macros/tests.rs diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 5f9b383c2da37..0bb14552432d5 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -5,9 +5,6 @@ //! library. // ignore-tidy-dbg -#[cfg(test)] -mod tests; - #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] #[rustc_builtin_macro(std_panic)] @@ -362,16 +359,19 @@ macro_rules! dbg { }; } -/// Internal macro that processes a list of expressions, binds their results -/// with `match`, calls `eprint!` with the collected information, and returns -/// all the evaluated expressions in a tuple. +/// Internal macro that processes a list of expressions and produces a chain of +/// nested `match`es, one for each expression, before finally calling `eprint!` +/// with the collected information and returning all the evaluated expressions +/// in a tuple. /// /// E.g. `dbg_internal!(() () (1, 2))` expands into /// ```rust, ignore -/// match (1, 2) { -/// (tmp_1, tmp_2) => { -/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */); -/// (tmp_1, tmp_2) +/// match 1 { +/// tmp_1 => match 2 { +/// tmp_2 => { +/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */); +/// (tmp_1, tmp_2) +/// } /// } /// } /// ``` @@ -380,41 +380,37 @@ macro_rules! dbg { #[doc(hidden)] #[rustc_macro_transparency = "semiopaque"] pub macro dbg_internal { - (($($piece:literal),+) ($($processed:expr => $bound:ident),+) ()) => { + (($($piece:literal),+) ($($processed:expr => $bound:expr),+) ()) => {{ + $crate::eprint!( + $crate::concat!($($piece),+), + $( + $crate::stringify!($processed), + // The `&T: Debug` check happens here (not in the format literal desugaring) + // to avoid format literal related messages and suggestions. + &&$bound as &dyn $crate::fmt::Debug + ),+, + // The location returned here is that of the macro invocation, so + // it will be the same for all expressions. Thus, label these + // arguments so that they can be reused in every piece of the + // formatting template. + file=$crate::file!(), + line=$crate::line!(), + column=$crate::column!() + ); + // Comma separate the variables only when necessary so that this will + // not yield a tuple for a single expression, but rather just parenthesize + // the expression. + ($($bound),+) + }}, + (($($piece:literal),*) ($($processed:expr => $bound:expr),*) ($val:expr $(,$rest:expr)*)) => { // Use of `match` here is intentional because it affects the lifetimes // of temporaries - https://stackoverflow.com/a/48732525/1063961 - // Always put the arguments in a tuple to avoid an unused parens lint on the pattern. - match ($($processed,)+) { - ($($bound,)+) => { - $crate::eprint!( - $crate::concat!($($piece),+), - $( - $crate::stringify!($processed), - // The `&T: Debug` check happens here (not in the format literal desugaring) - // to avoid format literal related messages and suggestions. - &&$bound as &dyn $crate::fmt::Debug - ),+, - // The location returned here is that of the macro invocation, so - // it will be the same for all expressions. Thus, label these - // arguments so that they can be reused in every piece of the - // formatting template. - file=$crate::file!(), - line=$crate::line!(), - column=$crate::column!() - ); - // Comma separate the variables only when necessary so that this will - // not yield a tuple for a single expression, but rather just parenthesize - // the expression. - ($($bound),+) - - } + match $val { + tmp => $crate::macros::dbg_internal!( + ($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n") + ($($processed => $bound,)* $val => tmp) + ($($rest),*) + ), } }, - (($($piece:literal),*) ($($processed:expr => $bound:ident),*) ($val:expr $(,$rest:expr)*)) => { - $crate::macros::dbg_internal!( - ($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n") - ($($processed => $bound,)* $val => tmp) - ($($rest),*) - ) - }, } diff --git a/library/std/src/macros/tests.rs b/library/std/src/macros/tests.rs deleted file mode 100644 index db2be925ff30a..0000000000000 --- a/library/std/src/macros/tests.rs +++ /dev/null @@ -1,13 +0,0 @@ -// ignore-tidy-dbg - -/// Test for : -/// `dbg!` shouldn't drop arguments' temporaries. -#[test] -fn no_dropping_temps() { - fn temp() {} - - *dbg!(&temp()); - *dbg!(&temp(), 1).0; - *dbg!(0, &temp()).1; - *dbg!(0, &temp(), 2).1; -} diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index aed9b875fd093..f47d0d4835a9e 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; +use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext}; @@ -92,15 +92,16 @@ impl LateLintPass<'_> for DbgMacro { (macro_call.span, String::from("()")) } }, - ExprKind::Match(args, _, _) => { - let suggestion = match args.kind { + ExprKind::Match(first, arms, _) => { + let vals = collect_vals(first, arms); + let suggestion = match *vals.as_slice() { // dbg!(1) => 1 - ExprKind::Tup([val]) => { + [val] => { snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) .to_string() }, // dbg!(2, 3) => (2, 3) - ExprKind::Tup([first, .., last]) => { + [first, .., last] => { let snippet = snippet_with_applicability( cx, first.span.source_callsite().to(last.span.source_callsite()), @@ -164,3 +165,39 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option { macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } + +/// Extracts all value expressions from the `match`-tree generated by `dbg!`. +/// +/// E.g. from +/// ```rust, ignore +/// match 1 { +/// tmp_1 => match 2 { +/// tmp_2 => { +/// /* printing */ +/// (tmp_1, tmp_2) +/// } +/// } +/// } +/// ``` +/// this extracts `1` and `2`. +fn collect_vals<'hir>(first: &'hir Expr<'hir>, mut arms: &'hir [Arm<'hir>]) -> Vec<&'hir Expr<'hir>> { + let mut vals = vec![first]; + loop { + let [arm] = arms else { + unreachable!("dbg! macro expansion only has single-arm matches") + }; + + match is_async_move_desugar(arm.body) + .unwrap_or(arm.body) + .peel_drop_temps() + .kind + { + ExprKind::Block(..) => return vals, + ExprKind::Match(val, a, _) => { + vals.push(val); + arms = a; + }, + _ => unreachable!("dbg! macro expansion only results in block or match expressions"), + } + } +} diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr index 4f06a1afa50fe..afc2cb214842e 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr @@ -2,7 +2,7 @@ error: Undefined Behavior: memory access failed: ALLOC has been freed, so this p --> tests/fail/dangling_pointers/dangling_primitive.rs:LL:CC | LL | dbg!(*ptr); - | ^^^^ Undefined Behavior occurred here + | ^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr index 88d5694c4736d..364a4b4a74418 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -7,7 +7,7 @@ error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is unin --> tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC | LL | dbg!(x.0); - | ^^^ Undefined Behavior occurred here + | ^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/tests/ui/borrowck/dbg-issue-120327.stderr b/tests/ui/borrowck/dbg-issue-120327.stderr index 685a530a1fe5b..efacc0c3f1341 100644 --- a/tests/ui/borrowck/dbg-issue-120327.stderr +++ b/tests/ui/borrowck/dbg-issue-120327.stderr @@ -4,14 +4,14 @@ error[E0382]: use of moved value: `a` LL | let a = String::new(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL | dbg!(a); - | - value moved here + | ------- value moved here LL | return a; | ^ value used here after move | -help: consider cloning the value if the performance cost is acceptable +help: consider borrowing instead of transferring ownership | -LL | dbg!(a.clone()); - | ++++++++ +LL | dbg!(&a); + | + error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:10:12 @@ -19,14 +19,14 @@ error[E0382]: use of moved value: `a` LL | let a = String::new(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL | dbg!(1, 2, a, 1, 2); - | - value moved here + | ------------------- value moved here LL | return a; | ^ value used here after move | -help: consider cloning the value if the performance cost is acceptable +help: consider borrowing instead of transferring ownership | -LL | dbg!(1, 2, a.clone(), 1, 2); - | ++++++++ +LL | dbg!(1, 2, &a, 1, 2); + | + error[E0382]: use of moved value: `b` --> $DIR/dbg-issue-120327.rs:16:12 @@ -34,14 +34,14 @@ error[E0382]: use of moved value: `b` LL | let b: String = "".to_string(); | - move occurs because `b` has type `String`, which does not implement the `Copy` trait LL | dbg!(a, b); - | - value moved here + | ---------- value moved here LL | return b; | ^ value used here after move | -help: consider cloning the value if the performance cost is acceptable +help: consider borrowing instead of transferring ownership | -LL | dbg!(a, b.clone()); - | ++++++++ +LL | dbg!(a, &b); + | + error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:22:12 @@ -50,14 +50,14 @@ LL | fn x(a: String) -> String { | - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL | let b: String = "".to_string(); LL | dbg!(a, b); - | - value moved here + | ---------- value moved here LL | return a; | ^ value used here after move | -help: consider cloning the value if the performance cost is acceptable +help: consider borrowing instead of transferring ownership | -LL | dbg!(a.clone(), b); - | ++++++++ +LL | dbg!(&a, b); + | + error[E0382]: use of moved value: `b` --> $DIR/dbg-issue-120327.rs:46:12 @@ -103,14 +103,14 @@ error[E0382]: borrow of moved value: `a` LL | let a: String = "".to_string(); | - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL | let _res = get_expr(dbg!(a)); - | - value moved here + | ------- value moved here LL | let _l = a.len(); | ^ value borrowed here after move | -help: consider cloning the value if the performance cost is acceptable +help: consider borrowing instead of transferring ownership | -LL | let _res = get_expr(dbg!(a.clone())); - | ++++++++ +LL | let _res = get_expr(dbg!(&a)); + | + error: aborting due to 7 previous errors diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs index 0e198f1dea10b..be58b48a40576 100644 --- a/tests/ui/liveness/liveness-upvars.rs +++ b/tests/ui/liveness/liveness-upvars.rs @@ -98,7 +98,7 @@ pub fn g(mut v: T) { } pub fn h() { - let mut z = T::default(); //~ WARN unused variable: `z` + let mut z = T::default(); let _ = move |b| { loop { if b { diff --git a/tests/ui/liveness/liveness-upvars.stderr b/tests/ui/liveness/liveness-upvars.stderr index 0bb5786ab3e2e..cfed2830164ad 100644 --- a/tests/ui/liveness/liveness-upvars.stderr +++ b/tests/ui/liveness/liveness-upvars.stderr @@ -156,14 +156,6 @@ LL | z = T::default(); | = help: maybe it is overwritten before being read? -warning: unused variable: `z` - --> $DIR/liveness-upvars.rs:101:9 - | -LL | let mut z = T::default(); - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_z` - | - = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` - warning: value captured by `state` is never read --> $DIR/liveness-upvars.rs:131:9 | @@ -204,5 +196,5 @@ LL | s = yield (); | = help: maybe it is overwritten before being read? -warning: 25 warnings emitted +warning: 24 warnings emitted diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr index 76b2d1be27795..f8ef315b9cc78 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr @@ -1,21 +1,17 @@ error[E0382]: use of moved value: `a` - --> $DIR/dbg-macro-move-semantics.rs:9:18 + --> $DIR/dbg-macro-move-semantics.rs:9:13 | LL | let a = NoCopy(0); | - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait LL | let _ = dbg!(a); - | - value moved here + | ------- value moved here LL | let _ = dbg!(a); - | ^ value used here after move + | ^^^^^^^ value used here after move | -note: if `NoCopy` implemented `Clone`, you could clone the value - --> $DIR/dbg-macro-move-semantics.rs:4:1 +help: consider borrowing instead of transferring ownership | -LL | struct NoCopy(usize); - | ^^^^^^^^^^^^^ consider implementing `Clone` for this type -... -LL | let _ = dbg!(a); - | - you could clone this value +LL | let _ = dbg!(&a); + | + error: aborting due to 1 previous error From aad47fb47d1ede44945beda9f90acba62ad6beaa Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 8 Apr 2026 10:41:06 -0700 Subject: [PATCH 03/11] Revert "Rollup merge of #149869 - joboet:torn-dbg, r=Mark-Simulacrum" This reverts commit cc666ba8f446ff47c7e1b56019afd1dbee85b625, reversing changes made to 2da59596005edb3979aca9ad59012a8aab2339c3. --- library/std/src/lib.rs | 4 +- library/std/src/macros.rs | 77 +++++------------ .../clippy/clippy_lints/src/dbg_macro.rs | 82 ++++++------------- 3 files changed, 48 insertions(+), 115 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 629d9f8adab3c..f047556671f21 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -468,9 +468,7 @@ extern crate std as realstd; // The standard macros that are not built-in to the compiler. #[macro_use] -#[doc(hidden)] -#[unstable(feature = "std_internals", issue = "none")] -pub mod macros; +mod macros; // The runtime entry point and a few unstable public functions used by the // compiler diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 0bb14552432d5..25e2b7ea13703 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -347,70 +347,35 @@ macro_rules! eprintln { /// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html /// [`log`]: https://crates.io/crates/log #[macro_export] -#[allow_internal_unstable(std_internals)] #[cfg_attr(not(test), rustc_diagnostic_item = "dbg_macro")] #[stable(feature = "dbg_macro", since = "1.32.0")] macro_rules! dbg { + // NOTE: We cannot use `concat!` to make a static string as a format argument + // of `eprintln!` because `file!` could contain a `{` or + // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!` + // will be malformed. () => { $crate::eprintln!("[{}:{}:{}]", $crate::file!(), $crate::line!(), $crate::column!()) }; - ($($val:expr),+ $(,)?) => { - $crate::macros::dbg_internal!(() () ($($val),+)) - }; -} - -/// Internal macro that processes a list of expressions and produces a chain of -/// nested `match`es, one for each expression, before finally calling `eprint!` -/// with the collected information and returning all the evaluated expressions -/// in a tuple. -/// -/// E.g. `dbg_internal!(() () (1, 2))` expands into -/// ```rust, ignore -/// match 1 { -/// tmp_1 => match 2 { -/// tmp_2 => { -/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */); -/// (tmp_1, tmp_2) -/// } -/// } -/// } -/// ``` -/// -/// This is necessary so that `dbg!` outputs don't get torn, see #136703. -#[doc(hidden)] -#[rustc_macro_transparency = "semiopaque"] -pub macro dbg_internal { - (($($piece:literal),+) ($($processed:expr => $bound:expr),+) ()) => {{ - $crate::eprint!( - $crate::concat!($($piece),+), - $( - $crate::stringify!($processed), - // The `&T: Debug` check happens here (not in the format literal desugaring) - // to avoid format literal related messages and suggestions. - &&$bound as &dyn $crate::fmt::Debug - ),+, - // The location returned here is that of the macro invocation, so - // it will be the same for all expressions. Thus, label these - // arguments so that they can be reused in every piece of the - // formatting template. - file=$crate::file!(), - line=$crate::line!(), - column=$crate::column!() - ); - // Comma separate the variables only when necessary so that this will - // not yield a tuple for a single expression, but rather just parenthesize - // the expression. - ($($bound),+) - }}, - (($($piece:literal),*) ($($processed:expr => $bound:expr),*) ($val:expr $(,$rest:expr)*)) => { + ($val:expr $(,)?) => { // Use of `match` here is intentional because it affects the lifetimes // of temporaries - https://stackoverflow.com/a/48732525/1063961 match $val { - tmp => $crate::macros::dbg_internal!( - ($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n") - ($($processed => $bound,)* $val => tmp) - ($($rest),*) - ), + tmp => { + $crate::eprintln!("[{}:{}:{}] {} = {:#?}", + $crate::file!(), + $crate::line!(), + $crate::column!(), + $crate::stringify!($val), + // The `&T: Debug` check happens here (not in the format literal desugaring) + // to avoid format literal related messages and suggestions. + &&tmp as &dyn $crate::fmt::Debug, + ); + tmp + } } - }, + }; + ($($val:expr),+ $(,)?) => { + ($($crate::dbg!($val)),+,) + }; } diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index f47d0d4835a9e..8d86a9f346314 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; +use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext}; @@ -92,27 +92,33 @@ impl LateLintPass<'_> for DbgMacro { (macro_call.span, String::from("()")) } }, - ExprKind::Match(first, arms, _) => { - let vals = collect_vals(first, arms); - let suggestion = match *vals.as_slice() { - // dbg!(1) => 1 - [val] => { - snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) - .to_string() + // dbg!(1) + ExprKind::Match(val, ..) => ( + macro_call.span, + snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) + .to_string(), + ), + // dbg!(2, 3) + ExprKind::Tup( + [ + Expr { + kind: ExprKind::Match(first, ..), + .. }, - // dbg!(2, 3) => (2, 3) - [first, .., last] => { - let snippet = snippet_with_applicability( - cx, - first.span.source_callsite().to(last.span.source_callsite()), - "..", - &mut applicability, - ); - format!("({snippet})") + .., + Expr { + kind: ExprKind::Match(last, ..), + .. }, - _ => unreachable!(), - }; - (macro_call.span, suggestion) + ], + ) => { + let snippet = snippet_with_applicability( + cx, + first.span.source_callsite().to(last.span.source_callsite()), + "..", + &mut applicability, + ); + (macro_call.span, format!("({snippet})")) }, _ => unreachable!(), }; @@ -165,39 +171,3 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option { macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } - -/// Extracts all value expressions from the `match`-tree generated by `dbg!`. -/// -/// E.g. from -/// ```rust, ignore -/// match 1 { -/// tmp_1 => match 2 { -/// tmp_2 => { -/// /* printing */ -/// (tmp_1, tmp_2) -/// } -/// } -/// } -/// ``` -/// this extracts `1` and `2`. -fn collect_vals<'hir>(first: &'hir Expr<'hir>, mut arms: &'hir [Arm<'hir>]) -> Vec<&'hir Expr<'hir>> { - let mut vals = vec![first]; - loop { - let [arm] = arms else { - unreachable!("dbg! macro expansion only has single-arm matches") - }; - - match is_async_move_desugar(arm.body) - .unwrap_or(arm.body) - .peel_drop_temps() - .kind - { - ExprKind::Block(..) => return vals, - ExprKind::Match(val, a, _) => { - vals.push(val); - arms = a; - }, - _ => unreachable!("dbg! macro expansion only results in block or match expressions"), - } - } -} From d0b5e61fe78023dd6578c757160e82f12cfeaa99 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 8 Apr 2026 14:10:50 -0700 Subject: [PATCH 04/11] Revert "Stabilize assert_matches" This reverts commit 2f3b95234982c74f8fb412384cdc770437572c7e. --- compiler/rustc_abi/src/lib.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_builtin_macros/src/lib.rs | 2 +- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- compiler/rustc_codegen_ssa/src/lib.rs | 2 +- compiler/rustc_const_eval/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_mir_build/src/lib.rs | 2 +- compiler/rustc_mir_dataflow/src/lib.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_symbol_mangling/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- compiler/rustc_ty_utils/src/lib.rs | 2 +- library/alloc/src/lib.rs | 1 + library/alloctests/lib.rs | 1 + library/alloctests/tests/lib.rs | 1 + library/core/src/lib.rs | 2 +- library/core/src/macros/mod.rs | 8 ++++++-- library/std/src/lib.rs | 3 ++- src/librustdoc/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- tests/ui-fulldeps/rustc_public/check_abi.rs | 1 + tests/ui-fulldeps/rustc_public/check_allocation.rs | 1 + tests/ui-fulldeps/rustc_public/check_assoc_items.rs | 1 + tests/ui-fulldeps/rustc_public/check_coroutine_body.rs | 1 + tests/ui-fulldeps/rustc_public/check_crate_defs.rs | 1 + tests/ui-fulldeps/rustc_public/check_def_ty.rs | 1 + tests/ui-fulldeps/rustc_public/check_defs.rs | 1 + tests/ui-fulldeps/rustc_public/check_foreign.rs | 1 + tests/ui-fulldeps/rustc_public/check_instance.rs | 1 + tests/ui-fulldeps/rustc_public/check_intrinsics.rs | 1 + tests/ui-fulldeps/rustc_public/check_item_kind.rs | 1 + tests/ui-fulldeps/rustc_public/check_trait_queries.rs | 1 + tests/ui-fulldeps/rustc_public/check_transform.rs | 1 + tests/ui-fulldeps/rustc_public/check_ty_fold.rs | 1 + tests/ui-fulldeps/rustc_public/check_variant.rs | 1 + tests/ui-fulldeps/rustc_public/closure-generic-body.rs | 1 + tests/ui-fulldeps/rustc_public/closure_body.rs | 1 + tests/ui-fulldeps/rustc_public/compilation-result.rs | 1 + tests/ui-fulldeps/rustc_public/crate-info.rs | 1 + tests/ui-fulldeps/rustc_public/projections.rs | 1 + tests/ui-fulldeps/rustc_public/smir_internal.rs | 1 + tests/ui-fulldeps/rustc_public/smir_serde.rs | 1 + tests/ui-fulldeps/rustc_public/smir_visitor.rs | 1 + tests/ui/coroutine/uninhabited-field.rs | 1 + tests/ui/macros/assert-matches-macro-msg.rs | 2 ++ tests/ui/stdlib-unit-tests/matches2021.rs | 2 ++ 55 files changed, 63 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 2a783cd73d9de..5d14d3fd627d0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![cfg_attr(all(feature = "nightly", bootstrap, test), feature(assert_matches))] +#![cfg_attr(all(feature = "nightly", test), feature(assert_matches))] #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(step_trait))] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index bd46a40c02da1..f52f61e49c91e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,8 +2,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(default_field_values)] #![feature(file_buffered)] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9c4005c7f7f2f..f671f59f983a3 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -3,8 +3,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(iter_order_by)] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 7120ee0afec96..6f8451b6c0174 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -5,8 +5,8 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(extern_types)] #![feature(file_buffered)] #![feature(impl_trait_in_assoc_type)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c7e90d3b3c330..42a4985d0231a 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,6 +1,6 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(file_buffered)] #![feature(negative_impls)] diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index e57d719a67a42..f42701d59b405 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,7 +1,7 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![feature(array_try_map)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(never_type)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index b01834aa80d9d..3bc6d9bd2ec10 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,7 +10,6 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(cfg_select))] #![cfg_attr(bootstrap, feature(cold_path))] #![cfg_attr(test, feature(test))] @@ -18,6 +17,7 @@ #![feature(allocator_api)] #![feature(ascii_char)] #![feature(ascii_char_variants)] +#![feature(assert_matches)] #![feature(auto_traits)] #![feature(const_default)] #![feature(const_trait_impl)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 837a41c191e15..5ff5bd7fe29b2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 40e79234d0201..a571094c9dc32 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -56,8 +56,8 @@ This API is completely unstable and subject to change. */ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(default_field_values)] #![feature(gen_blocks)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 15e94a27d559c..a96bd2da48ccd 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,6 +1,6 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(iter_intersperse)] #![feature(iter_order_by)] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 008b5c94a5eaa..2a1733ef63cb9 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -14,7 +14,7 @@ // tidy-alphabetical-start #![allow(rustc::direct_use_of_rustc_type_ir)] -#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(assert_matches)] #![feature(extend_one)] #![recursion_limit = "512"] // For rustdoc // tidy-alphabetical-end diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 34276eb76cf39..9da2125d964a3 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -21,8 +21,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(iter_order_by)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 615381b37cdb1..5f8f20147a9be 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,10 +27,10 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![cfg_attr(doc, feature(intra_doc_pointers))] #![feature(allocator_api)] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_as_ptr)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 7637ea81b0106..fcb5de69f0e44 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,8 +1,8 @@ //! Construction of MIR from HIR. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(try_blocks)] // tidy-alphabetical-end diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 692591a41a15b..5f1cf12501522 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(exact_size_is_empty)] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 7dd198ed9f9cc..51e100ef308d3 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,6 +1,6 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_type_name)] #![feature(cow_is_borrowed)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 1124f5830b6e6..6a0fe91493d5d 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,9 +1,9 @@ //! The main parser interface. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![cfg_attr(test, feature(iter_order_by))] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(default_field_values)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c12281a9e0ef0..949a96bc0ab99 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -8,10 +8,10 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))] #![feature(arbitrary_self_types)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_default)] #![feature(const_trait_impl)] diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 35a3d0dac8afa..7e126cb6a6e95 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,7 +88,7 @@ //! DefPaths which are much more robust in the face of changes to the code base. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(assert_matches)] // tidy-alphabetical-end use rustc_hir::def::DefKind; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5677a849d7495..72dbef0b37469 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,8 +11,8 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 2e21efbde1ac5..fbe7cdcd52977 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,8 +5,8 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(iterator_try_collect)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 73e93657b02f7..2e4b3e1e6300a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -89,6 +89,7 @@ #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(ascii_char)] +#![feature(assert_matches)] #![feature(async_fn_traits)] #![feature(async_iterator)] #![feature(bstr)] diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index e09d8495fdeac..4fbbf23116a5f 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -16,6 +16,7 @@ // tidy-alphabetical-start #![feature(allocator_api)] #![feature(array_into_iter_constructors)] +#![feature(assert_matches)] #![feature(char_internals)] #![feature(const_alloc_error)] #![feature(const_cmp)] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 60b26126cf6be..52f5a5382c90d 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -4,6 +4,7 @@ #![feature(const_heap)] #![feature(deque_extend_front)] #![feature(iter_array_chunks)] +#![feature(assert_matches)] #![feature(cow_is_borrowed)] #![feature(core_intrinsics)] #![feature(downcast_unchecked)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index fc9d314c7d057..c95f3cacbda2c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -205,7 +205,7 @@ use prelude::rust_2024::*; #[macro_use] mod macros; -#[stable(feature = "assert_matches", since = "1.95.0")] +#[unstable(feature = "assert_matches", issue = "82775")] pub use crate::macros::{assert_matches, debug_assert_matches}; #[unstable(feature = "derive_from", issue = "144889")] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 49e1acd0b90fb..c2d714d2b7877 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -147,6 +147,8 @@ macro_rules! assert_ne { /// # Examples /// /// ``` +/// #![feature(assert_matches)] +/// /// use std::assert_matches; /// /// let a = Some(345); @@ -164,7 +166,7 @@ macro_rules! assert_ne { /// assert_matches!(a, Some(x) if x > 100); /// // assert_matches!(a, Some(x) if x < 100); // panics /// ``` -#[stable(feature = "assert_matches", since = "1.95.0")] +#[unstable(feature = "assert_matches", issue = "82775")] #[allow_internal_unstable(panic_internals)] #[rustc_macro_transparency = "semiopaque"] pub macro assert_matches { @@ -374,6 +376,8 @@ macro_rules! debug_assert_ne { /// # Examples /// /// ``` +/// #![feature(assert_matches)] +/// /// use std::debug_assert_matches; /// /// let a = Some(345); @@ -391,7 +395,7 @@ macro_rules! debug_assert_ne { /// debug_assert_matches!(a, Some(x) if x > 100); /// // debug_assert_matches!(a, Some(x) if x < 100); // panics /// ``` -#[stable(feature = "assert_matches", since = "1.95.0")] +#[unstable(feature = "assert_matches", issue = "82775")] #[allow_internal_unstable(assert_matches)] #[rustc_macro_transparency = "semiopaque"] pub macro debug_assert_matches($($arg:tt)*) { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f047556671f21..b3425e4969ac0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -393,6 +393,7 @@ // // Only for re-exporting: // tidy-alphabetical-start +#![feature(assert_matches)] #![feature(async_iterator)] #![feature(c_variadic)] #![feature(cfg_accessible)] @@ -722,7 +723,7 @@ pub use core::{ assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented, unreachable, write, writeln, }; -#[stable(feature = "assert_matches", since = "1.95.0")] +#[unstable(feature = "assert_matches", issue = "82775")] pub use core::{assert_matches, debug_assert_matches}; // Re-export unstable derive macro defined through core. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 541ab3d1c295e..4258073e61047 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(assert_matches))] #![cfg_attr(bootstrap, feature(if_let_guard))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", @@ -7,6 +6,7 @@ )] #![feature(ascii_char)] #![feature(ascii_char_variants)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(file_buffered)] #![feature(formatting_options)] diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index f2f8cd583f31f..9f7f3e89cbe25 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3,7 +3,7 @@ #![feature(macro_metavar_expr)] #![feature(never_type)] #![feature(rustc_private)] -#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(assert_matches)] #![feature(unwrap_infallible)] #![recursion_limit = "512"] #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] diff --git a/tests/ui-fulldeps/rustc_public/check_abi.rs b/tests/ui-fulldeps/rustc_public/check_abi.rs index 8e97b773db567..256e267b7d303 100644 --- a/tests/ui-fulldeps/rustc_public/check_abi.rs +++ b/tests/ui-fulldeps/rustc_public/check_abi.rs @@ -6,6 +6,7 @@ //@ ignore-remote #![feature(rustc_private)] +#![feature(assert_matches)] #![feature(ascii_char, ascii_char_variants)] extern crate rustc_driver; diff --git a/tests/ui-fulldeps/rustc_public/check_allocation.rs b/tests/ui-fulldeps/rustc_public/check_allocation.rs index 580ce98329dc7..1acddc74cc0fd 100644 --- a/tests/ui-fulldeps/rustc_public/check_allocation.rs +++ b/tests/ui-fulldeps/rustc_public/check_allocation.rs @@ -8,6 +8,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; diff --git a/tests/ui-fulldeps/rustc_public/check_assoc_items.rs b/tests/ui-fulldeps/rustc_public/check_assoc_items.rs index ee0efd083588a..194d6be88a764 100644 --- a/tests/ui-fulldeps/rustc_public/check_assoc_items.rs +++ b/tests/ui-fulldeps/rustc_public/check_assoc_items.rs @@ -8,6 +8,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_coroutine_body.rs b/tests/ui-fulldeps/rustc_public/check_coroutine_body.rs index f988452fd52ba..75f4f1f5bf4c0 100644 --- a/tests/ui-fulldeps/rustc_public/check_coroutine_body.rs +++ b/tests/ui-fulldeps/rustc_public/check_coroutine_body.rs @@ -7,6 +7,7 @@ //@ edition: 2024 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_crate_defs.rs b/tests/ui-fulldeps/rustc_public/check_crate_defs.rs index 2b6a2ff8199ce..7d949eae39106 100644 --- a/tests/ui-fulldeps/rustc_public/check_crate_defs.rs +++ b/tests/ui-fulldeps/rustc_public/check_crate_defs.rs @@ -6,6 +6,7 @@ //@ ignore-remote #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_hir; extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_def_ty.rs b/tests/ui-fulldeps/rustc_public/check_def_ty.rs index 19ea731834b70..5984d6f8821a9 100644 --- a/tests/ui-fulldeps/rustc_public/check_def_ty.rs +++ b/tests/ui-fulldeps/rustc_public/check_def_ty.rs @@ -8,6 +8,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_defs.rs b/tests/ui-fulldeps/rustc_public/check_defs.rs index f3e27cdeb6043..0d472e156b40f 100644 --- a/tests/ui-fulldeps/rustc_public/check_defs.rs +++ b/tests/ui-fulldeps/rustc_public/check_defs.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_foreign.rs b/tests/ui-fulldeps/rustc_public/check_foreign.rs index 4670fd409b8f0..ea6d6585e51ec 100644 --- a/tests/ui-fulldeps/rustc_public/check_foreign.rs +++ b/tests/ui-fulldeps/rustc_public/check_foreign.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_instance.rs b/tests/ui-fulldeps/rustc_public/check_instance.rs index defea9d2f54bb..fd7523963fa9b 100644 --- a/tests/ui-fulldeps/rustc_public/check_instance.rs +++ b/tests/ui-fulldeps/rustc_public/check_instance.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_intrinsics.rs b/tests/ui-fulldeps/rustc_public/check_intrinsics.rs index 0cbb9659182a5..e3538a39f3371 100644 --- a/tests/ui-fulldeps/rustc_public/check_intrinsics.rs +++ b/tests/ui-fulldeps/rustc_public/check_intrinsics.rs @@ -10,6 +10,7 @@ //@ ignore-remote #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; extern crate rustc_hir; diff --git a/tests/ui-fulldeps/rustc_public/check_item_kind.rs b/tests/ui-fulldeps/rustc_public/check_item_kind.rs index b75ac70d86e3c..c687b3af1c632 100644 --- a/tests/ui-fulldeps/rustc_public/check_item_kind.rs +++ b/tests/ui-fulldeps/rustc_public/check_item_kind.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_trait_queries.rs b/tests/ui-fulldeps/rustc_public/check_trait_queries.rs index 44b7275a3df60..5603add82f591 100644 --- a/tests/ui-fulldeps/rustc_public/check_trait_queries.rs +++ b/tests/ui-fulldeps/rustc_public/check_trait_queries.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_transform.rs b/tests/ui-fulldeps/rustc_public/check_transform.rs index f8aa40e474468..815dec57b8be3 100644 --- a/tests/ui-fulldeps/rustc_public/check_transform.rs +++ b/tests/ui-fulldeps/rustc_public/check_transform.rs @@ -6,6 +6,7 @@ //@ ignore-remote #![feature(rustc_private)] +#![feature(assert_matches)] #![feature(ascii_char, ascii_char_variants)] extern crate rustc_hir; diff --git a/tests/ui-fulldeps/rustc_public/check_ty_fold.rs b/tests/ui-fulldeps/rustc_public/check_ty_fold.rs index 9ac7f14570e57..93cd304934409 100644 --- a/tests/ui-fulldeps/rustc_public/check_ty_fold.rs +++ b/tests/ui-fulldeps/rustc_public/check_ty_fold.rs @@ -8,6 +8,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/check_variant.rs b/tests/ui-fulldeps/rustc_public/check_variant.rs index 54ae8b8f83b97..9bdd0c9d80ba4 100644 --- a/tests/ui-fulldeps/rustc_public/check_variant.rs +++ b/tests/ui-fulldeps/rustc_public/check_variant.rs @@ -8,6 +8,7 @@ //@ edition: 2024 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/closure-generic-body.rs b/tests/ui-fulldeps/rustc_public/closure-generic-body.rs index a328bc396c544..46aeca76ba650 100644 --- a/tests/ui-fulldeps/rustc_public/closure-generic-body.rs +++ b/tests/ui-fulldeps/rustc_public/closure-generic-body.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/closure_body.rs b/tests/ui-fulldeps/rustc_public/closure_body.rs index 880d7dde34b68..43cbca8baab87 100644 --- a/tests/ui-fulldeps/rustc_public/closure_body.rs +++ b/tests/ui-fulldeps/rustc_public/closure_body.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/compilation-result.rs b/tests/ui-fulldeps/rustc_public/compilation-result.rs index 351ca2c8295f4..d33e602e8191a 100644 --- a/tests/ui-fulldeps/rustc_public/compilation-result.rs +++ b/tests/ui-fulldeps/rustc_public/compilation-result.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/crate-info.rs b/tests/ui-fulldeps/rustc_public/crate-info.rs index 3729aa7609b51..9bf865c54eeef 100644 --- a/tests/ui-fulldeps/rustc_public/crate-info.rs +++ b/tests/ui-fulldeps/rustc_public/crate-info.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_hir; extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/projections.rs b/tests/ui-fulldeps/rustc_public/projections.rs index e864bb9648db5..53baace827a02 100644 --- a/tests/ui-fulldeps/rustc_public/projections.rs +++ b/tests/ui-fulldeps/rustc_public/projections.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_hir; extern crate rustc_middle; diff --git a/tests/ui-fulldeps/rustc_public/smir_internal.rs b/tests/ui-fulldeps/rustc_public/smir_internal.rs index 98335da19dbde..b74bdfe4eb194 100644 --- a/tests/ui-fulldeps/rustc_public/smir_internal.rs +++ b/tests/ui-fulldeps/rustc_public/smir_internal.rs @@ -8,6 +8,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_driver; extern crate rustc_interface; diff --git a/tests/ui-fulldeps/rustc_public/smir_serde.rs b/tests/ui-fulldeps/rustc_public/smir_serde.rs index 6a345023de171..972bc5efe206c 100644 --- a/tests/ui-fulldeps/rustc_public/smir_serde.rs +++ b/tests/ui-fulldeps/rustc_public/smir_serde.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_driver; diff --git a/tests/ui-fulldeps/rustc_public/smir_visitor.rs b/tests/ui-fulldeps/rustc_public/smir_visitor.rs index 1ea2ab6f560ff..9438f46a59b5a 100644 --- a/tests/ui-fulldeps/rustc_public/smir_visitor.rs +++ b/tests/ui-fulldeps/rustc_public/smir_visitor.rs @@ -7,6 +7,7 @@ //@ edition: 2021 #![feature(rustc_private)] +#![feature(assert_matches)] extern crate rustc_middle; diff --git a/tests/ui/coroutine/uninhabited-field.rs b/tests/ui/coroutine/uninhabited-field.rs index 6debd89ef4a9e..bc1f8d7733716 100644 --- a/tests/ui/coroutine/uninhabited-field.rs +++ b/tests/ui/coroutine/uninhabited-field.rs @@ -1,6 +1,7 @@ // Test that uninhabited saved local doesn't make the entire variant uninhabited. //@ run-pass #![allow(unused)] +#![feature(assert_matches)] #![feature(coroutine_trait)] #![feature(coroutines, stmt_expr_attributes)] #![feature(never_type)] diff --git a/tests/ui/macros/assert-matches-macro-msg.rs b/tests/ui/macros/assert-matches-macro-msg.rs index 17900936a299b..8f4cd254f56b7 100644 --- a/tests/ui/macros/assert-matches-macro-msg.rs +++ b/tests/ui/macros/assert-matches-macro-msg.rs @@ -4,6 +4,8 @@ //@ error-pattern: right: 3 //@ needs-subprocess +#![feature(assert_matches)] + use std::assert_matches; fn main() { diff --git a/tests/ui/stdlib-unit-tests/matches2021.rs b/tests/ui/stdlib-unit-tests/matches2021.rs index 0958e82f43e42..c3276cd883471 100644 --- a/tests/ui/stdlib-unit-tests/matches2021.rs +++ b/tests/ui/stdlib-unit-tests/matches2021.rs @@ -3,6 +3,8 @@ // regression test for https://github.com/rust-lang/rust/pull/85678 +#![feature(assert_matches)] + use std::assert_matches; fn main() { From 2c2e33ac599aed6da12fa4be8b0a373e2eaff424 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Apr 2026 09:29:27 +0200 Subject: [PATCH 05/11] Revert performing basic const checks in typeck on stable --- compiler/rustc_hir_typeck/src/callee.rs | 8 ++ tests/crashes/137187.rs | 7 +- tests/ui/coercion/coerce-loop-issue-122561.rs | 8 -- .../coercion/coerce-loop-issue-122561.stderr | 105 +++--------------- .../const_raw_ptr_ops.stable.stderr | 9 +- tests/ui/consts/const-fn-error.rs | 4 +- tests/ui/consts/const-fn-error.stderr | 16 ++- tests/ui/consts/const-for-feature-gate.rs | 4 +- tests/ui/consts/const-for-feature-gate.stderr | 16 ++- tests/ui/consts/const-for.rs | 4 +- tests/ui/consts/const-for.stderr | 16 ++- tests/ui/consts/control-flow/loop.rs | 8 +- tests/ui/consts/control-flow/loop.stderr | 30 +++-- ...t-fn-ptr-binders-during-ctfe.stable.stderr | 5 +- tests/ui/consts/issue-25826.stderr | 5 +- .../min_const_fn/cmp_fn_pointers.stderr | 5 +- .../feature-gate-diagnostic-on-const.rs | 2 +- .../feature-gate-diagnostic-on-const.stderr | 7 +- tests/ui/issues/issue-25901.rs | 9 +- tests/ui/issues/issue-25901.stderr | 19 +++- .../for-loop-in-vec-type-mismatchrs-50585.rs | 2 - ...r-loop-in-vec-type-mismatchrs-50585.stderr | 24 +--- tests/ui/never_type/issue-52443.rs | 4 +- tests/ui/never_type/issue-52443.stderr | 18 ++- .../arbitrary-self-from-method-substs-ice.rs | 3 +- ...bitrary-self-from-method-substs-ice.stderr | 24 +++- .../derive-const-non-const-type.rs | 2 +- .../derive-const-non-const-type.stderr | 9 +- tests/ui/traits/const-traits/cross-crate.rs | 5 +- .../const-traits/cross-crate.stock.stderr | 2 +- .../const-traits/cross-crate.stocknc.stderr | 24 ++-- tests/ui/traits/const-traits/gate.rs | 1 - tests/ui/traits/const-traits/gate.stderr | 13 +-- .../super-traits-fail-3.nyn.stderr | 10 +- .../const-traits/super-traits-fail-3.rs | 4 +- tests/ui/typeck/for-in-const-eval.rs | 2 - tests/ui/typeck/for-in-const-eval.stderr | 21 +--- 37 files changed, 166 insertions(+), 289 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 3d044c1086b06..8eb270dd1bc00 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -921,6 +921,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_did: DefId, callee_args: GenericArgsRef<'tcx>, ) { + // FIXME(const_trait_impl): We should be enforcing these effects unconditionally. + // This can be done as soon as we convert the standard library back to + // using const traits, since if we were to enforce these conditions now, + // we'd fail on basically every builtin trait call (i.e. `1 + 2`). + if !self.tcx.features().const_trait_impl() { + return; + } + // If we have `rustc_do_not_const_check`, do not check `[const]` bounds. if self.has_rustc_attrs && find_attr!(self.tcx, self.body_id, RustcDoNotConstCheck) { return; diff --git a/tests/crashes/137187.rs b/tests/crashes/137187.rs index 554275441ff0e..f63b459de9d03 100644 --- a/tests/crashes/137187.rs +++ b/tests/crashes/137187.rs @@ -1,13 +1,10 @@ //@ known-bug: #137187 -#![feature(const_trait_impl, const_ops)] - use std::ops::Add; + const trait A where - *const Self: const Add, + *const Self: Add, { fn b(c: *const Self) -> <*const Self as Add>::Output { c + c } } - -fn main() {} diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs index 5f6f91e37d2ed..d79dfa28b0daf 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.rs +++ b/tests/ui/coercion/coerce-loop-issue-122561.rs @@ -42,8 +42,6 @@ fn for_single_line() -> bool { for i in 0.. { return false; } } // that it's readable fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { //~^ ERROR mismatched types - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied true } @@ -88,8 +86,6 @@ fn loop_() -> bool { const C: i32 = { for i in 0.. { //~^ ERROR mismatched types - //~| ERROR `std::ops::RangeFrom<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::RangeFrom<{integer}>: const Iterator` is not satisfied } }; @@ -97,8 +93,6 @@ fn main() { let _ = [10; { for i in 0..5 { //~^ ERROR mismatched types - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied } }]; @@ -111,6 +105,4 @@ fn main() { let _ = |a: &[(); for x in 0..2 {}]| {}; //~^ ERROR mismatched types - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied } diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index a7621e0d9363d..3fd6671565f18 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:51:5 + --> $DIR/coerce-loop-issue-122561.rs:49:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` @@ -7,30 +7,11 @@ LL | while true { = note: `#[warn(while_true)]` on by default warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:75:5 + --> $DIR/coerce-loop-issue-122561.rs:73:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:43:33 - | -LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { - | ^^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:43:33 - | -LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { - | ^^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0308]: mismatched types --> $DIR/coerce-loop-issue-122561.rs:43:24 | @@ -131,7 +112,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val | ++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:51:5 + --> $DIR/coerce-loop-issue-122561.rs:49:5 | LL | fn while_inifinite() -> bool { | ---- expected `bool` because of return type @@ -150,7 +131,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:60:5 + --> $DIR/coerce-loop-issue-122561.rs:58:5 | LL | fn while_finite() -> bool { | ---- expected `bool` because of return type @@ -170,7 +151,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:68:5 + --> $DIR/coerce-loop-issue-122561.rs:66:5 | LL | fn while_zero_times() -> bool { | ---- expected `bool` because of return type @@ -188,7 +169,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:75:5 + --> $DIR/coerce-loop-issue-122561.rs:73:5 | LL | fn while_never_type() -> ! { | - expected `!` because of return type @@ -206,30 +187,11 @@ LL ~ } LL + /* `loop {}` or `panic!("...")` */ | -error[E0277]: the trait bound `std::ops::RangeFrom<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:89:14 - | -LL | for i in 0.. { - | ^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::RangeFrom<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::RangeFrom<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:89:14 - | -LL | for i in 0.. { - | ^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:89:5 + --> $DIR/coerce-loop-issue-122561.rs:87:5 | LL | / for i in 0.. { -... | +LL | | LL | | } | |_____^ expected `i32`, found `()` | @@ -240,30 +202,11 @@ LL ~ } LL + /* `i32` value */ | -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:98:18 - | -LL | for i in 0..5 { - | ^^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:98:18 - | -LL | for i in 0..5 { - | ^^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:98:9 + --> $DIR/coerce-loop-issue-122561.rs:94:9 | LL | / for i in 0..5 { -... | +LL | | LL | | } | |_________^ expected `usize`, found `()` | @@ -275,7 +218,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:106:9 + --> $DIR/coerce-loop-issue-122561.rs:100:9 | LL | / while false { LL | | @@ -289,27 +232,8 @@ LL ~ } LL + /* `usize` value */ | -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:112:32 - | -LL | let _ = |a: &[(); for x in 0..2 {}]| {}; - | ^^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/coerce-loop-issue-122561.rs:112:32 - | -LL | let _ = |a: &[(); for x in 0..2 {}]| {}; - | ^^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:112:23 + --> $DIR/coerce-loop-issue-122561.rs:106:23 | LL | let _ = |a: &[(); for x in 0..2 {}]| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` @@ -320,7 +244,6 @@ help: consider returning a value here LL | let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {}; | +++++++++++++++++++ -error: aborting due to 22 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops.stable.stderr b/tests/ui/consts/const-eval/const_raw_ptr_ops.stable.stderr index c39048c8f283c..2c7e6e8671351 100644 --- a/tests/ui/consts/const-eval/const_raw_ptr_ops.stable.stderr +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops.stable.stderr @@ -1,23 +1,18 @@ -error[E0277]: pointers cannot be reliably compared during const eval +error: pointers cannot be reliably compared during const eval --> $DIR/const_raw_ptr_ops.rs:7:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: trait `PartialEq` is implemented but not `const` - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL = note: see issue #53020 for more information -error[E0277]: pointers cannot be reliably compared during const eval +error: pointers cannot be reliably compared during const eval --> $DIR/const_raw_ptr_ops.rs:9:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: trait `PartialEq` is implemented but not `const` - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL = note: see issue #53020 for more information error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs index 67053225e0a53..b71517824232f 100644 --- a/tests/ui/consts/const-fn-error.rs +++ b/tests/ui/consts/const-fn-error.rs @@ -3,8 +3,8 @@ const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; for i in 0..x { - //~^ ERROR `std::ops::Range: [const] Iterator` is not satisfied - //~| ERROR `std::ops::Range: [const] Iterator` is not satisfied + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` sum += i; } sum diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index f95cb47f22c5e..3d4cf6539c896 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -1,22 +1,20 @@ -error[E0277]: the trait bound `std::ops::Range: [const] Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { - | ^^^^ required by a bound introduced by this call + | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range` to implement `[const] IntoIterator` + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::Range: [const] Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index f361efdce8e3e..b643e63c09690 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -2,8 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 3369ba8147a1b..29db5d24ac866 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -1,22 +1,20 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} - | ^^^^ required by a bound introduced by this call + | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index b6d5ca70cfeb3..6f7895457c53d 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -2,8 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 3cb4816fdbe4e..d1308a8dedc85 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -1,22 +1,20 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} - | ^^^^ required by a bound introduced by this call + | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index 5311daec6143f..b02c31c4c25b5 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -51,14 +51,14 @@ const _: i32 = { let mut x = 0; for i in 0..4 { - //~^ ERROR: `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR: `std::ops::Range<{integer}>: const Iterator` is not satisfied + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } for i in 0..4 { - //~^ ERROR: `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR: `std::ops::Range<{integer}>: const Iterator` is not satisfied + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index ec821d23a619c..b91371f9dc218 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -1,41 +1,37 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { - | ^^^^ required by a bound introduced by this call + | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { - | ^^^^ required by a bound introduced by this call + | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { | ^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stable.stderr b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stable.stderr index f13e0c6661814..92b09e7db0d45 100644 --- a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stable.stderr +++ b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stable.stderr @@ -1,13 +1,10 @@ -error[E0277]: pointers cannot be reliably compared during const eval +error: pointers cannot be reliably compared during const eval --> $DIR/different-fn-ptr-binders-during-ctfe.rs:5:5 | LL | x == y | ^^^^^^ | -note: trait `PartialEq` is implemented but not `const` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL = note: see issue #53020 for more information error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-25826.stderr b/tests/ui/consts/issue-25826.stderr index 9c03f1270d656..7d21020da6477 100644 --- a/tests/ui/consts/issue-25826.stderr +++ b/tests/ui/consts/issue-25826.stderr @@ -1,13 +1,10 @@ -error[E0277]: pointers cannot be reliably compared during const eval +error: pointers cannot be reliably compared during const eval --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: trait `PartialOrd` is implemented but not `const` - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL = note: see issue #53020 for more information error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr index 47887a6c68b92..bfaccf1db1ca4 100644 --- a/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr +++ b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -1,13 +1,10 @@ -error[E0277]: pointers cannot be reliably compared during const eval +error: pointers cannot be reliably compared during const eval --> $DIR/cmp_fn_pointers.rs:2:14 | LL | unsafe { x == y } | ^^^^^^ | -note: trait `PartialEq` is implemented but not `const` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL = note: see issue #53020 for more information error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs b/tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs index 890e4aa5a601d..398fa30e74047 100644 --- a/tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs +++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs @@ -10,7 +10,7 @@ use diagnostic_on_const::Foo; const fn foo() { Foo == Foo; - //~^ ERROR: the trait bound `Foo: [const] PartialEq` is not satisfied + //~^ ERROR: cannot call non-const operator in constant functions } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-const.stderr b/tests/ui/feature-gates/feature-gate-diagnostic-on-const.stderr index 4e2a573f72d78..04c901f4f938b 100644 --- a/tests/ui/feature-gates/feature-gate-diagnostic-on-const.stderr +++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-const.stderr @@ -1,15 +1,16 @@ -error[E0277]: the trait bound `Foo: [const] PartialEq` is not satisfied +error[E0015]: cannot call non-const operator in constant functions --> $DIR/feature-gate-diagnostic-on-const.rs:12:5 | LL | Foo == Foo; | ^^^^^^^^^^ | -note: trait `PartialEq` is implemented but not `const` +note: impl defined here, but it is not `const` --> $DIR/auxiliary/diagnostic-on-const.rs:4:1 | LL | impl PartialEq for Foo { | ^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-25901.rs b/tests/ui/issues/issue-25901.rs index d40b869cd0cd8..4a3a197a582fc 100644 --- a/tests/ui/issues/issue-25901.rs +++ b/tests/ui/issues/issue-25901.rs @@ -2,13 +2,16 @@ struct A; struct B; static S: &'static B = &A; -//~^ ERROR the trait bound `A: const Deref` is not satisfied +//~^ ERROR cannot perform non-const deref coercion on `A` in statics use std::ops::Deref; impl Deref for A { type Target = B; - fn deref(&self)->&B { static B_: B = B; &B_ } + fn deref(&self) -> &B { + static B_: B = B; + &B_ + } } -fn main(){} +fn main() {} diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr index 9b65366b969a5..233b5bfee5075 100644 --- a/tests/ui/issues/issue-25901.stderr +++ b/tests/ui/issues/issue-25901.stderr @@ -1,14 +1,23 @@ -error[E0277]: the trait bound `A: const Deref` is not satisfied +error[E0015]: cannot perform non-const deref coercion on `A` in statics --> $DIR/issue-25901.rs:4:24 | LL | static S: &'static B = &A; | ^^ | -help: make the `impl` of trait `Deref` `const` + = note: attempting to deref into `B` +note: deref defined here + --> $DIR/issue-25901.rs:10:5 | -LL | impl const Deref for A { - | +++++ +LL | type Target = B; + | ^^^^^^^^^^^ +note: impl defined here, but it is not `const` + --> $DIR/issue-25901.rs:9:1 + | +LL | impl Deref for A { + | ^^^^^^^^^^^^^^^^ + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.rs b/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.rs index 1197eac72706a..4abef0bee81bd 100644 --- a/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.rs +++ b/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.rs @@ -2,6 +2,4 @@ fn main() { |y: Vec<[(); for x in 0..2 {}]>| {}; //~^ ERROR mismatched types - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied - //~| ERROR `std::ops::Range<{integer}>: const Iterator` is not satisfied } diff --git a/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.stderr b/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.stderr index 31287eda9600d..d60d97a02ab12 100644 --- a/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.stderr +++ b/tests/ui/mismatched_types/for-loop-in-vec-type-mismatchrs-50585.stderr @@ -1,22 +1,3 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/for-loop-in-vec-type-mismatchrs-50585.rs:3:27 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/for-loop-in-vec-type-mismatchrs-50585.rs:3:27 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0308]: mismatched types --> $DIR/for-loop-in-vec-type-mismatchrs-50585.rs:3:18 | @@ -29,7 +10,6 @@ help: consider returning a value here LL | |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {}; | +++++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs index f505719bfcee4..0e454eeb9ad35 100644 --- a/tests/ui/never_type/issue-52443.rs +++ b/tests/ui/never_type/issue-52443.rs @@ -7,6 +7,6 @@ fn main() { //~^ WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; - //~^ ERROR `std::ops::RangeFrom: const Iterator` is not satisfied - //~| ERROR `std::ops::RangeFrom: const Iterator` is not satisfied + //~^ ERROR cannot use `for` loop on `std::ops::RangeFrom` in constants + //~| ERROR cannot use `for` loop on `std::ops::RangeFrom` in constants } diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index d754bc415781c..bb60c33595c25 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -31,26 +31,24 @@ help: give the `break` a value of the expected type LL | [(); loop { break 42 }]; | ++ -error[E0277]: the trait bound `std::ops::RangeFrom: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ required by a bound introduced by this call + | ^^^^^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::RangeFrom` to implement `const IntoIterator` + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0277]: the trait bound `std::ops::RangeFrom: const Iterator` is not satisfied +error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0015, E0308. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs index da3f385a3bcbc..46e4afd8532e1 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.rs +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.rs @@ -9,8 +9,9 @@ struct Foo(u32); impl Foo { const fn get>(self: R) -> u32 { //~^ ERROR invalid generic `self` parameter type + //~| ERROR destructor of `R` cannot be evaluated at compile-time self.0 - //~^ ERROR the trait bound `R: [const] Deref` is not satisfied + //~^ ERROR cannot perform non-const deref coercion on `R` in constant functions } } diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr index 0ea6b68d232ca..f217370b024b5 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -1,8 +1,20 @@ -error[E0277]: the trait bound `R: [const] Deref` is not satisfied - --> $DIR/arbitrary-self-from-method-substs-ice.rs:12:9 +error[E0015]: cannot perform non-const deref coercion on `R` in constant functions + --> $DIR/arbitrary-self-from-method-substs-ice.rs:13:9 | LL | self.0 - | ^^^^ + | ^^^^^^ + | + = note: attempting to deref into `Foo` + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0493]: destructor of `R` cannot be evaluated at compile-time + --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43 + | +LL | const fn get>(self: R) -> u32 { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here error[E0801]: invalid generic `self` parameter type: `R` --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49 @@ -13,7 +25,7 @@ LL | const fn get>(self: R) -> u32 { = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0801. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0015, E0493, E0801. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs index ae5899f084465..e61ae2760aab8 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs @@ -10,6 +10,6 @@ impl Default for A { #[derive_const(Default)] pub struct S(A); -//~^ ERROR: `A: [const] Default` is not satisfied +//~^ ERROR: cannot call non-const associated function fn main() {} diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr index ba6fb140f424e..5589579853283 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `A: [const] Default` is not satisfied +error[E0015]: cannot call non-const associated function `::default` in constant functions --> $DIR/derive-const-non-const-type.rs:12:14 | LL | #[derive_const(Default)] @@ -6,11 +6,8 @@ LL | #[derive_const(Default)] LL | pub struct S(A); | ^ | -help: make the `impl` of trait `Default` `const` - | -LL | impl const Default for A { - | +++++ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/cross-crate.rs b/tests/ui/traits/const-traits/cross-crate.rs index a91201e3566b4..b07aa8944c05d 100644 --- a/tests/ui/traits/const-traits/cross-crate.rs +++ b/tests/ui/traits/const-traits/cross-crate.rs @@ -17,9 +17,10 @@ fn non_const_context() { const fn const_context() { #[cfg(any(stocknc, gatednc))] NonConst.func(); - //[stocknc,gatednc]~^ ERROR: the trait bound + //[stocknc]~^ ERROR: cannot call + //[gatednc]~^^ ERROR: the trait bound Const.func(); - //[stock]~^ ERROR: cannot call + //[stock,stocknc]~^ ERROR: cannot call } fn main() {} diff --git a/tests/ui/traits/const-traits/cross-crate.stock.stderr b/tests/ui/traits/const-traits/cross-crate.stock.stderr index 606793cd3149d..44a60c99ae9ea 100644 --- a/tests/ui/traits/const-traits/cross-crate.stock.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: cannot call conditionally-const method `::func` in constant functions - --> $DIR/cross-crate.rs:21:11 + --> $DIR/cross-crate.rs:22:11 | LL | Const.func(); | ^^^^^^ diff --git a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr index 45e06c78cfb25..766c20aa8211f 100644 --- a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr @@ -1,15 +1,23 @@ -error[E0277]: the trait bound `cross_crate::NonConst: [const] cross_crate::MyTrait` is not satisfied +error[E0015]: cannot call non-const method `::func` in constant functions --> $DIR/cross-crate.rs:19:14 | LL | NonConst.func(); - | ^^^^ + | ^^^^^^ | -note: trait `MyTrait` is implemented but not `const` - --> $DIR/auxiliary/cross-crate.rs:11:1 + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0658]: cannot call conditionally-const method `::func` in constant functions + --> $DIR/cross-crate.rs:22:11 + | +LL | Const.func(); + | ^^^^^^ | -LL | impl MyTrait for NonConst { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/gate.rs b/tests/ui/traits/const-traits/gate.rs index 3f348c8413930..d1c93ab9f95af 100644 --- a/tests/ui/traits/const-traits/gate.rs +++ b/tests/ui/traits/const-traits/gate.rs @@ -3,7 +3,6 @@ fn main() { (const || {})(); //~^ ERROR: const closures are experimental - //~| ERROR: the trait bound `{closure@$DIR/gate.rs:4:6: 4:14}: [const] Fn()` is not satisfied } macro_rules! e { diff --git a/tests/ui/traits/const-traits/gate.stderr b/tests/ui/traits/const-traits/gate.stderr index 6bef2c511ce7d..19fd54ff36983 100644 --- a/tests/ui/traits/const-traits/gate.stderr +++ b/tests/ui/traits/const-traits/gate.stderr @@ -9,7 +9,7 @@ LL | (const || {})(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const closures are experimental - --> $DIR/gate.rs:13:5 + --> $DIR/gate.rs:12:5 | LL | e!((const || {})); | ^^^^^ @@ -18,13 +18,6 @@ LL | e!((const || {})); = help: add `#![feature(const_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0277]: the trait bound `{closure@$DIR/gate.rs:4:6: 4:14}: [const] Fn()` is not satisfied - --> $DIR/gate.rs:4:5 - | -LL | (const || {})(); - | ^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr index 42b051cd8df82..1c56aa1297944 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr @@ -83,13 +83,15 @@ help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `co LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | +++++ -error[E0277]: the trait bound `T: [const] Foo` is not satisfied +error[E0015]: cannot call non-const method `::a` in constant functions --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); - | ^ + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 9 previous errors -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs index 55e8d3ca6e6ad..7dd434c528d09 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -36,8 +36,8 @@ const fn foo(x: &T) { //[yyn,ynn,nyn,nnn]~| ERROR: `[const]` can only be applied to `const` traits //[nyy,nyn,nny,nnn]~^^^ ERROR: const trait impls are experimental x.a(); - //[yyn,nyn]~^ ERROR: the trait bound `T: [const] Foo` is not satisfied - //[ynn,yny,nny,nnn]~^^ ERROR: cannot call non-const method `::a` in constant functions + //[yyn]~^ ERROR: the trait bound `T: [const] Foo` is not satisfied + //[ynn,yny,nny,nnn,nyn]~^^ ERROR: cannot call non-const method `::a` in constant functions //[nyy]~^^^ ERROR: cannot call conditionally-const method `::a` in constant functions } diff --git a/tests/ui/typeck/for-in-const-eval.rs b/tests/ui/typeck/for-in-const-eval.rs index 8de969e3eee05..f187a9ef30771 100644 --- a/tests/ui/typeck/for-in-const-eval.rs +++ b/tests/ui/typeck/for-in-const-eval.rs @@ -2,6 +2,4 @@ fn main() { Vec::<[(); 1 + for x in 0..1 {}]>::new(); //~^ ERROR cannot add - //~| ERROR const Iterator` is not satisfied - //~| ERROR const Iterator` is not satisfied } diff --git a/tests/ui/typeck/for-in-const-eval.stderr b/tests/ui/typeck/for-in-const-eval.stderr index 343da0f25ecd1..e7a2558495813 100644 --- a/tests/ui/typeck/for-in-const-eval.stderr +++ b/tests/ui/typeck/for-in-const-eval.stderr @@ -1,22 +1,3 @@ -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/for-in-const-eval.rs:3:29 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^ required by a bound introduced by this call - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - = note: required for `std::ops::Range<{integer}>` to implement `const IntoIterator` - -error[E0277]: the trait bound `std::ops::Range<{integer}>: const Iterator` is not satisfied - --> $DIR/for-in-const-eval.rs:3:29 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^ - | -note: trait `Iterator` is implemented but not `const` - --> $SRC_DIR/core/src/iter/range.rs:LL:COL - error[E0277]: cannot add `()` to `{integer}` --> $DIR/for-in-const-eval.rs:3:18 | @@ -35,6 +16,6 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); `&f64` implements `Add` and 56 others -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. From 524789f8ab7b11a71f21572ca9f649051e8d4cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 2 Apr 2026 12:13:21 +0200 Subject: [PATCH 06/11] Revert "Rollup merge of #149904 - ShoyuVanilla:ns-remove-sg-hack, r=lcnr" This reverts commit c108ad5617dbcb0e782a67b8de9f508c8a78e651, reversing changes made to 485f76b835abe0aa4c3c1578c16d0abee54079d3. (cherry picked from commit 22faa52629f3458e07c442fdd8c1ed1af1996831) --- .../rustc_type_ir/src/search_graph/mod.rs | 31 +++++++++++-- .../global-where-bound-normalization.rs | 45 ------------------- 2 files changed, 28 insertions(+), 48 deletions(-) delete mode 100644 tests/ui/traits/next-solver/global-where-bound-normalization.rs diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 7c58cd7303ebc..8e6376b22ce61 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -916,9 +916,10 @@ impl, X: Cx> SearchGraph { /// heads from the stack. This may not necessarily mean that we've actually /// reached a fixpoint for that cycle head, which impacts the way we rebase /// provisional cache entries. -#[derive(Debug)] -enum RebaseReason { +#[derive_where(Debug; X: Cx)] +enum RebaseReason { NoCycleUsages, + Ambiguity(X::AmbiguityInfo), Overflow, /// We've actually reached a fixpoint. /// @@ -955,7 +956,7 @@ impl, X: Cx> SearchGraph { &mut self, cx: X, stack_entry: &StackEntry, - rebase_reason: RebaseReason, + rebase_reason: RebaseReason, ) { let popped_head_index = self.stack.next_index(); #[allow(rustc::potential_query_instability)] @@ -1034,6 +1035,9 @@ impl, X: Cx> SearchGraph { // is not actually equal to the final provisional result. We // need to discard the provisional cache entry in this case. RebaseReason::NoCycleUsages => return false, + RebaseReason::Ambiguity(info) => { + *result = D::propagate_ambiguity(cx, input, info); + } RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input), RebaseReason::ReachedFixpoint(None) => {} RebaseReason::ReachedFixpoint(Some(path_kind)) => { @@ -1348,6 +1352,27 @@ impl, X: Cx> SearchGraph { return EvaluationResult::finalize(stack_entry, encountered_overflow, result); } + // If computing this goal results in ambiguity with no constraints, + // we do not rerun it. It's incredibly difficult to get a different + // response in the next iteration in this case. These changes would + // likely either be caused by incompleteness or can change the maybe + // cause from ambiguity to overflow. Returning ambiguity always + // preserves soundness and completeness even if the goal is be known + // to succeed or fail. + // + // This prevents exponential blowup affecting multiple major crates. + // As we only get to this branch if we haven't yet reached a fixpoint, + // we also taint all provisional cache entries which depend on the + // current goal. + if let Some(info) = D::is_ambiguous_result(result) { + self.rebase_provisional_cache_entries( + cx, + &stack_entry, + RebaseReason::Ambiguity(info), + ); + return EvaluationResult::finalize(stack_entry, encountered_overflow, result); + }; + // If we've reached the fixpoint step limit, we bail with overflow and taint all // provisional cache entries which depend on the current goal. i += 1; diff --git a/tests/ui/traits/next-solver/global-where-bound-normalization.rs b/tests/ui/traits/next-solver/global-where-bound-normalization.rs deleted file mode 100644 index e57fbf378a0d2..0000000000000 --- a/tests/ui/traits/next-solver/global-where-bound-normalization.rs +++ /dev/null @@ -1,45 +0,0 @@ -//@ check-pass -//@ compile-flags: -Znext-solver - -// Regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/257. - -#![feature(rustc_attrs)] -#![expect(internal_features)] -#![rustc_no_implicit_bounds] - -pub trait Bound {} -impl Bound for u8 {} - -pub trait Proj { - type Assoc; -} -impl Proj for U { - type Assoc = U; -} -impl Proj for MyField { - type Assoc = u8; -} - -// While wf-checking the global bounds of `fn foo`, elaborating this outlives predicate triggered a -// cycle in the search graph along a particular probe path, which was not an actual solution. -// That cycle then resulted in a forced false-positive ambiguity due to a performance hack in the -// search graph and then ended up floundering the root goal evaluation. -pub trait Field: Proj {} - -struct MyField; -impl Field for MyField {} - -trait IdReqField { - type This; -} -impl IdReqField for F { - type This = F; -} - -fn foo() -where - ::This: Field, -{ -} - -fn main() {} From 2b3d5e6a416738c0fc8a0f48bc2321d75878cbe8 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 8 Apr 2026 14:00:50 -0400 Subject: [PATCH 07/11] Clarify that `core::range::RangeInclusive` does not have special syntax I'm ignoring the fact that there's a feature to change the behavior of the syntax. I just want to help prevent confusing the people reading the docs. (cherry picked from commit 092f0ca1bd6ce2e96796ab82c3325750a2254e38) --- library/core/src/range.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 7a344d358fdb8..28286c761c99e 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -228,21 +228,24 @@ impl const From> for Range { } } -/// A range bounded inclusively below and above (`start..=last`). +/// A range bounded inclusively below and above. /// -/// The `RangeInclusive` `start..=last` contains all values with `x >= start` +/// The `RangeInclusive` contains all values with `x >= start` /// and `x <= last`. It is empty unless `start <= last`. /// /// # Examples /// -/// The `start..=last` syntax is a `RangeInclusive`: -/// /// ``` /// use core::range::RangeInclusive; /// /// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 }); /// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum()); /// ``` +/// +/// # Edition notes +/// +/// It is planned that the syntax `start..=last` will construct this +/// type in a future edition, but it does not do so today. #[lang = "RangeInclusiveCopy"] #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[stable(feature = "new_range_inclusive_api", since = "1.95.0")] From 6ae56934abe679858fcc12b3f7b75d92f8345d48 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 8 Apr 2026 14:01:34 -0400 Subject: [PATCH 08/11] Clarify that `core::range::{Range,RangeFrom,RangeToInclusive}` do not have special syntax I'm ignoring the fact that there's a feature to change the behavior of the syntax. I just want to help prevent confusing the people reading the docs. (cherry picked from commit eef43634035830f5572a6cb204c1b4e9ad46c468) --- library/core/src/range.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 28286c761c99e..7c96073a71331 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -45,10 +45,9 @@ use crate::iter::Step; use crate::ops::Bound::{self, Excluded, Included, Unbounded}; use crate::ops::{IntoBounds, RangeBounds}; -/// A (half-open) range bounded inclusively below and exclusively above -/// (`start..end` in a future edition). +/// A (half-open) range bounded inclusively below and exclusively above. /// -/// The range `start..end` contains all values with `start <= x < end`. +/// The `Range` contains all values with `start <= x < end`. /// It is empty if `start >= end`. /// /// # Examples @@ -60,6 +59,11 @@ use crate::ops::{IntoBounds, RangeBounds}; /// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 }); /// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum()); /// ``` +/// +/// # Edition notes +/// +/// It is planned that the syntax `start..end` will construct this +/// type in a future edition, but it does not do so today. #[lang = "RangeCopy"] #[derive(Copy, Hash)] #[derive_const(Clone, Default, PartialEq, Eq)] @@ -415,9 +419,9 @@ impl const From> for RangeInclusive { } } -/// A range only bounded inclusively below (`start..`). +/// A range only bounded inclusively below. /// -/// The `RangeFrom` `start..` contains all values with `x >= start`. +/// The `RangeFrom` contains all values with `x >= start`. /// /// *Note*: Overflow in the [`Iterator`] implementation (when the contained /// data type reaches its numerical limit) is allowed to panic, wrap, or @@ -432,8 +436,6 @@ impl const From> for RangeInclusive { /// /// # Examples /// -/// The `start..` syntax is a `RangeFrom`: -/// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeFrom; @@ -441,6 +443,11 @@ impl const From> for RangeInclusive { /// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 }); /// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum()); /// ``` +/// +/// # Edition notes +/// +/// It is planned that the syntax `start..` will construct this +/// type in a future edition, but it does not do so today. #[lang = "RangeFromCopy"] #[derive(Copy, Hash)] #[derive_const(Clone, PartialEq, Eq)] @@ -566,15 +573,13 @@ impl const From> for RangeFrom { } } -/// A range only bounded inclusively above (`..=last`). +/// A range only bounded inclusively above. /// -/// The `RangeToInclusive` `..=last` contains all values with `x <= last`. +/// The `RangeToInclusive` contains all values with `x <= last`. /// It cannot serve as an [`Iterator`] because it doesn't have a starting point. /// /// # Examples /// -/// The `..=last` syntax is a `RangeToInclusive`: -/// /// ``` /// #![feature(new_range_api)] /// #![feature(new_range)] @@ -606,6 +611,11 @@ impl const From> for RangeFrom { /// ``` /// /// [slicing index]: crate::slice::SliceIndex +/// +/// # Edition notes +/// +/// It is planned that the syntax `..=last` will construct this +/// type in a future edition, but it does not do so today. #[lang = "RangeToInclusiveCopy"] #[doc(alias = "..=")] #[derive(Copy, Clone, PartialEq, Eq, Hash)] From 0c9d5f0d250ac2c1e6abb27a4a20dcc978f69036 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 7 Mar 2026 22:48:24 +0000 Subject: [PATCH 09/11] Fix ICE in `match_same_arms` (#16685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wrong `TypeckResults` was used in the fallback equality function passed by the `match_same_arms` and `filter_map` lints. Previously, those fallback functions had no way of using the proper `TypeckResults`. Those (one per expression being compared) are now passed to the registered fallback function. changelog: [`match_same_arms`]: fix internal compiler error Fixes rust-lang/rust-clippy#16678 Fixes rust-lang/rust-clippy#16686 ### Summary Notes - [Beta nomination](https://github.com/rust-lang/rust-clippy/pull/16685#issuecomment-4017155418) by [samueltardieu](https://github.com/samueltardieu) *Managed by `@rustbot`—see [help](https://forge.rust-lang.org/triagebot/note.html) for details* --- .../src/matches/match_same_arms.rs | 9 ++++++--- .../clippy_lints/src/methods/filter_map.rs | 7 +++++-- .../clippy/clippy_utils/src/hir_utils.rs | 20 +++++++++++++++---- .../clippy/tests/ui/match_same_arms.fixed | 16 +++++++++++++++ src/tools/clippy/tests/ui/match_same_arms.rs | 16 +++++++++++++++ 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 5b0de80e67fd7..a8312a04f36f8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExpr, PatExprKind, PatKind, RangeEnd}; use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::ty; +use rustc_middle::ty::{self, TypeckResults}; use rustc_span::{ByteSymbol, ErrorGuaranteed, Span, Symbol}; use super::MATCH_SAME_ARMS; @@ -61,7 +61,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| { let mut local_map: HirIdMap = HirIdMap::default(); - let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { + let eq_fallback = |a_typeck_results: &TypeckResults<'tcx>, + a: &Expr<'_>, + b_typeck_results: &TypeckResults<'tcx>, + b: &Expr<'_>| { if let Some(a_id) = a.res_local_id() && let Some(b_id) = b.res_local_id() && let entry = match local_map.entry(a_id) { @@ -71,7 +74,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { } // the names technically don't have to match; this makes the lint more conservative && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id) - && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b) + && a_typeck_results.expr_ty(a) == b_typeck_results.expr_ty(b) && pat_contains_local(lhs.pat, a_id) && pat_contains_local(rhs.pat, b_id) { diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 7b10c37de42df..d2e593fc17df8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp}; use rustc_lint::LateContext; +use rustc_middle::ty::TypeckResults; use rustc_middle::ty::adjustment::Adjust; use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol}; @@ -136,7 +137,9 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // .map(|y| y[.acceptable_method()].unwrap()) && let simple_equal = (receiver.res_local_id() == Some(filter_param_id) && map_arg_peeled.res_local_id() == Some(map_param_id)) - && let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| { + && let eq_fallback = + (|a_typeck_results: &TypeckResults<'tcx>, a: &Expr<'_>, + b_typeck_results: &TypeckResults<'tcx>, b: &Expr<'_>| { // in `filter(|x| ..)`, replace `*x` with `x` let a_path = if !is_filter_param_ref && let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind @@ -144,7 +147,7 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // let the filter closure arg and the map closure arg be equal a_path.res_local_id() == Some(filter_param_id) && b.res_local_id() == Some(map_param_id) - && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b) + && a_typeck_results.expr_ty_adjusted(a) == b_typeck_results.expr_ty_adjusted(b) }) && (simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(receiver, map_arg_peeled)) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 3ff40f2fb722b..7ba3216d6e5e9 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -26,7 +26,8 @@ use std::slice; /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but /// other conditions would make them equal. -type SpanlessEqCallback<'a> = dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a; +type SpanlessEqCallback<'a, 'tcx> = + dyn FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a; /// Determines how paths are hashed and compared for equality. #[derive(Copy, Clone, Debug, Default)] @@ -59,7 +60,7 @@ pub struct SpanlessEq<'a, 'tcx> { cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<(&'tcx TypeckResults<'tcx>, &'tcx TypeckResults<'tcx>)>, allow_side_effects: bool, - expr_fallback: Option>>, + expr_fallback: Option>>, path_check: PathCheck, } @@ -94,7 +95,10 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } #[must_use] - pub fn expr_fallback(self, expr_fallback: impl FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a) -> Self { + pub fn expr_fallback( + self, + expr_fallback: impl FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a, + ) -> Self { Self { expr_fallback: Some(Box::new(expr_fallback)), ..self @@ -639,7 +643,15 @@ impl HirEqInterExpr<'_, '_, '_> { ) => false, }; (is_eq && (!self.should_ignore(left) || !self.should_ignore(right))) - || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right)) + || self + .inner + .maybe_typeck_results + .is_some_and(|(left_typeck_results, right_typeck_results)| { + self.inner + .expr_fallback + .as_mut() + .is_some_and(|f| f(left_typeck_results, left, right_typeck_results, right)) + }) } fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool { diff --git a/src/tools/clippy/tests/ui/match_same_arms.fixed b/src/tools/clippy/tests/ui/match_same_arms.fixed index 31684a5759fe9..8b16fd3193f5f 100644 --- a/src/tools/clippy/tests/ui/match_same_arms.fixed +++ b/src/tools/clippy/tests/ui/match_same_arms.fixed @@ -140,3 +140,19 @@ fn main() { _ => false, }; } + +fn issue16678() { + // ICE in Rust 1.94.0 + match true { + true => { + fn wrapper(_arg: ()) { + _arg; + } + }, + false => { + fn wrapper(_arg: ()) { + _arg; + } + }, + } +} diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs index 39bee01bac22b..3b2d585c579d3 100644 --- a/src/tools/clippy/tests/ui/match_same_arms.rs +++ b/src/tools/clippy/tests/ui/match_same_arms.rs @@ -149,3 +149,19 @@ fn main() { _ => false, }; } + +fn issue16678() { + // ICE in Rust 1.94.0 + match true { + true => { + fn wrapper(_arg: ()) { + _arg; + } + }, + false => { + fn wrapper(_arg: ()) { + _arg; + } + }, + } +} From c79919adeda9ea8df3e4397d0bb0a489a7c80482 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Wed, 4 Mar 2026 21:01:08 +0000 Subject: [PATCH 10/11] Fix ICE in `swap_binop()` (#16659) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make `swap_binop()` a method of `HirEqInterExpr`, and use the proper typeck to check the type of an expression. changelog: none (fix of a regression, should be backported) Fixes rust-lang/rust-clippy#16505 ### Summary Notes - [Beta-nomination](https://github.com/rust-lang/rust-clippy/pull/16659#issuecomment-3993931812) by [samueltardieu](https://github.com/samueltardieu) *Managed by `@rustbot`—see [help](https://forge.rust-lang.org/triagebot/note.html) for details* --- .../clippy/clippy_utils/src/hir_utils.rs | 69 ++++++++++--------- .../clippy/tests/ui/if_same_then_else.rs | 17 +++++ 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7ba3216d6e5e9..1018b1eb37b0d 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -509,7 +509,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r), (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(self.inner.cx, l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { + || self.swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, @@ -933,6 +933,40 @@ impl HirEqInterExpr<'_, '_, '_> { self.right_ctxt = right; true } + + fn swap_binop<'a>( + &self, + binop: BinOpKind, + lhs: &'a Expr<'a>, + rhs: &'a Expr<'a>, + ) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { + match binop { + // `==` and `!=`, are commutative + BinOpKind::Eq | BinOpKind::Ne => Some((binop, rhs, lhs)), + // Comparisons can be reversed + BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), + BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), + BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), + BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), + // Non-commutative operators + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub | BinOpKind::Div => None, + // We know that those operators are commutative for primitive types, + // and we don't assume anything for other types + BinOpKind::Mul + | BinOpKind::Add + | BinOpKind::And + | BinOpKind::Or + | BinOpKind::BitAnd + | BinOpKind::BitXor + | BinOpKind::BitOr => self.inner.maybe_typeck_results.and_then(|(typeck_lhs, _)| { + typeck_lhs + .expr_ty_adjusted(lhs) + .peel_refs() + .is_primitive() + .then_some((binop, rhs, lhs)) + }), + } + } } /// Some simple reductions like `{ return }` => `return` @@ -978,39 +1012,6 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' } } -fn swap_binop<'a>( - cx: &LateContext<'_>, - binop: BinOpKind, - lhs: &'a Expr<'a>, - rhs: &'a Expr<'a>, -) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { - match binop { - // `==` and `!=`, are commutative - BinOpKind::Eq | BinOpKind::Ne => Some((binop, rhs, lhs)), - // Comparisons can be reversed - BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), - BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), - BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), - BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - // Non-commutative operators - BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub | BinOpKind::Div => None, - // We know that those operators are commutative for primitive types, - // and we don't assume anything for other types - BinOpKind::Mul - | BinOpKind::Add - | BinOpKind::And - | BinOpKind::Or - | BinOpKind::BitAnd - | BinOpKind::BitXor - | BinOpKind::BitOr => cx - .typeck_results() - .expr_ty_adjusted(lhs) - .peel_refs() - .is_primitive() - .then_some((binop, rhs, lhs)), - } -} - /// Checks if the two `Option`s are both `None` or some equal values as per /// `eq_fn`. pub fn both(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs index 6e0e2c5ea7202..6982a9d143e4c 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else.rs +++ b/src/tools/clippy/tests/ui/if_same_then_else.rs @@ -305,3 +305,20 @@ fn issue16416_prim(x: bool, a: u32, b: u32) { //~v if_same_then_else _ = if x { a >= b } else { b <= a }; } + +mod issue16505 { + macro_rules! foo { + (< $hi:literal : $lo:literal > | $N:tt bits) => {{ + const NEW_N_: usize = $hi - $lo + 1; + NEW_N_ + }}; + } + + fn bar(x: bool) { + _ = if x { + foo!(<2:0> | 3 bits) == foo!(<3:1> | 3 bits) + } else { + foo!(<3:1> | 3 bits) == foo!(<2:0> | 3 bits) + }; + } +} From b6da6b82788580175ad5059b4cd11a336d9c4da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandra=20Gonz=C3=A1lez?= Date: Tue, 3 Mar 2026 23:45:14 +0000 Subject: [PATCH 11/11] Optimize `allow_unwrap_types` evaluation to eliminate performance regression (#16652) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/rust-lang/rust-clippy/pull/16605 This PR addresses the 6.2% compilation performance regression introduced by the original `allow_unwrap_types` implementation (which natively allocated AST strings on every `unwrap` call via `bumpalo`). The implementation has been refactored to pre-resolve types securely without a performance penalty: **Pre-Resolution Cache via `LateLintPass`**: Instead of executing `ty.to_string()` and `lookup_path_str` inside the immediate `unwrap_expect_used` hot check for every method call encountered, `allow-unwrap-types` configuration strings are now parsed exactly *once* per crate compilation during the `LateLintPass::check_crate` hook in `clippy_lints/src/methods/mod.rs`. **`DefId` Native Storage**: The parsed `DefId` representations are stored in-memory using highly efficient caching maps directly on the main `Methods` struct: - `unwrap_allowed_ids: FxHashSet`: Allows instant O(1) lookups for standard types. - `unwrap_allowed_aliases: Vec`: Tracks type aliases requiring signature substitution checking later. **Execution Relief**: Inside `unwrap_expect_used::check()`, string manipulation is completely removed and `ty::Adt` checking uses lightning-fast `.contains(&adt.did())` operations to categorically avoid regression allocation loops. This implementation strongly parallels the pre-resolution type-routing logic in `clippy_config::types::create_disallowed_map` without altering the core `clippy.toml` config requirements. ### Summary Notes - [Beta-nomination](https://github.com/rust-lang/rust-clippy/pull/16652#issuecomment-3976671413) by [samueltardieu](https://github.com/samueltardieu) *Managed by `@rustbot`—see [help](https://forge.rust-lang.org/triagebot/note.html) for details* changelog: none --- .../clippy/clippy_lints/src/methods/mod.rs | 32 ++++++-- .../src/methods/unwrap_expect_used.rs | 80 +++++++++---------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 74db7ae03ba0b..994ad446593af 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -4761,6 +4761,8 @@ pub struct Methods { allowed_dotfiles: FxHashSet<&'static str>, format_args: FormatArgsStorage, allow_unwrap_types: Vec, + unwrap_allowed_ids: FxHashSet, + unwrap_allowed_aliases: Vec, } impl Methods { @@ -4778,6 +4780,8 @@ impl Methods { allowed_dotfiles, format_args, allow_unwrap_types: conf.allow_unwrap_types.clone(), + unwrap_allowed_ids: FxHashSet::default(), + unwrap_allowed_aliases: Vec::new(), } } } @@ -4953,6 +4957,19 @@ pub fn method_call<'tcx>(recv: &'tcx Expr<'tcx>) -> Option<(Symbol, &'tcx Expr<' } impl<'tcx> LateLintPass<'tcx> for Methods { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { + for s in &self.allow_unwrap_types { + let def_ids = clippy_utils::paths::lookup_path_str(cx.tcx, clippy_utils::paths::PathNS::Type, s); + for def_id in def_ids { + if cx.tcx.def_kind(def_id) == rustc_hir::def::DefKind::TyAlias { + self.unwrap_allowed_aliases.push(def_id); + } else { + self.unwrap_allowed_ids.insert(def_id); + } + } + } + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if expr.span.from_expansion() { return; @@ -4976,7 +4993,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods { self.allow_expect_in_tests, self.allow_unwrap_in_consts, self.allow_expect_in_consts, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, ); }, ExprKind::MethodCall(..) => { @@ -5730,7 +5748,8 @@ impl Methods { false, self.allow_expect_in_consts, self.allow_expect_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Expect, ); expect_fun_call::check(cx, &self.format_args, expr, method_span, recv, arg); @@ -5743,7 +5762,8 @@ impl Methods { true, self.allow_expect_in_consts, self.allow_expect_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Expect, ); }, @@ -5764,7 +5784,8 @@ impl Methods { false, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Unwrap, ); }, @@ -5776,7 +5797,8 @@ impl Methods { true, self.allow_unwrap_in_consts, self.allow_unwrap_in_tests, - &self.allow_unwrap_types, + &self.unwrap_allowed_ids, + &self.unwrap_allowed_aliases, unwrap_expect_used::Variant::Unwrap, ); }, diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs index 6d8777cbc23f8..c07c932176462 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs @@ -44,7 +44,8 @@ pub(super) fn check( is_err: bool, allow_unwrap_in_consts: bool, allow_unwrap_in_tests: bool, - allow_unwrap_types: &[String], + unwrap_allowed_ids: &rustc_data_structures::fx::FxHashSet, + unwrap_allowed_aliases: &[rustc_hir::def_id::DefId], variant: Variant, ) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); @@ -66,51 +67,39 @@ pub(super) fn check( let method_suffix = if is_err { "_err" } else { "" }; - let ty_name = ty.to_string(); - if allow_unwrap_types - .iter() - .any(|allowed_type| ty_name.starts_with(allowed_type) || ty_name == *allowed_type) + if let ty::Adt(adt, _) = ty.kind() + && unwrap_allowed_ids.contains(&adt.did()) { return; } - for s in allow_unwrap_types { - let def_ids = clippy_utils::paths::lookup_path_str(cx.tcx, clippy_utils::paths::PathNS::Type, s); - for def_id in def_ids { - if let ty::Adt(adt, _) = ty.kind() - && adt.did() == def_id - { - return; - } - if cx.tcx.def_kind(def_id) == DefKind::TyAlias { - let alias_ty = cx.tcx.type_of(def_id).instantiate_identity(); - if let (ty::Adt(adt, substs), ty::Adt(alias_adt, alias_substs)) = (ty.kind(), alias_ty.kind()) - && adt.did() == alias_adt.did() - { - let mut all_match = true; - for (arg, alias_arg) in substs.iter().zip(alias_substs.iter()) { - if let (Some(arg_ty), Some(alias_arg_ty)) = (arg.as_type(), alias_arg.as_type()) { - if matches!(alias_arg_ty.kind(), ty::Param(_)) { - continue; - } - if let (ty::Adt(arg_adt, _), ty::Adt(alias_arg_adt, _)) = - (arg_ty.peel_refs().kind(), alias_arg_ty.peel_refs().kind()) - { - if arg_adt.did() != alias_arg_adt.did() { - all_match = false; - break; - } - } else if arg_ty != alias_arg_ty { - all_match = false; - break; - } - } + for &def_id in unwrap_allowed_aliases { + let alias_ty = cx.tcx.type_of(def_id).instantiate_identity(); + if let (ty::Adt(adt, substs), ty::Adt(alias_adt, alias_substs)) = (ty.kind(), alias_ty.kind()) + && adt.did() == alias_adt.did() + { + let mut all_match = true; + for (arg, alias_arg) in substs.iter().zip(alias_substs.iter()) { + if let (Some(arg_ty), Some(alias_arg_ty)) = (arg.as_type(), alias_arg.as_type()) { + if matches!(alias_arg_ty.kind(), ty::Param(_)) { + continue; } - if all_match { - return; + if let (ty::Adt(arg_adt, _), ty::Adt(alias_arg_adt, _)) = + (arg_ty.peel_refs().kind(), alias_arg_ty.peel_refs().kind()) + { + if arg_adt.did() != alias_arg_adt.did() { + all_match = false; + break; + } + } else if arg_ty != alias_arg_ty { + all_match = false; + break; } } } + if all_match { + return; + } } } @@ -149,7 +138,8 @@ pub(super) fn check_call( allow_unwrap_in_tests: bool, allow_expect_in_consts: bool, allow_expect_in_tests: bool, - allow_unwrap_types: &[String], + unwrap_allowed_ids: &rustc_data_structures::fx::FxHashSet, + unwrap_allowed_aliases: &[rustc_hir::def_id::DefId], ) { let Some(recv) = args.first() else { return; @@ -167,7 +157,8 @@ pub(super) fn check_call( false, allow_unwrap_in_consts, allow_unwrap_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Unwrap, ); }, @@ -179,7 +170,8 @@ pub(super) fn check_call( false, allow_expect_in_consts, allow_expect_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Expect, ); }, @@ -191,7 +183,8 @@ pub(super) fn check_call( true, allow_unwrap_in_consts, allow_unwrap_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Unwrap, ); }, @@ -203,7 +196,8 @@ pub(super) fn check_call( true, allow_expect_in_consts, allow_expect_in_tests, - allow_unwrap_types, + unwrap_allowed_ids, + unwrap_allowed_aliases, Variant::Expect, ); },