From 60427ac5be3d1129fc318ef82cf7aa0228a45466 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 18 Nov 2025 11:17:09 -0700 Subject: [PATCH 01/18] feat: Enable annotate-snippets' simd feature --- Cargo.lock | 1 + compiler/rustc_errors/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 9dce64ce66ab6..e186ba343b291 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,6 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44baf24dd94e781f74dfe67ffee75a09a57971ddf0f615a178b4f6d404b48ff" dependencies = [ "anstyle", + "memchr", "unicode-width 0.2.2", ] diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index b3f76732a602c..a513a0345c3b7 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -annotate-snippets = "0.12.9" +annotate-snippets = { version = "0.12.9", features = ["simd"] } anstream = "0.6.20" anstyle = "1.0.13" derive_setters = "0.1.6" From 1befb0bac0310b8585a244eb009e7f795c293c53 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Thu, 13 Nov 2025 03:50:17 -0700 Subject: [PATCH 02/18] fix: Only add extra padding to the first group's last file --- compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs | 2 ++ tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 5b1fffd21d184..f26bf31a1aead 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -213,6 +213,7 @@ impl AnnotateSnippetEmitter { file_ann.swap(0, pos); } + let file_ann_len = file_ann.len(); for (file_idx, (file, annotations)) in file_ann.into_iter().enumerate() { if should_show_source_code(&self.ignored_directories_in_source_blocks, sm, &file) { if let Some(snippet) = self.annotated_snippet(annotations, &file.name, sm) { @@ -240,6 +241,7 @@ impl AnnotateSnippetEmitter { // ╰ warning: this was previously accepted if let Some(c) = children.first() && (!c.span.has_primary_spans() && !c.span.has_span_labels()) + && file_idx == file_ann_len - 1 { group = group.element(Padding); } diff --git a/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout index 1048db07ae95a..65989a8ef47c7 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout +++ b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout @@ -19,7 +19,6 @@ LL | println!(); error: macro expansion ignores `{` and any tokens following --> $SRC_DIR/std/src/macros.rs:LL:COL | - | ::: $DIR/main-alongside-macro-calls.rs:30:1 | LL | println!(); @@ -42,7 +41,6 @@ LL | println!(); error: macro expansion ignores `{` and any tokens following --> $SRC_DIR/std/src/macros.rs:LL:COL | - | ::: $DIR/main-alongside-macro-calls.rs:34:1 | LL | println!(); From ec17d9ea7cfbe6c69c14f40bff651d0ba8fb5671 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Thu, 13 Nov 2025 03:50:17 -0700 Subject: [PATCH 03/18] fix: Sort annotations by line number in AnnotateSnippetEmitter --- .../src/annotate_snippet_emitter_writer.rs | 8 ++++++++ tests/ui/statics/check-values-constraints.stderr | 4 ++-- tests/ui/typeck/typeck_type_placeholder_item.stderr | 12 ++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f26bf31a1aead..f7f78d2b28520 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -742,6 +742,14 @@ fn collect_annotations( } } } + + // Sort annotations within each file by line number + for (_, ann) in output.iter_mut() { + ann.sort_by_key(|a| { + let lo = sm.lookup_char_pos(a.span.lo()); + lo.line + }); + } output } diff --git a/tests/ui/statics/check-values-constraints.stderr b/tests/ui/statics/check-values-constraints.stderr index f6fa8df45e5e4..c54f4830533ae 100644 --- a/tests/ui/statics/check-values-constraints.stderr +++ b/tests/ui/statics/check-values-constraints.stderr @@ -38,10 +38,10 @@ LL | field2: SafeEnum::Variant4("str".to_string()), note: method `to_string` is not const because trait `ToString` is not const --> $SRC_DIR/alloc/src/string.rs:LL:COL | - = note: this method is not const + = note: this trait is not const ::: $SRC_DIR/alloc/src/string.rs:LL:COL | - = note: this trait is not const + = note: this method is not const = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 747d032dfd4be..5820078d8329b 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -686,12 +686,12 @@ LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | note: method `filter` is not const because trait `Iterator` is not const --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | - = note: this method is not const + = note: this trait is not const + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | - = note: this trait is not const + = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::` in constants @@ -702,12 +702,12 @@ LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | note: method `map` is not const because trait `Iterator` is not const --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | - = note: this method is not const + = note: this trait is not const + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | - = note: this trait is not const + = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 83 previous errors From 83485b94a03ae6cae525eaa00679b0d10cb80330 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Thu, 13 Nov 2025 03:50:17 -0700 Subject: [PATCH 04/18] fix: Only show one origin for multiline annotations with no source --- compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs | 2 +- tests/ui/typeck/typeck_type_placeholder_item.stderr | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f7f78d2b28520..7f64dc3df23ed 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -633,7 +633,7 @@ impl AnnotateSnippetEmitter { report.push(std::mem::replace(&mut group, Group::with_level(level.clone()))); } - if !line_tracker.contains(&lo.line) { + if !line_tracker.contains(&lo.line) && (i == 0 || hi.line <= lo.line) { line_tracker.push(lo.line); // ╭▸ $SRC_DIR/core/src/option.rs:594:0 (<- It adds *this*) // ⸬ $SRC_DIR/core/src/option.rs:602:4 diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 5820078d8329b..0b70ac97fd435 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -688,7 +688,6 @@ note: method `filter` is not const because trait `Iterator` is not const --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | = note: this method is not const @@ -704,7 +703,6 @@ note: method `map` is not const because trait `Iterator` is not const --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | = note: this method is not const From 4930d3e6129b17538e687f97c3b3f3e0dcaea76f Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 19 Nov 2025 08:16:11 +0800 Subject: [PATCH 05/18] Fix the issue of unused assignment from MIR liveness checking --- compiler/rustc_mir_transform/src/liveness.rs | 25 +++++++----- tests/ui/lint/unused/unused-assign-148960.rs | 33 +++++++++++++++ .../lint/unused/unused-assign-148960.stderr | 40 +++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 tests/ui/lint/unused/unused-assign-148960.rs create mode 100644 tests/ui/lint/unused/unused-assign-148960.stderr diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index f7dc703560245..d0134689fec06 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -45,6 +45,9 @@ struct Access { /// When we encounter multiple statements at the same location, we only increase the liveness, /// in order to avoid false positives. live: bool, + /// Is this a direct access to the place itself, no projections, or to a field? + /// This helps distinguish `x = ...` from `x.field = ...` + is_direct: bool, } #[tracing::instrument(level = "debug", skip(tcx), ret)] @@ -650,15 +653,17 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { |place: Place<'tcx>, kind, source_info: SourceInfo, live: &DenseBitSet| { if let Some((index, extra_projections)) = checked_places.get(place.as_ref()) { if !is_indirect(extra_projections) { + let is_direct = extra_projections.is_empty(); match assignments[index].entry(source_info) { IndexEntry::Vacant(v) => { - let access = Access { kind, live: live.contains(index) }; + let access = Access { kind, live: live.contains(index), is_direct }; v.insert(access); } IndexEntry::Occupied(mut o) => { // There were already a sighting. Mark this statement as live if it // was, to avoid false positives. o.get_mut().live |= live.contains(index); + o.get_mut().is_direct &= is_direct; } } } @@ -742,7 +747,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { continue; }; let source_info = body.local_decls[place.local].source_info; - let access = Access { kind, live: live.contains(index) }; + let access = Access { kind, live: live.contains(index), is_direct: true }; assignments[index].insert(source_info, access); } } @@ -1048,26 +1053,28 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { let Some((name, decl_span)) = self.checked_places.names[index] else { continue }; - // We have outstanding assignments and with non-trivial drop. - // This is probably a drop-guard, so we do not issue a warning there. - if maybe_drop_guard( + let is_maybe_drop_guard = maybe_drop_guard( tcx, self.typing_env, index, &self.ever_dropped, self.checked_places, self.body, - ) { - continue; - } + ); // We probed MIR in reverse order for dataflow. // We revert the vector to give a consistent order to the user. - for (source_info, Access { live, kind }) in statements.into_iter().rev() { + for (source_info, Access { live, kind, is_direct }) in statements.into_iter().rev() { if live { continue; } + // If this place was dropped and has non-trivial drop, + // skip reporting field assignments. + if !is_direct && is_maybe_drop_guard { + continue; + } + // Report the dead assignment. let Some(hir_id) = source_info.scope.lint_root(&self.body.source_scopes) else { continue; diff --git a/tests/ui/lint/unused/unused-assign-148960.rs b/tests/ui/lint/unused/unused-assign-148960.rs new file mode 100644 index 0000000000000..5d1810ad04a68 --- /dev/null +++ b/tests/ui/lint/unused/unused-assign-148960.rs @@ -0,0 +1,33 @@ +//@ check-fail +#![deny(unused)] + +fn test_one_extra_assign() { + let mut value = b"0".to_vec(); //~ ERROR value assigned to `value` is never read + value = b"1".to_vec(); + println!("{:?}", value); +} + +fn test_two_extra_assign() { + let mut x = 1; //~ ERROR value assigned to `x` is never read + x = 2; //~ ERROR value assigned to `x` is never read + x = 3; + println!("{}", x); +} + +struct Point { + x: i32, + y: i32, +} + +fn test_indirect_assign() { + let mut p = Point { x: 1, y: 1 }; //~ ERROR value assigned to `p` is never read + p = Point { x: 2, y: 2 }; + p.x = 3; + println!("{}", p.y); +} + +fn main() { + test_one_extra_assign(); + test_two_extra_assign(); + test_indirect_assign(); +} diff --git a/tests/ui/lint/unused/unused-assign-148960.stderr b/tests/ui/lint/unused/unused-assign-148960.stderr new file mode 100644 index 0000000000000..3f135264d8690 --- /dev/null +++ b/tests/ui/lint/unused/unused-assign-148960.stderr @@ -0,0 +1,40 @@ +error: value assigned to `value` is never read + --> $DIR/unused-assign-148960.rs:5:21 + | +LL | let mut value = b"0".to_vec(); + | ^^^^^^^^^^^^^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/unused-assign-148960.rs:2:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_assignments)]` implied by `#[deny(unused)]` + +error: value assigned to `x` is never read + --> $DIR/unused-assign-148960.rs:11:17 + | +LL | let mut x = 1; + | ^ + | + = help: maybe it is overwritten before being read? + +error: value assigned to `x` is never read + --> $DIR/unused-assign-148960.rs:12:5 + | +LL | x = 2; + | ^^^^^ + | + = help: maybe it is overwritten before being read? + +error: value assigned to `p` is never read + --> $DIR/unused-assign-148960.rs:23:17 + | +LL | let mut p = Point { x: 1, y: 1 }; + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: maybe it is overwritten before being read? + +error: aborting due to 4 previous errors + From 00f3155794f40030249a36b4abb09906b6e8fa5d Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 20 Nov 2025 19:47:21 +0800 Subject: [PATCH 06/18] fix unused assigment issue for variable with drop, issue 148418 --- compiler/rustc_mir_transform/src/liveness.rs | 6 ++- tests/ui/drop/or-pattern-drop-order.rs | 22 ++++++---- tests/ui/drop/or-pattern-drop-order.stderr | 43 +++++++++++++++++++ tests/ui/lint/unused/unused-assign-148960.rs | 17 ++++++-- .../lint/unused/unused-assign-148960.stderr | 32 +++++++++++--- tests/ui/liveness/liveness-unused.rs | 4 +- tests/ui/liveness/liveness-unused.stderr | 18 +++++++- 7 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 tests/ui/drop/or-pattern-drop-order.stderr diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index d0134689fec06..e66fb9d2d2a35 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -981,8 +981,10 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { self.checked_places, self.body, ) { - statements.clear(); - continue; + statements.retain(|_, access| access.is_direct); + if statements.is_empty() { + continue; + } } let typo = maybe_suggest_typo(); diff --git a/tests/ui/drop/or-pattern-drop-order.rs b/tests/ui/drop/or-pattern-drop-order.rs index 88355a4937e4f..c7913be032eab 100644 --- a/tests/ui/drop/or-pattern-drop-order.rs +++ b/tests/ui/drop/or-pattern-drop-order.rs @@ -33,15 +33,15 @@ fn main() { // Drops are right-to-left: `z`, `y`, `x`. let (x, Ok(y) | Err(y), z); // Assignment order doesn't matter. - z = LogDrop(o, 1); - y = LogDrop(o, 2); - x = LogDrop(o, 3); + z = LogDrop(o, 1); //~ WARN value assigned to `z` is never read + y = LogDrop(o, 2); //~ WARN value assigned to `y` is never read + x = LogDrop(o, 3); //~ WARN value assigned to `x` is never read }); assert_drop_order(1..=2, |o| { // The first or-pattern alternative determines the bindings' drop order: `y`, `x`. let ((true, x, y) | (false, y, x)); - x = LogDrop(o, 2); - y = LogDrop(o, 1); + x = LogDrop(o, 2); //~ WARN value assigned to `x` is never read + y = LogDrop(o, 1); //~ WARN value assigned to `y` is never read }); // `let pat = expr;` should have the same drop order. @@ -61,15 +61,21 @@ fn main() { // `match` should have the same drop order. assert_drop_order(1..=3, |o| { // Drops are right-to-left: `z`, `y` `x`. - match (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) { (x, Ok(y) | Err(y), z) => {} } + match (LogDrop(o, 3), Ok(LogDrop(o, 2)), LogDrop(o, 1)) { + (x, Ok(y) | Err(y), z) => {} + } }); assert_drop_order(1..=2, |o| { // The first or-pattern alternative determines the bindings' drop order: `y`, `x`. - match (true, LogDrop(o, 2), LogDrop(o, 1)) { (true, x, y) | (false, y, x) => {} } + match (true, LogDrop(o, 2), LogDrop(o, 1)) { + (true, x, y) | (false, y, x) => {} + } }); assert_drop_order(1..=2, |o| { // That drop order is used regardless of which or-pattern alternative matches: `y`, `x`. - match (false, LogDrop(o, 1), LogDrop(o, 2)) { (true, x, y) | (false, y, x) => {} } + match (false, LogDrop(o, 1), LogDrop(o, 2)) { + (true, x, y) | (false, y, x) => {} + } }); // Function params are visited one-by-one, and the order of bindings within a param's pattern is diff --git a/tests/ui/drop/or-pattern-drop-order.stderr b/tests/ui/drop/or-pattern-drop-order.stderr new file mode 100644 index 0000000000000..3d1aa69fb91a8 --- /dev/null +++ b/tests/ui/drop/or-pattern-drop-order.stderr @@ -0,0 +1,43 @@ +warning: value assigned to `x` is never read + --> $DIR/or-pattern-drop-order.rs:43:9 + | +LL | x = LogDrop(o, 2); + | ^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default + +warning: value assigned to `y` is never read + --> $DIR/or-pattern-drop-order.rs:44:9 + | +LL | y = LogDrop(o, 1); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `x` is never read + --> $DIR/or-pattern-drop-order.rs:38:9 + | +LL | x = LogDrop(o, 3); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `y` is never read + --> $DIR/or-pattern-drop-order.rs:37:9 + | +LL | y = LogDrop(o, 2); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `z` is never read + --> $DIR/or-pattern-drop-order.rs:36:9 + | +LL | z = LogDrop(o, 1); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/unused/unused-assign-148960.rs b/tests/ui/lint/unused/unused-assign-148960.rs index 5d1810ad04a68..2e51c01398a37 100644 --- a/tests/ui/lint/unused/unused-assign-148960.rs +++ b/tests/ui/lint/unused/unused-assign-148960.rs @@ -1,5 +1,6 @@ //@ check-fail #![deny(unused)] +#![allow(dead_code)] fn test_one_extra_assign() { let mut value = b"0".to_vec(); //~ ERROR value assigned to `value` is never read @@ -26,8 +27,16 @@ fn test_indirect_assign() { println!("{}", p.y); } -fn main() { - test_one_extra_assign(); - test_two_extra_assign(); - test_indirect_assign(); +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +// testcase for issue #148418 +fn test_unused_variable() { + let mut foo = Foo; //~ ERROR variable `foo` is assigned to, but never used + foo = Foo; //~ ERROR value assigned to `foo` is never read } + +fn main() {} diff --git a/tests/ui/lint/unused/unused-assign-148960.stderr b/tests/ui/lint/unused/unused-assign-148960.stderr index 3f135264d8690..0e23fabd5f561 100644 --- a/tests/ui/lint/unused/unused-assign-148960.stderr +++ b/tests/ui/lint/unused/unused-assign-148960.stderr @@ -1,5 +1,5 @@ error: value assigned to `value` is never read - --> $DIR/unused-assign-148960.rs:5:21 + --> $DIR/unused-assign-148960.rs:6:21 | LL | let mut value = b"0".to_vec(); | ^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #![deny(unused)] = note: `#[deny(unused_assignments)]` implied by `#[deny(unused)]` error: value assigned to `x` is never read - --> $DIR/unused-assign-148960.rs:11:17 + --> $DIR/unused-assign-148960.rs:12:17 | LL | let mut x = 1; | ^ @@ -21,7 +21,7 @@ LL | let mut x = 1; = help: maybe it is overwritten before being read? error: value assigned to `x` is never read - --> $DIR/unused-assign-148960.rs:12:5 + --> $DIR/unused-assign-148960.rs:13:5 | LL | x = 2; | ^^^^^ @@ -29,12 +29,34 @@ LL | x = 2; = help: maybe it is overwritten before being read? error: value assigned to `p` is never read - --> $DIR/unused-assign-148960.rs:23:17 + --> $DIR/unused-assign-148960.rs:24:17 | LL | let mut p = Point { x: 1, y: 1 }; | ^^^^^^^^^^^^^^^^^^^^ | = help: maybe it is overwritten before being read? -error: aborting due to 4 previous errors +error: variable `foo` is assigned to, but never used + --> $DIR/unused-assign-148960.rs:38:9 + | +LL | let mut foo = Foo; + | ^^^^^^^ + | + = note: consider using `_foo` instead + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` +help: you might have meant to pattern match on the similarly named struct `Foo` + | +LL - let mut foo = Foo; +LL + let Foo = Foo; + | + +error: value assigned to `foo` is never read + --> $DIR/unused-assign-148960.rs:39:5 + | +LL | foo = Foo; + | ^^^ + | + = help: maybe it is overwritten before being read? + +error: aborting due to 6 previous errors diff --git a/tests/ui/liveness/liveness-unused.rs b/tests/ui/liveness/liveness-unused.rs index 639d7c2776dee..a291d2489695f 100644 --- a/tests/ui/liveness/liveness-unused.rs +++ b/tests/ui/liveness/liveness-unused.rs @@ -244,8 +244,8 @@ fn f10(mut a: T, b: T) { //~^ ERROR value assigned to `a` is never read } -fn f10b(mut a: Box, b: Box) { - a = b; +fn f10b(mut a: Box, b: Box) { //~ ERROR variable `a` is assigned to, but never used + a = b; //~ ERROR value assigned to `a` is never read } // unused params warnings are not needed for intrinsic functions without bodies diff --git a/tests/ui/liveness/liveness-unused.stderr b/tests/ui/liveness/liveness-unused.stderr index 23a26841be2fc..f56ca7823e165 100644 --- a/tests/ui/liveness/liveness-unused.stderr +++ b/tests/ui/liveness/liveness-unused.stderr @@ -283,5 +283,21 @@ LL | a = b; | = help: maybe it is overwritten before being read? -error: aborting due to 34 previous errors; 1 warning emitted +error: variable `a` is assigned to, but never used + --> $DIR/liveness-unused.rs:247:12 + | +LL | fn f10b(mut a: Box, b: Box) { + | ^^^^^ + | + = note: consider using `_a` instead + +error: value assigned to `a` is never read + --> $DIR/liveness-unused.rs:248:5 + | +LL | a = b; + | ^ + | + = help: maybe it is overwritten before being read? + +error: aborting due to 36 previous errors; 1 warning emitted From d340ea520b8981f088c7930821dc2b4a80c202f3 Mon Sep 17 00:00:00 2001 From: lapla-cogito Date: Fri, 21 Nov 2025 14:04:06 +0900 Subject: [PATCH 07/18] Fix ICE when collecting opaques from trait method declarations --- compiler/rustc_ty_utils/src/opaque_types.rs | 5 ++- .../ice-148622-opaque-as-const-generics.rs | 12 +++++++ ...ice-148622-opaque-as-const-generics.stderr | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/ice-148622-opaque-as-const-generics.rs create mode 100644 tests/ui/impl-trait/ice-148622-opaque-as-const-generics.stderr diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4dd45a09a4df3..445021801beff 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -64,7 +64,10 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn collect_taits_declared_in_body(&mut self) { - let body = self.tcx.hir_body_owned_by(self.item).value; + let Some(body) = self.tcx.hir_maybe_body_owned_by(self.item) else { + return; + }; + let body = body.value; struct TaitInBodyFinder<'a, 'tcx> { collector: &'a mut OpaqueTypeCollector<'tcx>, } diff --git a/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.rs b/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.rs new file mode 100644 index 0000000000000..03741dca32978 --- /dev/null +++ b/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +pub type Opaque = impl std::future::Future; +//~^ ERROR: unconstrained opaque type + +trait Foo { + //~^ ERROR: `Opaque` is forbidden as the type of a const generic parameter + fn bar(&self) -> [u8; N]; + //~^ ERROR: the constant `N` is not of type `usize` +} + +fn main() {} diff --git a/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.stderr b/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.stderr new file mode 100644 index 0000000000000..bc76c6fe85e74 --- /dev/null +++ b/tests/ui/impl-trait/ice-148622-opaque-as-const-generics.stderr @@ -0,0 +1,31 @@ +error: `Opaque` is forbidden as the type of a const generic parameter + --> $DIR/ice-148622-opaque-as-const-generics.rs:6:20 + | +LL | trait Foo { + | ^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: the constant `N` is not of type `usize` + --> $DIR/ice-148622-opaque-as-const-generics.rs:8:22 + | +LL | fn bar(&self) -> [u8; N]; + | ^^^^^^^ expected `usize`, found future + | +note: this item must have a `#[define_opaque(Opaque)]` attribute to be able to define hidden types + --> $DIR/ice-148622-opaque-as-const-generics.rs:8:8 + | +LL | fn bar(&self) -> [u8; N]; + | ^^^ + = note: the length of array `[u8; N]` must be type `usize` + +error: unconstrained opaque type + --> $DIR/ice-148622-opaque-as-const-generics.rs:3:19 + | +LL | pub type Opaque = impl std::future::Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Opaque` must be used in combination with a concrete type within the same crate + +error: aborting due to 3 previous errors + From 7f7b3488c0258e1059426611267b5bd4ec068ac0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:51:24 +0000 Subject: [PATCH 08/18] Introduce InlineAsmError type --- compiler/rustc_codegen_llvm/src/back/write.rs | 16 +++++++--- compiler/rustc_codegen_ssa/src/back/write.rs | 31 ++++++++++--------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fde7dd6ef7a85..95539059653bd 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -9,8 +9,8 @@ use libc::{c_char, c_int, c_void, size_t}; use rustc_codegen_ssa::back::link::ensure_removed; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::back::write::{ - BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig, - TargetMachineFactoryFn, + BitcodeSection, CodegenContext, EmitObj, InlineAsmError, ModuleConfig, + TargetMachineFactoryConfig, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::wants_wasm_eh; use rustc_codegen_ssa::traits::*; @@ -434,7 +434,7 @@ fn report_inline_asm( level: llvm::DiagnosticLevel, cookie: u64, source: Option<(String, Vec)>, -) { +) -> InlineAsmError { // In LTO build we may get srcloc values from other crates which are invalid // since they use a different source map. To be safe we just suppress these // in LTO builds. @@ -454,7 +454,7 @@ fn report_inline_asm( llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; let msg = msg.trim_prefix("error: ").to_string(); - cgcx.diag_emitter.inline_asm_error(span, msg, level, source); + InlineAsmError { span, msg, level, source } } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { @@ -466,7 +466,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } { llvm::diagnostic::InlineAsm(inline) => { - report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source); + cgcx.diag_emitter.inline_asm_error(report_inline_asm( + cgcx, + inline.message, + inline.level, + inline.cookie, + inline.source, + )); } llvm::diagnostic::Optimization(opt) => { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index fc1edec8de843..3073b1641ac7c 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1897,10 +1897,17 @@ fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>( enum SharedEmitterMessage { Diagnostic(Diagnostic), - InlineAsmError(SpanData, String, Level, Option<(String, Vec)>), + InlineAsmError(InlineAsmError), Fatal(String), } +pub struct InlineAsmError { + pub span: SpanData, + pub msg: String, + pub level: Level, + pub source: Option<(String, Vec)>, +} + #[derive(Clone)] pub struct SharedEmitter { sender: Sender, @@ -1917,14 +1924,8 @@ impl SharedEmitter { (SharedEmitter { sender }, SharedEmitterMain { receiver }) } - pub fn inline_asm_error( - &self, - span: SpanData, - msg: String, - level: Level, - source: Option<(String, Vec)>, - ) { - drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source))); + pub fn inline_asm_error(&self, err: InlineAsmError) { + drop(self.sender.send(SharedEmitterMessage::InlineAsmError(err))); } fn fatal(&self, msg: &str) { @@ -2007,15 +2008,15 @@ impl SharedEmitterMain { dcx.emit_diagnostic(d); sess.dcx().abort_if_errors(); } - Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => { - assert_matches!(level, Level::Error | Level::Warning | Level::Note); - let mut err = Diag::<()>::new(sess.dcx(), level, msg); - if !span.is_dummy() { - err.span(span.span()); + Ok(SharedEmitterMessage::InlineAsmError(inner)) => { + assert_matches!(inner.level, Level::Error | Level::Warning | Level::Note); + let mut err = Diag::<()>::new(sess.dcx(), inner.level, inner.msg); + if !inner.span.is_dummy() { + err.span(inner.span.span()); } // Point to the generated assembly if it is available. - if let Some((buffer, spans)) = source { + if let Some((buffer, spans)) = inner.source { let source = sess .source_map() .new_source_file(FileName::inline_asm_source_code(&buffer), buffer); From bba5f7f72b6d1aacd12442d538419fac480b6393 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:46:19 +0000 Subject: [PATCH 09/18] Remove unused pop_span_label method --- compiler/rustc_error_messages/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 64dcf3c1f72d8..085403c8ef36b 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -455,10 +455,6 @@ impl MultiSpan { replacements_occurred } - pub fn pop_span_label(&mut self) -> Option<(Span, DiagMessage)> { - self.span_labels.pop() - } - /// Returns the strings to highlight. We always ensure that there /// is an entry for each of the primary spans -- for each primary /// span `P`, if there is at least one label with span `P`, we return From 2a280130db7b6fa5a52ee42f68e130d101e73607 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:46:51 +0000 Subject: [PATCH 10/18] Allow passing primary spans to SharedEmitter --- compiler/rustc_codegen_ssa/src/back/write.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 3073b1641ac7c..3e36bd8552b18 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1208,6 +1208,7 @@ pub struct CguMessage; // - `is_lint`: lints aren't relevant during codegen. // - `emitted_at`: not used for codegen diagnostics. struct Diagnostic { + span: Vec, level: Level, messages: Vec<(DiagMessage, Style)>, code: Option, @@ -1218,7 +1219,7 @@ struct Diagnostic { // A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's // missing the following fields from `rustc_errors::Subdiag`. // - `span`: it doesn't impl `Send`. -pub(crate) struct Subdiagnostic { +struct Subdiagnostic { level: Level, messages: Vec<(DiagMessage, Style)>, } @@ -1941,7 +1942,7 @@ impl Emitter for SharedEmitter { ) { // Check that we aren't missing anything interesting when converting to // the cut-down local `DiagInner`. - assert_eq!(diag.span, MultiSpan::new()); + assert!(!diag.span.has_span_labels()); assert_eq!(diag.suggestions, Suggestions::Enabled(vec![])); assert_eq!(diag.sort_span, rustc_span::DUMMY_SP); assert_eq!(diag.is_lint, None); @@ -1950,6 +1951,7 @@ impl Emitter for SharedEmitter { let args = mem::replace(&mut diag.args, DiagArgMap::default()); drop( self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { + span: diag.span.primary_spans().iter().map(|span| span.data()).collect::>(), level: diag.level(), messages: diag.messages, code: diag.code, @@ -1994,6 +1996,9 @@ impl SharedEmitterMain { let dcx = sess.dcx(); let mut d = rustc_errors::DiagInner::new_with_messages(diag.level, diag.messages); + d.span = MultiSpan::from_spans( + diag.span.into_iter().map(|span| span.span()).collect(), + ); d.code = diag.code; // may be `None`, that's ok d.children = diag .children From f580357863c1689ea1903b9570092a53f85a5c44 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 21 Nov 2025 11:43:53 -0500 Subject: [PATCH 11/18] Handle cycles when checking impl candidates for `doc(hidden)` Fixes https://github.com/rust-lang/rust/issues/149092 --- .../traits/fulfillment_errors.rs | 13 +++++++--- compiler/rustc_trait_selection/src/lib.rs | 1 + .../ui/suggestions/auxiliary/hidden-struct.rs | 3 +++ .../dont-suggest-foreign-doc-hidden.rs | 5 ++++ .../dont-suggest-foreign-doc-hidden.stderr | 26 +++++++++++++++++-- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d2f2c92dda080..0f5607dd7fecb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1,12 +1,13 @@ // ignore-tidy-filelength use core::ops::ControlFlow; use std::borrow::Cow; +use std::collections::hash_set; use std::path::PathBuf; use rustc_abi::ExternAbi; use rustc_ast::ast::LitKind; use rustc_ast::{LitIntType, TraitObjectSyntax}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ @@ -1956,11 +1957,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if self.tcx.visibility(did).is_accessible_from(body_def_id, self.tcx) { // don't suggest foreign `#[doc(hidden)]` types if !did.is_local() { - while let Some(parent) = parent_map.get(&did) { + let mut previously_seen_dids: FxHashSet = Default::default(); + previously_seen_dids.insert(did); + while let Some(&parent) = parent_map.get(&did) + && let hash_set::Entry::Vacant(v) = + previously_seen_dids.entry(parent) + { if self.tcx.is_doc_hidden(did) { return false; } - did = *parent; + v.insert(); + did = parent; } } true diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index c5dfaa2a60d87..0184b2ccde784 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,6 +17,7 @@ #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] +#![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] diff --git a/tests/ui/suggestions/auxiliary/hidden-struct.rs b/tests/ui/suggestions/auxiliary/hidden-struct.rs index 1f495a9f2224a..ee24389bebd7c 100644 --- a/tests/ui/suggestions/auxiliary/hidden-struct.rs +++ b/tests/ui/suggestions/auxiliary/hidden-struct.rs @@ -33,3 +33,6 @@ impl Marker for hidden::Foo {} impl Marker for hidden1::Bar {} impl Marker for Baz {} impl Marker for Quux {} + + +pub use crate as library; diff --git a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs index a83e496f2703d..0716e4e2e143b 100644 --- a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs +++ b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.rs @@ -21,7 +21,12 @@ pub fn test4(_: Quux) {} fn test5() {} +fn test6() {} + fn main() { test5::(); //~^ ERROR [E0277] + + test6::(); + //~^ ERROR [E0277] } diff --git a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr index e0444c93eeece..a111d0e5aa95a 100644 --- a/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr +++ b/tests/ui/suggestions/dont-suggest-foreign-doc-hidden.stderr @@ -38,7 +38,7 @@ LL + use hidden_struct::Quux; | error[E0277]: the trait bound `i32: Marker` is not satisfied - --> $DIR/dont-suggest-foreign-doc-hidden.rs:25:13 + --> $DIR/dont-suggest-foreign-doc-hidden.rs:27:13 | LL | test5::(); | ^^^ the trait `Marker` is not implemented for `i32` @@ -59,7 +59,29 @@ note: required by a bound in `test5` LL | fn test5() {} | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test5` -error: aborting due to 5 previous errors +error[E0277]: the trait bound `i32: Marker` is not satisfied + --> $DIR/dont-suggest-foreign-doc-hidden.rs:30:13 + | +LL | test6::(); + | ^^^ the trait `Marker` is not implemented for `i32` + | +help: the following other types implement trait `Marker` + --> $DIR/auxiliary/hidden-struct.rs:31:1 + | +LL | impl Marker for Option {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Option` +... +LL | impl Marker for Baz {} + | ^^^^^^^^^^^^^^^^^^^ `Baz` +LL | impl Marker for Quux {} + | ^^^^^^^^^^^^^^^^^^^^ `Quux` +note: required by a bound in `test6` + --> $DIR/dont-suggest-foreign-doc-hidden.rs:24:13 + | +LL | fn test6() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test6` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0412. For more information about an error, try `rustc --explain E0277`. From 3386da8f6fd77206acfa135c99727395a427bd2e Mon Sep 17 00:00:00 2001 From: chiri Date: Fri, 21 Nov 2025 22:52:19 +0300 Subject: [PATCH 12/18] Move safe computation out of unsafe block --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 52e079d3ae8e6..ea9d5b128ebe4 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2479,11 +2479,11 @@ impl VecDeque { let other_len = len - at; let mut other = VecDeque::with_capacity_in(other_len, self.allocator().clone()); - unsafe { - let (first_half, second_half) = self.as_slices(); + let (first_half, second_half) = self.as_slices(); + let first_len = first_half.len(); + let second_len = second_half.len(); - let first_len = first_half.len(); - let second_len = second_half.len(); + unsafe { if at < first_len { // `at` lies in the first half. let amount_in_first = first_len - at; From 8094934b9a7e882e40ea1de03a73d8c1053bed28 Mon Sep 17 00:00:00 2001 From: winningMove Date: Sat, 22 Nov 2025 10:37:31 +0100 Subject: [PATCH 13/18] Fix typo in HashMap performance comment --- library/std/src/collections/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 6104a02c739b5..460deb490ef0b 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -104,7 +104,7 @@ //! unlikely, for [`HashMap`] to experience significantly worse performance than //! the expected cost. This is due to the probabilistic nature of hashing - i.e. //! it is possible to generate a duplicate hash given some input key that will -//! requires extra computation to correct. +//! require extra computation to correct. //! //! ## Cost of Collection Operations //! From e2a69cea60d58ced09c1aaee15669c75a2f64aae Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 2 Nov 2025 12:46:59 +0100 Subject: [PATCH 14/18] Add `#[rustc_should_not_be_called_on_const_items]` attribute --- .../rustc_attr_parsing/src/attributes/lint_helpers.rs | 11 +++++++++++ compiler/rustc_attr_parsing/src/context.rs | 2 ++ compiler/rustc_feature/src/builtin_attrs.rs | 5 +++++ compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + 7 files changed, 24 insertions(+) diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 63b0809d0d8c9..8ca5f0f7228e3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -38,6 +38,17 @@ impl NoArgsAttributeParser for PassByValueParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue; } +pub(crate) struct RustcShouldNotBeCalledOnConstItems; +impl NoArgsAttributeParser for RustcShouldNotBeCalledOnConstItems { + const PATH: &[Symbol] = &[sym::rustc_should_not_be_called_on_const_items]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcShouldNotBeCalledOnConstItems; +} + pub(crate) struct AutomaticallyDerivedParser; impl NoArgsAttributeParser for AutomaticallyDerivedParser { const PATH: &[Symbol] = &[sym::automatically_derived]; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index d1777991731c0..99e6c748dbe90 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -39,6 +39,7 @@ use crate::attributes::link_attrs::{ }; use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, + RustcShouldNotBeCalledOnConstItems, }; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; use crate::attributes::macro_attrs::{ @@ -244,6 +245,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ce7dd16cd19cb..c1e947720452c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1267,6 +1267,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations." ), + rustc_attr!( + rustc_should_not_be_called_on_const_items, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::Yes, + "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts." + ), rustc_attr!( rustc_pass_by_value, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 4ba64b240ac03..708210ac6c6e4 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -701,6 +701,9 @@ pub enum AttributeKind { /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]` RustcPassIndirectlyInNonRusticAbis(Span), + /// Represents `#[rustc_should_not_be_called_on_const_items]` + RustcShouldNotBeCalledOnConstItems(Span), + /// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`. RustcSimdMonomorphizeLaneLimit(Limit), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 2ccfdc2ad983d..74fc6c6af009e 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -91,6 +91,7 @@ impl AttributeKind { RustcMain => No, RustcObjectLifetimeDefault => No, RustcPassIndirectlyInNonRusticAbis(..) => No, + RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate Sanitize { .. } => No, ShouldPanic { .. } => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 347e103af9378..30bb7d657f7a5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -254,6 +254,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcLayoutScalarValidRangeStart(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) + | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::ExportStable | AttributeKind::FfiConst(..) | AttributeKind::UnstableFeatureBound(..) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index eca4259efa7d1..cd730ede4ba1f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1986,6 +1986,7 @@ symbols! { rustc_regions, rustc_reservation_impl, rustc_serialize, + rustc_should_not_be_called_on_const_items, rustc_simd_monomorphize_lane_limit, rustc_skip_during_method_dispatch, rustc_specialization_trait, From 0e8d1e1f8ec2c8feb0b573371e688f97485b6a06 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 2 Nov 2025 13:38:30 +0100 Subject: [PATCH 15/18] Add `#[rustc_should_not_be_called_on_const_items]` to std methods --- library/core/src/cell.rs | 17 ++++++++++ library/core/src/cell/lazy.rs | 1 + library/core/src/cell/once.rs | 4 +++ library/core/src/sync/atomic.rs | 45 ++++++++++++++++++++++++++ library/std/src/sync/lazy_lock.rs | 2 ++ library/std/src/sync/once.rs | 4 +++ library/std/src/sync/once_lock.rs | 6 ++++ library/std/src/sync/poison/condvar.rs | 7 ++++ library/std/src/sync/poison/mutex.rs | 5 +++ library/std/src/sync/poison/rwlock.rs | 6 ++++ 10 files changed, 97 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 988c50795e299..c8340c328be12 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -430,6 +430,7 @@ impl Cell { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cell_traits", issue = "147787")] + #[rustc_should_not_be_called_on_const_items] pub const fn set(&self, val: T) where T: [const] Destruct, @@ -461,6 +462,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] + #[rustc_should_not_be_called_on_const_items] pub fn swap(&self, other: &Self) { // This function documents that it *will* panic, and intrinsics::is_nonoverlapping doesn't // do the check in const, so trying to use it here would be inviting unnecessary fragility. @@ -505,6 +507,7 @@ impl Cell { #[stable(feature = "move_cell", since = "1.17.0")] #[rustc_const_stable(feature = "const_cell", since = "1.88.0")] #[rustc_confusables("swap")] + #[rustc_should_not_be_called_on_const_items] pub const fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -546,6 +549,7 @@ impl Cell { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_cell", since = "1.88.0")] + #[rustc_should_not_be_called_on_const_items] pub const fn get(&self) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -566,6 +570,7 @@ impl Cell { #[inline] #[stable(feature = "cell_update", since = "1.88.0")] #[rustc_const_unstable(feature = "const_cell_traits", issue = "147787")] + #[rustc_should_not_be_called_on_const_items] pub const fn update(&self, f: impl [const] FnOnce(T) -> T) where // FIXME(const-hack): `Copy` should imply `const Destruct` @@ -994,6 +999,7 @@ impl RefCell { #[track_caller] #[rustc_confusables("swap")] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn replace(&self, t: T) -> T { mem::replace(&mut self.borrow_mut(), t) } @@ -1017,6 +1023,7 @@ impl RefCell { #[inline] #[stable(feature = "refcell_replace_swap", since = "1.35.0")] #[track_caller] + #[rustc_should_not_be_called_on_const_items] pub fn replace_with T>(&self, f: F) -> T { let mut_borrow = &mut *self.borrow_mut(); let replacement = f(mut_borrow); @@ -1046,6 +1053,7 @@ impl RefCell { #[inline] #[stable(feature = "refcell_swap", since = "1.24.0")] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn swap(&self, other: &Self) { mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) } @@ -1087,6 +1095,7 @@ impl RefCell { #[inline] #[track_caller] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn borrow(&self) -> Ref<'_, T> { match self.try_borrow() { Ok(b) => b, @@ -1123,6 +1132,7 @@ impl RefCell { #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn try_borrow(&self) -> Result, BorrowError> { match BorrowRef::new(&self.borrow) { Some(b) => { @@ -1185,6 +1195,7 @@ impl RefCell { #[inline] #[track_caller] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn borrow_mut(&self) -> RefMut<'_, T> { match self.try_borrow_mut() { Ok(b) => b, @@ -1218,6 +1229,7 @@ impl RefCell { #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + #[rustc_should_not_be_called_on_const_items] pub const fn try_borrow_mut(&self) -> Result, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { Some(b) => { @@ -2356,6 +2368,7 @@ impl UnsafeCell { /// ``` #[inline] #[unstable(feature = "unsafe_cell_access", issue = "136327")] + #[rustc_should_not_be_called_on_const_items] pub const unsafe fn replace(&self, value: T) -> T { // SAFETY: pointer comes from `&self` so naturally satisfies invariants. unsafe { ptr::replace(self.get(), value) } @@ -2404,6 +2417,7 @@ impl UnsafeCell { #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] #[rustc_as_ptr] #[rustc_never_returns_null_ptr] + #[rustc_should_not_be_called_on_const_items] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of // #[repr(transparent)]. This exploits std's special status, there is @@ -2493,6 +2507,7 @@ impl UnsafeCell { /// ``` #[inline] #[unstable(feature = "unsafe_cell_access", issue = "136327")] + #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_ref_unchecked(&self) -> &T { // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants. unsafe { self.get().as_ref_unchecked() } @@ -2521,6 +2536,7 @@ impl UnsafeCell { #[inline] #[unstable(feature = "unsafe_cell_access", issue = "136327")] #[allow(clippy::mut_from_ref)] + #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_mut_unchecked(&self) -> &mut T { // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants. unsafe { self.get().as_mut_unchecked() } @@ -2608,6 +2624,7 @@ impl SyncUnsafeCell { #[inline] #[rustc_as_ptr] #[rustc_never_returns_null_ptr] + #[rustc_should_not_be_called_on_const_items] pub const fn get(&self) -> *mut T { self.value.get() } diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index a1bd4c8571706..3dae6c64200c1 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -134,6 +134,7 @@ impl T> LazyCell { /// ``` #[inline] #[stable(feature = "lazy_cell", since = "1.80.0")] + #[rustc_should_not_be_called_on_const_items] pub fn force(this: &LazyCell) -> &T { // SAFETY: // This invalidates any mutable references to the data. The resulting diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 833be059d75f7..1e211ae66e79c 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -88,6 +88,7 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_should_not_be_called_on_const_items] pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), @@ -120,6 +121,7 @@ impl OnceCell { /// ``` #[inline] #[unstable(feature = "once_cell_try_insert", issue = "116693")] + #[rustc_should_not_be_called_on_const_items] pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { if let Some(old) = self.get() { return Err((old, value)); @@ -157,6 +159,7 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_should_not_be_called_on_const_items] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, @@ -231,6 +234,7 @@ impl OnceCell { /// assert_eq!(cell.get(), Some(&92)) /// ``` #[unstable(feature = "once_cell_try", issue = "109737")] + #[rustc_should_not_be_called_on_const_items] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index d7eaaf35b53a3..0c5552a0b81cc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -749,6 +749,7 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn store(&self, val: bool, order: Ordering) { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. @@ -781,6 +782,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn swap(&self, val: bool, order: Ordering) -> bool { if EMULATE_ATOMIC_BOOL { if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) } @@ -848,6 +850,7 @@ impl AtomicBool { )] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -909,6 +912,7 @@ impl AtomicBool { #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange( &self, current: bool, @@ -1004,6 +1008,7 @@ impl AtomicBool { #[doc(alias = "compare_and_swap")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange_weak( &self, current: bool, @@ -1060,6 +1065,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } @@ -1102,6 +1108,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done @@ -1154,6 +1161,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } @@ -1195,6 +1203,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } @@ -1232,6 +1241,7 @@ impl AtomicBool { #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_not(&self, order: Ordering) -> bool { self.fetch_xor(true, order) } @@ -1270,6 +1280,7 @@ impl AtomicBool { #[stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] #[rustc_never_returns_null_ptr] + #[rustc_should_not_be_called_on_const_items] pub const fn as_ptr(&self) -> *mut bool { self.v.get().cast() } @@ -1323,6 +1334,7 @@ impl AtomicBool { #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_update( &self, set_order: Ordering, @@ -1394,6 +1406,7 @@ impl AtomicBool { #[unstable(feature = "atomic_try_update", issue = "135894")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn try_update( &self, set_order: Ordering, @@ -1452,6 +1465,7 @@ impl AtomicBool { #[unstable(feature = "atomic_try_update", issue = "135894")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn update( &self, set_order: Ordering, @@ -1735,6 +1749,7 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn store(&self, ptr: *mut T, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. unsafe { @@ -1768,6 +1783,7 @@ impl AtomicPtr { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.p.get(), ptr, order) } @@ -1830,6 +1846,7 @@ impl AtomicPtr { )] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -1884,6 +1901,7 @@ impl AtomicPtr { #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange( &self, current: *mut T, @@ -1947,6 +1965,7 @@ impl AtomicPtr { #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange_weak( &self, current: *mut T, @@ -2020,6 +2039,7 @@ impl AtomicPtr { #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_update( &self, set_order: Ordering, @@ -2100,6 +2120,7 @@ impl AtomicPtr { #[unstable(feature = "atomic_try_update", issue = "135894")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn try_update( &self, set_order: Ordering, @@ -2163,6 +2184,7 @@ impl AtomicPtr { #[unstable(feature = "atomic_try_update", issue = "135894")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn update( &self, set_order: Ordering, @@ -2214,6 +2236,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(size_of::()), order) } @@ -2258,6 +2281,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(size_of::()), order) } @@ -2292,6 +2316,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_add(self.p.get(), val, order).cast() } @@ -2327,6 +2352,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_sub(self.p.get(), val, order).cast() } @@ -2377,6 +2403,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.p.get(), val, order).cast() } @@ -2426,6 +2453,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.p.get(), val, order).cast() } @@ -2473,6 +2501,7 @@ impl AtomicPtr { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.p.get(), val, order).cast() } @@ -2913,6 +2942,7 @@ macro_rules! atomic_int { #[inline] #[$stable] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn store(&self, val: $int_type, order: Ordering) { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.v.get(), val, order); } @@ -2941,6 +2971,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.v.get(), val, order) } @@ -3005,6 +3036,7 @@ macro_rules! atomic_int { ] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_and_swap(&self, current: $int_type, new: $int_type, @@ -3073,6 +3105,7 @@ macro_rules! atomic_int { #[$stable_cxchg] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange(&self, current: $int_type, new: $int_type, @@ -3136,6 +3169,7 @@ macro_rules! atomic_int { #[$stable_cxchg] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn compare_exchange_weak(&self, current: $int_type, new: $int_type, @@ -3172,6 +3206,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_add(self.v.get(), val, order) } @@ -3202,6 +3237,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_sub(self.v.get(), val, order) } @@ -3235,6 +3271,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.v.get(), val, order) } @@ -3268,6 +3305,7 @@ macro_rules! atomic_int { #[$stable_nand] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_nand(self.v.get(), val, order) } @@ -3301,6 +3339,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.v.get(), val, order) } @@ -3334,6 +3373,7 @@ macro_rules! atomic_int { #[$stable] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.v.get(), val, order) } @@ -3388,6 +3428,7 @@ macro_rules! atomic_int { #[stable(feature = "no_more_cas", since = "1.45.0")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_update(&self, set_order: Ordering, fetch_order: Ordering, @@ -3455,6 +3496,7 @@ macro_rules! atomic_int { #[unstable(feature = "atomic_try_update", issue = "135894")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn try_update( &self, set_order: Ordering, @@ -3516,6 +3558,7 @@ macro_rules! atomic_int { #[unstable(feature = "atomic_try_update", issue = "135894")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn update( &self, set_order: Ordering, @@ -3570,6 +3613,7 @@ macro_rules! atomic_int { #[stable(feature = "atomic_min_max", since = "1.45.0")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { $max_fn(self.v.get(), val, order) } @@ -3616,6 +3660,7 @@ macro_rules! atomic_int { #[stable(feature = "atomic_min_max", since = "1.45.0")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + #[rustc_should_not_be_called_on_const_items] pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: data races are prevented by atomic intrinsics. unsafe { $min_fn(self.v.get(), val, order) } diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index f1cae4b207c9a..ef58b64d4967e 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -247,6 +247,7 @@ impl T> LazyLock { /// ``` #[inline] #[stable(feature = "lazy_cell", since = "1.80.0")] + #[rustc_should_not_be_called_on_const_items] pub fn force(this: &LazyLock) -> &T { this.once.call_once_force(|state| { if state.is_poisoned() { @@ -320,6 +321,7 @@ impl LazyLock { /// ``` #[inline] #[unstable(feature = "lazy_get", issue = "129333")] + #[rustc_should_not_be_called_on_const_items] pub fn get(this: &LazyLock) -> Option<&T> { if this.once.is_completed() { // SAFETY: diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 12cc32f381d18..bcfc9f581fd28 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -145,6 +145,7 @@ impl Once { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] + #[rustc_should_not_be_called_on_const_items] pub fn call_once(&self, f: F) where F: FnOnce(), @@ -204,6 +205,7 @@ impl Once { /// ``` #[inline] #[stable(feature = "once_poison", since = "1.51.0")] + #[rustc_should_not_be_called_on_const_items] pub fn call_once_force(&self, f: F) where F: FnOnce(&OnceState), @@ -288,6 +290,7 @@ impl Once { /// panicked, this method will also panic. Use [`wait_force`](Self::wait_force) /// if this behavior is not desired. #[stable(feature = "once_wait", since = "1.86.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait(&self) { if !self.inner.is_completed() { self.inner.wait(false); @@ -300,6 +303,7 @@ impl Once { /// If this [`Once`] has been poisoned, this function blocks until it /// becomes completed, unlike [`Once::wait()`], which panics in this case. #[stable(feature = "once_wait", since = "1.86.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait_force(&self) { if !self.inner.is_completed() { self.inner.wait(true); diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index b224044cbe09c..d1bbe0ff843cf 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -150,6 +150,7 @@ impl OnceLock { /// This method never blocks. #[inline] #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_should_not_be_called_on_const_items] pub fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized @@ -197,6 +198,7 @@ impl OnceLock { /// ``` #[inline] #[stable(feature = "once_wait", since = "1.86.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait(&self) -> &T { self.once.wait_force(); @@ -231,6 +233,7 @@ impl OnceLock { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_should_not_be_called_on_const_items] pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), @@ -270,6 +273,7 @@ impl OnceLock { /// ``` #[inline] #[unstable(feature = "once_cell_try_insert", issue = "116693")] + #[rustc_should_not_be_called_on_const_items] pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { let mut value = Some(value); let res = self.get_or_init(|| value.take().unwrap()); @@ -308,6 +312,7 @@ impl OnceLock { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_should_not_be_called_on_const_items] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, @@ -388,6 +393,7 @@ impl OnceLock { /// ``` #[inline] #[unstable(feature = "once_cell_try", issue = "109737")] + #[rustc_should_not_be_called_on_const_items] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, diff --git a/library/std/src/sync/poison/condvar.rs b/library/std/src/sync/poison/condvar.rs index de625a6cc5f63..fa9e1caada59b 100644 --- a/library/std/src/sync/poison/condvar.rs +++ b/library/std/src/sync/poison/condvar.rs @@ -121,6 +121,7 @@ impl Condvar { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult> { let poisoned = unsafe { let lock = mutex::guard_lock(&guard); @@ -177,6 +178,7 @@ impl Condvar { /// let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| { *pending }).unwrap(); /// ``` #[stable(feature = "wait_until", since = "1.42.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait_while<'a, T, F>( &self, mut guard: MutexGuard<'a, T>, @@ -245,6 +247,7 @@ impl Condvar { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] #[deprecated(since = "1.6.0", note = "replaced by `std::sync::Condvar::wait_timeout`")] pub fn wait_timeout_ms<'a, T>( &self, @@ -316,6 +319,7 @@ impl Condvar { /// } /// ``` #[stable(feature = "wait_timeout", since = "1.5.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, @@ -382,6 +386,7 @@ impl Condvar { /// // access the locked mutex via result.0 /// ``` #[stable(feature = "wait_timeout_until", since = "1.42.0")] + #[rustc_should_not_be_called_on_const_items] pub fn wait_timeout_while<'a, T, F>( &self, mut guard: MutexGuard<'a, T>, @@ -442,6 +447,7 @@ impl Condvar { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn notify_one(&self) { self.inner.notify_one() } @@ -482,6 +488,7 @@ impl Condvar { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn notify_all(&self) { self.inner.notify_all() } diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 6fdb4f6799ee5..7f9e5fe62516f 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -401,6 +401,7 @@ impl Mutex { /// assert_eq!(mutex.get_cloned().unwrap(), 11); /// ``` #[unstable(feature = "lock_value_accessors", issue = "133407")] + #[rustc_should_not_be_called_on_const_items] pub fn set(&self, value: T) -> Result<(), PoisonError> { if mem::needs_drop::() { // If the contained value has non-trivial destructor, we @@ -438,6 +439,7 @@ impl Mutex { /// assert_eq!(mutex.get_cloned().unwrap(), 11); /// ``` #[unstable(feature = "lock_value_accessors", issue = "133407")] + #[rustc_should_not_be_called_on_const_items] pub fn replace(&self, value: T) -> LockResult { match self.lock() { Ok(mut guard) => Ok(mem::replace(&mut *guard, value)), @@ -484,6 +486,7 @@ impl Mutex { /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn lock(&self) -> LockResult> { unsafe { self.inner.lock(); @@ -532,6 +535,7 @@ impl Mutex { /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn try_lock(&self) -> TryLockResult> { unsafe { if self.inner.try_lock() { @@ -602,6 +606,7 @@ impl Mutex { /// ``` #[inline] #[stable(feature = "mutex_unpoison", since = "1.77.0")] + #[rustc_should_not_be_called_on_const_items] pub fn clear_poison(&self) { self.poison.clear(); } diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 10e45bc8c11a3..acfeb96900cc9 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -299,6 +299,7 @@ impl RwLock { /// assert_eq!(lock.get_cloned().unwrap(), 11); /// ``` #[unstable(feature = "lock_value_accessors", issue = "133407")] + #[rustc_should_not_be_called_on_const_items] pub fn set(&self, value: T) -> Result<(), PoisonError> { if mem::needs_drop::() { // If the contained value has non-trivial destructor, we @@ -337,6 +338,7 @@ impl RwLock { /// assert_eq!(lock.get_cloned().unwrap(), 11); /// ``` #[unstable(feature = "lock_value_accessors", issue = "133407")] + #[rustc_should_not_be_called_on_const_items] pub fn replace(&self, value: T) -> LockResult { match self.write() { Ok(mut guard) => Ok(mem::replace(&mut *guard, value)), @@ -389,6 +391,7 @@ impl RwLock { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn read(&self) -> LockResult> { unsafe { self.inner.read(); @@ -435,6 +438,7 @@ impl RwLock { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn try_read(&self) -> TryLockResult> { unsafe { if self.inner.try_read() { @@ -479,6 +483,7 @@ impl RwLock { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn write(&self) -> LockResult> { unsafe { self.inner.write(); @@ -526,6 +531,7 @@ impl RwLock { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_should_not_be_called_on_const_items] pub fn try_write(&self) -> TryLockResult> { unsafe { if self.inner.try_write() { From dc2a61eccd6702e297db6a4bfd1443064cabc0a4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 2 Nov 2025 15:19:33 +0100 Subject: [PATCH 16/18] Add `const_item_interior_mutations` lint --- compiler/rustc_lint/messages.ftl | 8 + .../rustc_lint/src/interior_mutable_consts.rs | 122 +++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 33 + ...tem-interior-mutations-const-atomics.fixed | 164 ++++ ...t-item-interior-mutations-const-atomics.rs | 164 ++++ ...em-interior-mutations-const-atomics.stderr | 765 ++++++++++++++++++ ...onst-item-interior-mutations-const-cell.rs | 105 +++ ...-item-interior-mutations-const-cell.stderr | 377 +++++++++ .../const-item-interior-mutations-const.fixed | 139 ++++ .../const-item-interior-mutations-const.rs | 139 ++++ ...const-item-interior-mutations-const.stderr | 513 ++++++++++++ 12 files changed, 2532 insertions(+) create mode 100644 compiler/rustc_lint/src/interior_mutable_consts.rs create mode 100644 tests/ui/lint/const-item-interior-mutations-const-atomics.fixed create mode 100644 tests/ui/lint/const-item-interior-mutations-const-atomics.rs create mode 100644 tests/ui/lint/const-item-interior-mutations-const-atomics.stderr create mode 100644 tests/ui/lint/const-item-interior-mutations-const-cell.rs create mode 100644 tests/ui/lint/const-item-interior-mutations-const-cell.stderr create mode 100644 tests/ui/lint/const-item-interior-mutations-const.fixed create mode 100644 tests/ui/lint/const-item-interior-mutations-const.rs create mode 100644 tests/ui/lint/const-item-interior-mutations-const.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index c996181354b92..df04d135600ac 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -193,6 +193,14 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i .current_use = this identifier can be confused with `{$existing_sym}` .other_use = other identifier used here +lint_const_item_interior_mutations = + mutation of an interior mutable `const` item with call to `{$method_name}` + .label = `{$const_name}` is a interior mutable `const` item of type `{$const_ty}` + .temporary = each usage of a `const` item creates a new temporary + .never_original = only the temporaries and never the original `const {$const_name}` will be modified + .suggestion_static = for a shared instance of `{$const_name}`, consider making it a `static` item instead + .help = for more details on interior mutability see + lint_dangling_pointers_from_locals = {$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}` .ret_ty = return type is `{$ret_ty}` .local_var = local variable `{$local_var_name}` is dropped at the end of the {$fn_kind} diff --git a/compiler/rustc_lint/src/interior_mutable_consts.rs b/compiler/rustc_lint/src/interior_mutable_consts.rs new file mode 100644 index 0000000000000..8576698dec33e --- /dev/null +++ b/compiler/rustc_lint/src/interior_mutable_consts.rs @@ -0,0 +1,122 @@ +use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, find_attr}; +use rustc_session::{declare_lint, declare_lint_pass}; + +use crate::lints::{ConstItemInteriorMutationsDiag, ConstItemInteriorMutationsSuggestionStatic}; +use crate::{LateContext, LateLintPass, LintContext}; + +declare_lint! { + /// The `const_item_interior_mutations` lint checks for calls which + /// mutates an interior mutable const-item. + /// + /// ### Example + /// + /// ```rust + /// use std::sync::Once; + /// + /// const INIT: Once = Once::new(); // using `INIT` will always create a temporary and + /// // never modify it-self on use, should be a `static` + /// // instead for shared use + /// + /// fn init() { + /// INIT.call_once(|| { + /// println!("Once::call_once first call"); + /// }); + /// INIT.call_once(|| { // this second will also print + /// println!("Once::call_once second call"); // as each call to `INIT` creates + /// }); // new temporary + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Calling a method which mutates an interior mutable type has no effect as const-item + /// are essentially inlined wherever they are used, meaning that they are copied + /// directly into the relevant context when used rendering modification through + /// interior mutability ineffective across usage of that const-item. + /// + /// The current implementation of this lint only warns on significant `std` and + /// `core` interior mutable types, like `Once`, `AtomicI32`, ... this is done out + /// of prudence to avoid false-positive and may be extended in the future. + pub CONST_ITEM_INTERIOR_MUTATIONS, + Warn, + "checks for calls which mutates a interior mutable const-item" +} + +declare_lint_pass!(InteriorMutableConsts => [CONST_ITEM_INTERIOR_MUTATIONS]); + +impl<'tcx> LateLintPass<'tcx> for InteriorMutableConsts { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + let typeck = cx.typeck_results(); + + let (method_did, receiver) = match expr.kind { + // matching on `.method(..)` + ExprKind::MethodCall(_, receiver, _, _) => { + (typeck.type_dependent_def_id(expr.hir_id), receiver) + } + // matching on `function(&, ...)` + ExprKind::Call(path, [receiver, ..]) => match receiver.kind { + ExprKind::AddrOf(_, _, receiver) => match path.kind { + ExprKind::Path(ref qpath) => { + (cx.qpath_res(qpath, path.hir_id).opt_def_id(), receiver) + } + _ => return, + }, + _ => return, + }, + _ => return, + }; + + let Some(method_did) = method_did else { + return; + }; + + if let ExprKind::Path(qpath) = &receiver.kind + && let Res::Def(DefKind::Const | DefKind::AssocConst, const_did) = + typeck.qpath_res(qpath, receiver.hir_id) + // Let's do the attribute check after the other checks for perf reasons + && find_attr!( + cx.tcx.get_all_attrs(method_did), + AttributeKind::RustcShouldNotBeCalledOnConstItems(_) + ) + && let Some(method_name) = cx.tcx.opt_item_ident(method_did) + && let Some(const_name) = cx.tcx.opt_item_ident(const_did) + && let Some(const_ty) = typeck.node_type_opt(receiver.hir_id) + { + // Find the local `const`-item and create the suggestion to use `static` instead + let sugg_static = if let Some(Node::Item(const_item)) = + cx.tcx.hir_get_if_local(const_did) + && let ItemKind::Const(ident, _generics, _ty, _body_id) = const_item.kind + { + if let Some(vis_span) = const_item.vis_span.find_ancestor_inside(const_item.span) + && const_item.span.can_be_used_for_suggestions() + && vis_span.can_be_used_for_suggestions() + { + Some(ConstItemInteriorMutationsSuggestionStatic::Spanful { + const_: const_item.vis_span.between(ident.span), + before: if !vis_span.is_empty() { " " } else { "" }, + }) + } else { + Some(ConstItemInteriorMutationsSuggestionStatic::Spanless) + } + } else { + None + }; + + cx.emit_span_lint( + CONST_ITEM_INTERIOR_MUTATIONS, + expr.span, + ConstItemInteriorMutationsDiag { + method_name, + const_name, + const_ty, + receiver_span: receiver.span, + sugg_static, + }, + ); + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 7c3a81e891300..78b76e083d416 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -48,6 +48,7 @@ mod foreign_modules; mod function_cast_as_integer; mod if_let_rescope; mod impl_trait_overcaptures; +mod interior_mutable_consts; mod internal; mod invalid_from_utf8; mod late; @@ -93,6 +94,7 @@ use for_loops_over_fallibles::*; use function_cast_as_integer::*; use if_let_rescope::IfLetRescope; use impl_trait_overcaptures::ImplTraitOvercaptures; +use interior_mutable_consts::*; use internal::*; use invalid_from_utf8::*; use let_underscore::*; @@ -239,6 +241,7 @@ late_lint_methods!( AsyncClosureUsage: AsyncClosureUsage, AsyncFnInTrait: AsyncFnInTrait, NonLocalDefinitions: NonLocalDefinitions::default(), + InteriorMutableConsts: InteriorMutableConsts, ImplTraitOvercaptures: ImplTraitOvercaptures, IfLetRescope: IfLetRescope::default(), StaticMutRefs: StaticMutRefs, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index dc50f61f741d6..096299c16e0fe 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -784,6 +784,39 @@ pub(crate) enum InvalidFromUtf8Diag { }, } +// interior_mutable_consts.rs +#[derive(LintDiagnostic)] +#[diag(lint_const_item_interior_mutations)] +#[note(lint_temporary)] +#[note(lint_never_original)] +#[help] +pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { + pub method_name: Ident, + pub const_name: Ident, + pub const_ty: Ty<'tcx>, + #[label] + pub receiver_span: Span, + #[subdiagnostic] + pub sugg_static: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { + #[suggestion( + lint_suggestion_static, + code = "{before}static ", + style = "verbose", + applicability = "maybe-incorrect" + )] + Spanful { + #[primary_span] + const_: Span, + before: &'static str, + }, + #[help(lint_suggestion_static)] + Spanless, +} + // reference_casting.rs #[derive(LintDiagnostic)] pub(crate) enum InvalidReferenceCastingDiag<'tcx> { diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed b/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed new file mode 100644 index 0000000000000..17737e5cb8b9f --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed @@ -0,0 +1,164 @@ +//@ check-pass +//@ run-rustfix + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(atomic_try_update)] + +use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering}; + +fn atomic_bool() { + static A: AtomicBool = AtomicBool::new(false); + + let _a = A.store(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(false, true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + + let _a = A.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + + let _a = A.fetch_and(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_and` + + let _a = A.fetch_nand(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_nand` + + let _a = A.fetch_or(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` + + let _a = A.fetch_not(Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_not` + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(true)); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(false)); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| true); + //~^ WARN mutation of an interior mutable `const` item with call to `update` +} + +fn atomic_ptr() { + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + + let _a = A.store(std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(std::ptr::null_mut(), std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange( + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + std::ptr::null_mut(), + std::ptr::null_mut(), + Ordering::SeqCst, + Ordering::Relaxed, + ); + + let _a = A.compare_exchange_weak( + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + std::ptr::null_mut(), + std::ptr::null_mut(), + Ordering::SeqCst, + Ordering::Relaxed, + ); + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| std::ptr::null_mut()); + //~^ WARN mutation of an interior mutable `const` item with call to `update` + + let _a = A.fetch_ptr_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_ptr_add` + + let _a = A.fetch_ptr_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_ptr_sub` + + let _a = A.fetch_byte_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_byte_add` + + let _a = A.fetch_byte_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_byte_sub` + + let _a = A.fetch_and(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_and` + + let _a = A.fetch_or(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` +} + +fn atomic_u32() { + static A: AtomicU32 = AtomicU32::new(0); + + let _a = A.store(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(2, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(2, 3, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange(3, 4, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + + let _a = A.compare_exchange_weak(4, 5, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + + let _a = A.fetch_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_add` + + let _a = A.fetch_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_sub` + + let _a = A.fetch_add(2, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_add` + + let _a = A.fetch_nand(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_nand` + + let _a = A.fetch_or(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(10)); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(11)); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| 12); + //~^ WARN mutation of an interior mutable `const` item with call to `update` + + let _a = A.fetch_max(20, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_max` + + let _a = A.fetch_min(5, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_min` +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.rs b/tests/ui/lint/const-item-interior-mutations-const-atomics.rs new file mode 100644 index 0000000000000..4180b2340df6e --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.rs @@ -0,0 +1,164 @@ +//@ check-pass +//@ run-rustfix + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(atomic_try_update)] + +use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering}; + +fn atomic_bool() { + const A: AtomicBool = AtomicBool::new(false); + + let _a = A.store(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(false, true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + + let _a = A.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + + let _a = A.fetch_and(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_and` + + let _a = A.fetch_nand(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_nand` + + let _a = A.fetch_or(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(true, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` + + let _a = A.fetch_not(Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_not` + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(true)); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(false)); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| true); + //~^ WARN mutation of an interior mutable `const` item with call to `update` +} + +fn atomic_ptr() { + const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + + let _a = A.store(std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(std::ptr::null_mut(), std::ptr::null_mut(), Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange( + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + std::ptr::null_mut(), + std::ptr::null_mut(), + Ordering::SeqCst, + Ordering::Relaxed, + ); + + let _a = A.compare_exchange_weak( + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + std::ptr::null_mut(), + std::ptr::null_mut(), + Ordering::SeqCst, + Ordering::Relaxed, + ); + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| std::ptr::null_mut()); + //~^ WARN mutation of an interior mutable `const` item with call to `update` + + let _a = A.fetch_ptr_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_ptr_add` + + let _a = A.fetch_ptr_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_ptr_sub` + + let _a = A.fetch_byte_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_byte_add` + + let _a = A.fetch_byte_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_byte_sub` + + let _a = A.fetch_and(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_and` + + let _a = A.fetch_or(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` +} + +fn atomic_u32() { + const A: AtomicU32 = AtomicU32::new(0); + + let _a = A.store(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `store` + + let _a = A.swap(2, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _a = A.compare_and_swap(2, 3, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_and_swap` + + let _a = A.compare_exchange(3, 4, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange` + + let _a = A.compare_exchange_weak(4, 5, Ordering::SeqCst, Ordering::Relaxed); + //~^ WARN mutation of an interior mutable `const` item with call to `compare_exchange_weak` + + let _a = A.fetch_add(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_add` + + let _a = A.fetch_sub(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_sub` + + let _a = A.fetch_add(2, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_add` + + let _a = A.fetch_nand(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_nand` + + let _a = A.fetch_or(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_or` + + let _a = A.fetch_xor(1, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_xor` + + let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(10)); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_update` + + let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(11)); + //~^ WARN mutation of an interior mutable `const` item with call to `try_update` + + let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| 12); + //~^ WARN mutation of an interior mutable `const` item with call to `update` + + let _a = A.fetch_max(20, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_max` + + let _a = A.fetch_min(5, Ordering::SeqCst); + //~^ WARN mutation of an interior mutable `const` item with call to `fetch_min` +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr b/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr new file mode 100644 index 0000000000000..17823366d406f --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr @@ -0,0 +1,765 @@ +warning: mutation of an interior mutable `const` item with call to `store` + --> $DIR/const-item-interior-mutations-const-atomics.rs:13:14 + | +LL | let _a = A.store(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see + = note: `#[warn(const_item_interior_mutations)]` on by default +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:16:14 + | +LL | let _a = A.swap(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `compare_and_swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:19:14 + | +LL | let _a = A.compare_and_swap(false, true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange` + --> $DIR/const-item-interior-mutations-const-atomics.rs:22:14 + | +LL | let _a = A.compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` + --> $DIR/const-item-interior-mutations-const-atomics.rs:25:14 + | +LL | let _a = A.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_and` + --> $DIR/const-item-interior-mutations-const-atomics.rs:28:14 + | +LL | let _a = A.fetch_and(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_nand` + --> $DIR/const-item-interior-mutations-const-atomics.rs:31:14 + | +LL | let _a = A.fetch_nand(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_or` + --> $DIR/const-item-interior-mutations-const-atomics.rs:34:14 + | +LL | let _a = A.fetch_or(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_xor` + --> $DIR/const-item-interior-mutations-const-atomics.rs:37:14 + | +LL | let _a = A.fetch_xor(true, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_not` + --> $DIR/const-item-interior-mutations-const-atomics.rs:40:14 + | +LL | let _a = A.fetch_not(Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:43:14 + | +LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(true)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `try_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:46:14 + | +LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(false)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:49:14 + | +LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| true); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicBool` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicBool = AtomicBool::new(false); +LL + static A: AtomicBool = AtomicBool::new(false); + | + +warning: mutation of an interior mutable `const` item with call to `store` + --> $DIR/const-item-interior-mutations-const-atomics.rs:56:14 + | +LL | let _a = A.store(std::ptr::null_mut(), Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:59:14 + | +LL | let _a = A.swap(std::ptr::null_mut(), Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `compare_and_swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:62:14 + | +LL | let _a = A.compare_and_swap(std::ptr::null_mut(), std::ptr::null_mut(), Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange` + --> $DIR/const-item-interior-mutations-const-atomics.rs:65:14 + | +LL | let _a = A.compare_exchange( + | ^ `A` is a interior mutable `const` item of type `AtomicPtr` + | ______________| + | | +LL | | +LL | | std::ptr::null_mut(), +LL | | std::ptr::null_mut(), +LL | | Ordering::SeqCst, +LL | | Ordering::Relaxed, +LL | | ); + | |_____^ + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` + --> $DIR/const-item-interior-mutations-const-atomics.rs:73:14 + | +LL | let _a = A.compare_exchange_weak( + | ^ `A` is a interior mutable `const` item of type `AtomicPtr` + | ______________| + | | +LL | | +LL | | std::ptr::null_mut(), +LL | | std::ptr::null_mut(), +LL | | Ordering::SeqCst, +LL | | Ordering::Relaxed, +LL | | ); + | |_____^ + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:81:14 + | +LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `try_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:84:14 + | +LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:87:14 + | +LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| std::ptr::null_mut()); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_ptr_add` + --> $DIR/const-item-interior-mutations-const-atomics.rs:90:14 + | +LL | let _a = A.fetch_ptr_add(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_ptr_sub` + --> $DIR/const-item-interior-mutations-const-atomics.rs:93:14 + | +LL | let _a = A.fetch_ptr_sub(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_byte_add` + --> $DIR/const-item-interior-mutations-const-atomics.rs:96:14 + | +LL | let _a = A.fetch_byte_add(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_byte_sub` + --> $DIR/const-item-interior-mutations-const-atomics.rs:99:14 + | +LL | let _a = A.fetch_byte_sub(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_and` + --> $DIR/const-item-interior-mutations-const-atomics.rs:102:14 + | +LL | let _a = A.fetch_and(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_or` + --> $DIR/const-item-interior-mutations-const-atomics.rs:105:14 + | +LL | let _a = A.fetch_or(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_xor` + --> $DIR/const-item-interior-mutations-const-atomics.rs:108:14 + | +LL | let _a = A.fetch_xor(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicPtr` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + | + +warning: mutation of an interior mutable `const` item with call to `store` + --> $DIR/const-item-interior-mutations-const-atomics.rs:115:14 + | +LL | let _a = A.store(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:118:14 + | +LL | let _a = A.swap(2, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `compare_and_swap` + --> $DIR/const-item-interior-mutations-const-atomics.rs:121:14 + | +LL | let _a = A.compare_and_swap(2, 3, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange` + --> $DIR/const-item-interior-mutations-const-atomics.rs:124:14 + | +LL | let _a = A.compare_exchange(3, 4, Ordering::SeqCst, Ordering::Relaxed); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` + --> $DIR/const-item-interior-mutations-const-atomics.rs:127:14 + | +LL | let _a = A.compare_exchange_weak(4, 5, Ordering::SeqCst, Ordering::Relaxed); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_add` + --> $DIR/const-item-interior-mutations-const-atomics.rs:130:14 + | +LL | let _a = A.fetch_add(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_sub` + --> $DIR/const-item-interior-mutations-const-atomics.rs:133:14 + | +LL | let _a = A.fetch_sub(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_add` + --> $DIR/const-item-interior-mutations-const-atomics.rs:136:14 + | +LL | let _a = A.fetch_add(2, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_nand` + --> $DIR/const-item-interior-mutations-const-atomics.rs:139:14 + | +LL | let _a = A.fetch_nand(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_or` + --> $DIR/const-item-interior-mutations-const-atomics.rs:142:14 + | +LL | let _a = A.fetch_or(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_xor` + --> $DIR/const-item-interior-mutations-const-atomics.rs:145:14 + | +LL | let _a = A.fetch_xor(1, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:148:14 + | +LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(10)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:151:14 + | +LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(11)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `update` + --> $DIR/const-item-interior-mutations-const-atomics.rs:154:14 + | +LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| 12); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_max` + --> $DIR/const-item-interior-mutations-const-atomics.rs:157:14 + | +LL | let _a = A.fetch_max(20, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `fetch_min` + --> $DIR/const-item-interior-mutations-const-atomics.rs:160:14 + | +LL | let _a = A.fetch_min(5, Ordering::SeqCst); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `AtomicU32` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: AtomicU32 = AtomicU32::new(0); +LL + static A: AtomicU32 = AtomicU32::new(0); + | + +warning: 44 warnings emitted + diff --git a/tests/ui/lint/const-item-interior-mutations-const-cell.rs b/tests/ui/lint/const-item-interior-mutations-const-cell.rs new file mode 100644 index 0000000000000..b4a7f54c8e7a0 --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-cell.rs @@ -0,0 +1,105 @@ +//@ check-pass + +#![feature(unsafe_cell_access)] +#![feature(sync_unsafe_cell)] +#![feature(once_cell_try_insert)] +#![feature(once_cell_try)] +#![feature(lazy_get)] + +use std::cell::{Cell, RefCell, SyncUnsafeCell, UnsafeCell}; +use std::cell::{LazyCell, OnceCell}; +use std::ops::Deref; + +fn lazy_cell() { + const A: LazyCell = LazyCell::new(|| 0); + + let _ = LazyCell::force(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `force` +} + +fn once_cell() { + const A: OnceCell = OnceCell::new(); + + let _ = A.set(10); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _ = A.try_insert(20); + //~^ WARN mutation of an interior mutable `const` item with call to `try_insert` + + let _ = A.get_or_init(|| 30); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_init` + + let _ = A.get_or_try_init(|| Ok::<_, ()>(40)); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_try_init` +} + +fn cell() { + const A: Cell = Cell::new(0); + + let _ = A.set(1); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _ = A.swap(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _ = A.replace(2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + let _ = A.get(); + //~^ WARN mutation of an interior mutable `const` item with call to `get` + + let _ = A.update(|x| x + 1); + //~^ WARN mutation of an interior mutable `const` item with call to `update` +} + +fn ref_cell() { + const A: RefCell = RefCell::new(0); + + let _ = A.replace(1); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + let _ = A.replace_with(|x| *x + 2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace_with` + + let _ = A.swap(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `swap` + + let _ = A.borrow(); + //~^ WARN mutation of an interior mutable `const` item with call to `borrow` + + let _ = A.try_borrow(); + //~^ WARN mutation of an interior mutable `const` item with call to `try_borrow` + + let _ = A.borrow_mut(); + //~^ WARN mutation of an interior mutable `const` item with call to `borrow_mut` + + let _ = A.try_borrow_mut(); + //~^ WARN mutation of an interior mutable `const` item with call to `try_borrow_mut` +} + +fn unsafe_cell() { + const A: UnsafeCell = UnsafeCell::new(0); + + let _ = unsafe { A.replace(1) }; + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + let _ = A.get(); + //~^ WARN mutation of an interior mutable `const` item with call to `get` + + unsafe { + let _ = A.as_ref_unchecked(); + //~^ WARN mutation of an interior mutable `const` item with call to `as_ref_unchecked` + + let _ = A.as_mut_unchecked(); + //~^ WARN mutation of an interior mutable `const` item with call to `as_mut_unchecked` + } +} + +fn sync_unsafe_cell() { + const A: SyncUnsafeCell = SyncUnsafeCell::new(0); + + let _ = A.get(); + //~^ WARN mutation of an interior mutable `const` item with call to `get` +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const-cell.stderr b/tests/ui/lint/const-item-interior-mutations-const-cell.stderr new file mode 100644 index 0000000000000..d9f19c61fa773 --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const-cell.stderr @@ -0,0 +1,377 @@ +warning: mutation of an interior mutable `const` item with call to `force` + --> $DIR/const-item-interior-mutations-const-cell.rs:16:13 + | +LL | let _ = LazyCell::force(&A); + | ^^^^^^^^^^^^^^^^^-^ + | | + | `A` is a interior mutable `const` item of type `LazyCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see + = note: `#[warn(const_item_interior_mutations)]` on by default +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: LazyCell = LazyCell::new(|| 0); +LL + static A: LazyCell = LazyCell::new(|| 0); + | + +warning: mutation of an interior mutable `const` item with call to `set` + --> $DIR/const-item-interior-mutations-const-cell.rs:23:13 + | +LL | let _ = A.set(10); + | -^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceCell = OnceCell::new(); +LL + static A: OnceCell = OnceCell::new(); + | + +warning: mutation of an interior mutable `const` item with call to `try_insert` + --> $DIR/const-item-interior-mutations-const-cell.rs:26:13 + | +LL | let _ = A.try_insert(20); + | -^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceCell = OnceCell::new(); +LL + static A: OnceCell = OnceCell::new(); + | + +warning: mutation of an interior mutable `const` item with call to `get_or_init` + --> $DIR/const-item-interior-mutations-const-cell.rs:29:13 + | +LL | let _ = A.get_or_init(|| 30); + | -^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceCell = OnceCell::new(); +LL + static A: OnceCell = OnceCell::new(); + | + +warning: mutation of an interior mutable `const` item with call to `get_or_try_init` + --> $DIR/const-item-interior-mutations-const-cell.rs:32:13 + | +LL | let _ = A.get_or_try_init(|| Ok::<_, ()>(40)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceCell = OnceCell::new(); +LL + static A: OnceCell = OnceCell::new(); + | + +warning: mutation of an interior mutable `const` item with call to `set` + --> $DIR/const-item-interior-mutations-const-cell.rs:39:13 + | +LL | let _ = A.set(1); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `Cell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Cell = Cell::new(0); +LL + static A: Cell = Cell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `swap` + --> $DIR/const-item-interior-mutations-const-cell.rs:42:13 + | +LL | let _ = A.swap(&A); + | -^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `Cell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Cell = Cell::new(0); +LL + static A: Cell = Cell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace` + --> $DIR/const-item-interior-mutations-const-cell.rs:45:13 + | +LL | let _ = A.replace(2); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `Cell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Cell = Cell::new(0); +LL + static A: Cell = Cell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `get` + --> $DIR/const-item-interior-mutations-const-cell.rs:48:13 + | +LL | let _ = A.get(); + | -^^^^^^ + | | + | `A` is a interior mutable `const` item of type `Cell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Cell = Cell::new(0); +LL + static A: Cell = Cell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `update` + --> $DIR/const-item-interior-mutations-const-cell.rs:51:13 + | +LL | let _ = A.update(|x| x + 1); + | -^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `Cell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Cell = Cell::new(0); +LL + static A: Cell = Cell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace` + --> $DIR/const-item-interior-mutations-const-cell.rs:58:13 + | +LL | let _ = A.replace(1); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace_with` + --> $DIR/const-item-interior-mutations-const-cell.rs:61:13 + | +LL | let _ = A.replace_with(|x| *x + 2); + | -^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `swap` + --> $DIR/const-item-interior-mutations-const-cell.rs:64:13 + | +LL | let _ = A.swap(&A); + | -^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `borrow` + --> $DIR/const-item-interior-mutations-const-cell.rs:67:13 + | +LL | let _ = A.borrow(); + | -^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_borrow` + --> $DIR/const-item-interior-mutations-const-cell.rs:70:13 + | +LL | let _ = A.try_borrow(); + | -^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `borrow_mut` + --> $DIR/const-item-interior-mutations-const-cell.rs:73:13 + | +LL | let _ = A.borrow_mut(); + | -^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_borrow_mut` + --> $DIR/const-item-interior-mutations-const-cell.rs:76:13 + | +LL | let _ = A.try_borrow_mut(); + | -^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `RefCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RefCell = RefCell::new(0); +LL + static A: RefCell = RefCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace` + --> $DIR/const-item-interior-mutations-const-cell.rs:83:22 + | +LL | let _ = unsafe { A.replace(1) }; + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `UnsafeCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: UnsafeCell = UnsafeCell::new(0); +LL + static A: UnsafeCell = UnsafeCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `get` + --> $DIR/const-item-interior-mutations-const-cell.rs:86:13 + | +LL | let _ = A.get(); + | -^^^^^^ + | | + | `A` is a interior mutable `const` item of type `UnsafeCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: UnsafeCell = UnsafeCell::new(0); +LL + static A: UnsafeCell = UnsafeCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `as_ref_unchecked` + --> $DIR/const-item-interior-mutations-const-cell.rs:90:17 + | +LL | let _ = A.as_ref_unchecked(); + | -^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `UnsafeCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: UnsafeCell = UnsafeCell::new(0); +LL + static A: UnsafeCell = UnsafeCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `as_mut_unchecked` + --> $DIR/const-item-interior-mutations-const-cell.rs:93:17 + | +LL | let _ = A.as_mut_unchecked(); + | -^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `UnsafeCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: UnsafeCell = UnsafeCell::new(0); +LL + static A: UnsafeCell = UnsafeCell::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `get` + --> $DIR/const-item-interior-mutations-const-cell.rs:101:13 + | +LL | let _ = A.get(); + | -^^^^^^ + | | + | `A` is a interior mutable `const` item of type `SyncUnsafeCell` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: SyncUnsafeCell = SyncUnsafeCell::new(0); +LL + static A: SyncUnsafeCell = SyncUnsafeCell::new(0); + | + +warning: 22 warnings emitted + diff --git a/tests/ui/lint/const-item-interior-mutations-const.fixed b/tests/ui/lint/const-item-interior-mutations-const.fixed new file mode 100644 index 0000000000000..82f3fdac43a3a --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const.fixed @@ -0,0 +1,139 @@ +//@ check-pass +//@ run-rustfix + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(lock_value_accessors)] +#![feature(once_cell_try_insert)] +#![feature(once_cell_try)] +#![feature(lazy_get)] + +use std::sync::{Condvar, LazyLock, Mutex, Once, OnceLock, RwLock}; +use std::time::Duration; + +fn mutex() { + static A: Mutex = Mutex::new(0); + + let _a = A.set(1); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.replace(2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + drop(A.lock()); + //~^ WARN mutation of an interior mutable `const` item with call to `lock` + + drop(A.try_lock()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_lock` + + let _a = A.clear_poison(); + //~^ WARN mutation of an interior mutable `const` item with call to `clear_poison` +} + +fn once() { + static A: Once = Once::new(); + + let _a = A.call_once(|| {}); + //~^ WARN mutation of an interior mutable `const` item with call to `call_once` + + let _a = A.call_once_force(|_| {}); + //~^ WARN mutation of an interior mutable `const` item with call to `call_once_force` + + let _a = A.wait(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let _a = A.wait_force(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_force` +} + +fn rwlock() { + static A: RwLock = RwLock::new(0); + + let _a = A.set(1); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.replace(2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + drop(A.read()); + //~^ WARN mutation of an interior mutable `const` item with call to `read` + + drop(A.try_read()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_read` + + drop(A.write()); + //~^ WARN mutation of an interior mutable `const` item with call to `write` + + drop(A.try_write()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_write` +} + +fn lazy_lock() { + static A: LazyLock = LazyLock::new(|| 0); + + let _a = LazyLock::force(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `force` + + let _a = LazyLock::get(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `get` +} + +fn once_lock() { + static A: OnceLock = OnceLock::new(); + + let _a = A.get(); + //~^ WARN mutation of an interior mutable `const` item with call to `get` + + let _a = A.wait(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let _a = A.set(10); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.try_insert(20); + //~^ WARN mutation of an interior mutable `const` item with call to `try_insert` + + let _a = A.get_or_init(|| 30); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_init` + + let _a = A.get_or_try_init(|| Ok::<_, ()>(40)); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_try_init` +} + +fn condvar() { + static A: Condvar = Condvar::new(); + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + + let _a = A.wait(guard); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_while(guard, |x| *x == 0); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_while` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout_ms(guard, 10); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout_ms` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout(guard, Duration::from_millis(10)); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout_while(guard, Duration::from_millis(10), |x| *x == 0); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout_while` + + let _a = A.notify_one(); + //~^ WARN mutation of an interior mutable `const` item with call to `notify_one` + + let _a = A.notify_all(); + //~^ WARN mutation of an interior mutable `const` item with call to `notify_all` +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const.rs b/tests/ui/lint/const-item-interior-mutations-const.rs new file mode 100644 index 0000000000000..5dbbfd8ca32f2 --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const.rs @@ -0,0 +1,139 @@ +//@ check-pass +//@ run-rustfix + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(lock_value_accessors)] +#![feature(once_cell_try_insert)] +#![feature(once_cell_try)] +#![feature(lazy_get)] + +use std::sync::{Condvar, LazyLock, Mutex, Once, OnceLock, RwLock}; +use std::time::Duration; + +fn mutex() { + const A: Mutex = Mutex::new(0); + + let _a = A.set(1); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.replace(2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + drop(A.lock()); + //~^ WARN mutation of an interior mutable `const` item with call to `lock` + + drop(A.try_lock()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_lock` + + let _a = A.clear_poison(); + //~^ WARN mutation of an interior mutable `const` item with call to `clear_poison` +} + +fn once() { + const A: Once = Once::new(); + + let _a = A.call_once(|| {}); + //~^ WARN mutation of an interior mutable `const` item with call to `call_once` + + let _a = A.call_once_force(|_| {}); + //~^ WARN mutation of an interior mutable `const` item with call to `call_once_force` + + let _a = A.wait(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let _a = A.wait_force(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_force` +} + +fn rwlock() { + const A: RwLock = RwLock::new(0); + + let _a = A.set(1); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.replace(2); + //~^ WARN mutation of an interior mutable `const` item with call to `replace` + + drop(A.read()); + //~^ WARN mutation of an interior mutable `const` item with call to `read` + + drop(A.try_read()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_read` + + drop(A.write()); + //~^ WARN mutation of an interior mutable `const` item with call to `write` + + drop(A.try_write()); + //~^ WARN mutation of an interior mutable `const` item with call to `try_write` +} + +fn lazy_lock() { + const A: LazyLock = LazyLock::new(|| 0); + + let _a = LazyLock::force(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `force` + + let _a = LazyLock::get(&A); + //~^ WARN mutation of an interior mutable `const` item with call to `get` +} + +fn once_lock() { + const A: OnceLock = OnceLock::new(); + + let _a = A.get(); + //~^ WARN mutation of an interior mutable `const` item with call to `get` + + let _a = A.wait(); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let _a = A.set(10); + //~^ WARN mutation of an interior mutable `const` item with call to `set` + + let _a = A.try_insert(20); + //~^ WARN mutation of an interior mutable `const` item with call to `try_insert` + + let _a = A.get_or_init(|| 30); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_init` + + let _a = A.get_or_try_init(|| Ok::<_, ()>(40)); + //~^ WARN mutation of an interior mutable `const` item with call to `get_or_try_init` +} + +fn condvar() { + const A: Condvar = Condvar::new(); + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + + let _a = A.wait(guard); + //~^ WARN mutation of an interior mutable `const` item with call to `wait` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_while(guard, |x| *x == 0); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_while` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout_ms(guard, 10); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout_ms` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout(guard, Duration::from_millis(10)); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout` + + let mutex = Mutex::new(0); + let guard = mutex.lock().unwrap(); + let _a = A.wait_timeout_while(guard, Duration::from_millis(10), |x| *x == 0); + //~^ WARN mutation of an interior mutable `const` item with call to `wait_timeout_while` + + let _a = A.notify_one(); + //~^ WARN mutation of an interior mutable `const` item with call to `notify_one` + + let _a = A.notify_all(); + //~^ WARN mutation of an interior mutable `const` item with call to `notify_all` +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const.stderr b/tests/ui/lint/const-item-interior-mutations-const.stderr new file mode 100644 index 0000000000000..7d3e7bee7fbb0 --- /dev/null +++ b/tests/ui/lint/const-item-interior-mutations-const.stderr @@ -0,0 +1,513 @@ +warning: mutation of an interior mutable `const` item with call to `set` + --> $DIR/const-item-interior-mutations-const.rs:17:14 + | +LL | let _a = A.set(1); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Mutex` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see + = note: `#[warn(const_item_interior_mutations)]` on by default +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Mutex = Mutex::new(0); +LL + static A: Mutex = Mutex::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace` + --> $DIR/const-item-interior-mutations-const.rs:20:14 + | +LL | let _a = A.replace(2); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Mutex` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Mutex = Mutex::new(0); +LL + static A: Mutex = Mutex::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `lock` + --> $DIR/const-item-interior-mutations-const.rs:23:10 + | +LL | drop(A.lock()); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Mutex` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Mutex = Mutex::new(0); +LL + static A: Mutex = Mutex::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_lock` + --> $DIR/const-item-interior-mutations-const.rs:26:10 + | +LL | drop(A.try_lock()); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Mutex` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Mutex = Mutex::new(0); +LL + static A: Mutex = Mutex::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `clear_poison` + --> $DIR/const-item-interior-mutations-const.rs:29:14 + | +LL | let _a = A.clear_poison(); + | -^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Mutex` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Mutex = Mutex::new(0); +LL + static A: Mutex = Mutex::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `call_once` + --> $DIR/const-item-interior-mutations-const.rs:36:14 + | +LL | let _a = A.call_once(|| {}); + | -^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Once` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Once = Once::new(); +LL + static A: Once = Once::new(); + | + +warning: mutation of an interior mutable `const` item with call to `call_once_force` + --> $DIR/const-item-interior-mutations-const.rs:39:14 + | +LL | let _a = A.call_once_force(|_| {}); + | -^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Once` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Once = Once::new(); +LL + static A: Once = Once::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait` + --> $DIR/const-item-interior-mutations-const.rs:42:14 + | +LL | let _a = A.wait(); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Once` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Once = Once::new(); +LL + static A: Once = Once::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait_force` + --> $DIR/const-item-interior-mutations-const.rs:45:14 + | +LL | let _a = A.wait_force(); + | -^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Once` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Once = Once::new(); +LL + static A: Once = Once::new(); + | + +warning: mutation of an interior mutable `const` item with call to `set` + --> $DIR/const-item-interior-mutations-const.rs:52:14 + | +LL | let _a = A.set(1); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `replace` + --> $DIR/const-item-interior-mutations-const.rs:55:14 + | +LL | let _a = A.replace(2); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `read` + --> $DIR/const-item-interior-mutations-const.rs:58:10 + | +LL | drop(A.read()); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_read` + --> $DIR/const-item-interior-mutations-const.rs:61:10 + | +LL | drop(A.try_read()); + | -^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `write` + --> $DIR/const-item-interior-mutations-const.rs:64:10 + | +LL | drop(A.write()); + | -^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `try_write` + --> $DIR/const-item-interior-mutations-const.rs:67:10 + | +LL | drop(A.try_write()); + | -^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::RwLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: RwLock = RwLock::new(0); +LL + static A: RwLock = RwLock::new(0); + | + +warning: mutation of an interior mutable `const` item with call to `force` + --> $DIR/const-item-interior-mutations-const.rs:74:14 + | +LL | let _a = LazyLock::force(&A); + | ^^^^^^^^^^^^^^^^^-^ + | | + | `A` is a interior mutable `const` item of type `LazyLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: LazyLock = LazyLock::new(|| 0); +LL + static A: LazyLock = LazyLock::new(|| 0); + | + +warning: mutation of an interior mutable `const` item with call to `get` + --> $DIR/const-item-interior-mutations-const.rs:77:14 + | +LL | let _a = LazyLock::get(&A); + | ^^^^^^^^^^^^^^^-^ + | | + | `A` is a interior mutable `const` item of type `LazyLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: LazyLock = LazyLock::new(|| 0); +LL + static A: LazyLock = LazyLock::new(|| 0); + | + +warning: mutation of an interior mutable `const` item with call to `get` + --> $DIR/const-item-interior-mutations-const.rs:84:14 + | +LL | let _a = A.get(); + | -^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait` + --> $DIR/const-item-interior-mutations-const.rs:87:14 + | +LL | let _a = A.wait(); + | -^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `set` + --> $DIR/const-item-interior-mutations-const.rs:90:14 + | +LL | let _a = A.set(10); + | -^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `try_insert` + --> $DIR/const-item-interior-mutations-const.rs:93:14 + | +LL | let _a = A.try_insert(20); + | -^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `get_or_init` + --> $DIR/const-item-interior-mutations-const.rs:96:14 + | +LL | let _a = A.get_or_init(|| 30); + | -^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `get_or_try_init` + --> $DIR/const-item-interior-mutations-const.rs:99:14 + | +LL | let _a = A.get_or_try_init(|| Ok::<_, ()>(40)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `OnceLock` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: OnceLock = OnceLock::new(); +LL + static A: OnceLock = OnceLock::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait` + --> $DIR/const-item-interior-mutations-const.rs:109:14 + | +LL | let _a = A.wait(guard); + | -^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait_while` + --> $DIR/const-item-interior-mutations-const.rs:114:14 + | +LL | let _a = A.wait_while(guard, |x| *x == 0); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait_timeout_ms` + --> $DIR/const-item-interior-mutations-const.rs:119:14 + | +LL | let _a = A.wait_timeout_ms(guard, 10); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait_timeout` + --> $DIR/const-item-interior-mutations-const.rs:124:14 + | +LL | let _a = A.wait_timeout(guard, Duration::from_millis(10)); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `wait_timeout_while` + --> $DIR/const-item-interior-mutations-const.rs:129:14 + | +LL | let _a = A.wait_timeout_while(guard, Duration::from_millis(10), |x| *x == 0); + | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `notify_one` + --> $DIR/const-item-interior-mutations-const.rs:132:14 + | +LL | let _a = A.notify_one(); + | -^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: mutation of an interior mutable `const` item with call to `notify_all` + --> $DIR/const-item-interior-mutations-const.rs:135:14 + | +LL | let _a = A.notify_all(); + | -^^^^^^^^^^^^^ + | | + | `A` is a interior mutable `const` item of type `std::sync::Condvar` + | + = note: each usage of a `const` item creates a new temporary + = note: only the temporaries and never the original `const A` will be modified + = help: for more details on interior mutability see +help: for a shared instance of `A`, consider making it a `static` item instead + | +LL - const A: Condvar = Condvar::new(); +LL + static A: Condvar = Condvar::new(); + | + +warning: 30 warnings emitted + From ddabb1c13973b85a6a8475f9b98394d12e9211dc Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 2 Nov 2025 16:57:29 +0100 Subject: [PATCH 17/18] Allow `const_item_interior_mutations` in Clippy tests --- .../tests/ui/borrow_interior_mutable_const.rs | 1 + .../ui/borrow_interior_mutable_const.stderr | 58 +++++++++---------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs index 674450a73ad23..39d6e76d5d002 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.rs @@ -4,6 +4,7 @@ #![allow( clippy::declare_interior_mutable_const, clippy::out_of_bounds_indexing, + const_item_interior_mutations, const_item_mutation, unconditional_panic )] diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr index e7c3f879b05b0..b3b1eb858e475 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const.stderr @@ -1,5 +1,5 @@ error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:35:17 + --> tests/ui/borrow_interior_mutable_const.rs:36:17 | LL | let _ = &C; | ^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::borrow_interior_mutable_const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:37:17 + --> tests/ui/borrow_interior_mutable_const.rs:38:17 | LL | let _ = C.get(); | ^ @@ -21,7 +21,7 @@ LL | let _ = C.get(); = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:42:17 + --> tests/ui/borrow_interior_mutable_const.rs:43:17 | LL | let _ = &C; | ^^ @@ -29,7 +29,7 @@ LL | let _ = &C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:43:17 + --> tests/ui/borrow_interior_mutable_const.rs:44:17 | LL | let _ = &mut C; | ^^^^^^ @@ -37,7 +37,7 @@ LL | let _ = &mut C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:47:9 + --> tests/ui/borrow_interior_mutable_const.rs:48:9 | LL | C.swap(&local) | ^ @@ -46,7 +46,7 @@ LL | C.swap(&local) = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:52:17 + --> tests/ui/borrow_interior_mutable_const.rs:53:17 | LL | let _ = &C; | ^^ @@ -54,7 +54,7 @@ LL | let _ = &C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:53:17 + --> tests/ui/borrow_interior_mutable_const.rs:54:17 | LL | let _ = &C[0]; | ^^^^^ @@ -62,7 +62,7 @@ LL | let _ = &C[0]; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:54:17 + --> tests/ui/borrow_interior_mutable_const.rs:55:17 | LL | let _ = &C[0].0; | ^^^^^^^ @@ -70,7 +70,7 @@ LL | let _ = &C[0].0; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:55:9 + --> tests/ui/borrow_interior_mutable_const.rs:56:9 | LL | C[0].0.set(1); | ^^^^^^ @@ -79,7 +79,7 @@ LL | C[0].0.set(1); = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:70:17 + --> tests/ui/borrow_interior_mutable_const.rs:71:17 | LL | let _ = &S::C; | ^^^^^ @@ -87,7 +87,7 @@ LL | let _ = &S::C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:71:17 + --> tests/ui/borrow_interior_mutable_const.rs:72:17 | LL | let _ = &S::C.0; | ^^^^^^^ @@ -95,7 +95,7 @@ LL | let _ = &S::C.0; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:72:9 + --> tests/ui/borrow_interior_mutable_const.rs:73:9 | LL | S::C.set(1); | ^^^^ @@ -104,7 +104,7 @@ LL | S::C.set(1); = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:73:18 + --> tests/ui/borrow_interior_mutable_const.rs:74:18 | LL | let _ = &*S::C; | ^^^^^ @@ -113,7 +113,7 @@ LL | let _ = &*S::C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:74:9 + --> tests/ui/borrow_interior_mutable_const.rs:75:9 | LL | (*S::C).set(1); | ^^^^^^^ @@ -122,7 +122,7 @@ LL | (*S::C).set(1); = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:85:17 + --> tests/ui/borrow_interior_mutable_const.rs:86:17 | LL | let _ = &CELL; | ^^^^^ @@ -130,7 +130,7 @@ LL | let _ = &CELL; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:109:25 + --> tests/ui/borrow_interior_mutable_const.rs:110:25 | LL | let _ = &Self::C; | ^^^^^^^^ @@ -138,7 +138,7 @@ LL | let _ = &Self::C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:112:25 + --> tests/ui/borrow_interior_mutable_const.rs:113:25 | LL | let _ = &Self::C.cell; | ^^^^^^^^^^^^^ @@ -146,7 +146,7 @@ LL | let _ = &Self::C.cell; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:113:25 + --> tests/ui/borrow_interior_mutable_const.rs:114:25 | LL | let _ = &Self::C.cell.0; | ^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | let _ = &Self::C.cell.0; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:114:17 + --> tests/ui/borrow_interior_mutable_const.rs:115:17 | LL | Self::C.cell.0.set(T::DEFAULT); | ^^^^^^^^^^^^^^ @@ -163,7 +163,7 @@ LL | Self::C.cell.0.set(T::DEFAULT); = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:128:17 + --> tests/ui/borrow_interior_mutable_const.rs:129:17 | LL | let _ = &u32::VALUE; | ^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | let _ = &u32::VALUE; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:145:21 + --> tests/ui/borrow_interior_mutable_const.rs:146:21 | LL | let _ = &>::VALUE; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +179,7 @@ LL | let _ = &>::VALUE; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:172:17 + --> tests/ui/borrow_interior_mutable_const.rs:173:17 | LL | let _ = &C; | ^^ @@ -187,7 +187,7 @@ LL | let _ = &C; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:173:18 + --> tests/ui/borrow_interior_mutable_const.rs:174:18 | LL | let _ = &C[0]; | ^^^^ @@ -196,7 +196,7 @@ LL | let _ = &C[0]; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:174:17 + --> tests/ui/borrow_interior_mutable_const.rs:175:17 | LL | let _ = &C.0[0]; | ^^^^^^^ @@ -204,7 +204,7 @@ LL | let _ = &C.0[0]; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:190:17 + --> tests/ui/borrow_interior_mutable_const.rs:191:17 | LL | let _ = &C[1]; | ^^^^^ @@ -212,7 +212,7 @@ LL | let _ = &C[1]; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:194:21 + --> tests/ui/borrow_interior_mutable_const.rs:195:21 | LL | let _ = &C[i]; | ^^^^^ @@ -220,7 +220,7 @@ LL | let _ = &C[i]; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:198:17 + --> tests/ui/borrow_interior_mutable_const.rs:199:17 | LL | let _ = &interior_mutable_const::WRAPPED_PRIVATE_UNFROZEN_VARIANT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -228,7 +228,7 @@ LL | let _ = &interior_mutable_const::WRAPPED_PRIVATE_UNFROZEN_VARIANT; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:216:17 + --> tests/ui/borrow_interior_mutable_const.rs:217:17 | LL | let _ = &S::VALUE; | ^^^^^^^^^ @@ -236,7 +236,7 @@ LL | let _ = &S::VALUE; = help: this lint can be silenced by assigning the value to a local variable before borrowing error: borrow of a named constant with interior mutability - --> tests/ui/borrow_interior_mutable_const.rs:218:17 + --> tests/ui/borrow_interior_mutable_const.rs:219:17 | LL | let _ = &S::VALUE.1; | ^^^^^^^^^^^ From c48dce11871a5cfe2c0475ea35c5086436d5f32e Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 2 Nov 2025 18:13:14 +0100 Subject: [PATCH 18/18] Allow `const_item_interior_mutations` in tests --- tests/ui/consts/issue-17718.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ui/consts/issue-17718.rs b/tests/ui/consts/issue-17718.rs index b6c676886c10d..33e2d791840e6 100644 --- a/tests/ui/consts/issue-17718.rs +++ b/tests/ui/consts/issue-17718.rs @@ -1,7 +1,9 @@ //@ run-pass -#![allow(dead_code)] //@ aux-build:issue-17718-aux.rs +#![allow(dead_code)] +#![allow(const_item_interior_mutations)] + extern crate issue_17718_aux as other; use std::sync::atomic::{AtomicUsize, Ordering};