diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs index a8457043278..e2d50ba034a 100644 --- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs +++ b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs @@ -66,12 +66,14 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> { location: Location, decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b>, ) { - // Don't lint on borrowing/assigning to a dereference - // e.g: + // Don't lint on borrowing/assigning when a dereference is involved. + // If we 'leave' the temporary via a dereference, we must + // be modifying something else // // `unsafe { *FOO = 0; *BAR.field = 1; }` // `unsafe { &mut *FOO }` - if !matches!(place.projection.last(), Some(PlaceElem::Deref)) { + // `unsafe { (*ARRAY)[0] = val; } + if !place.projection.iter().any(|p| matches!(p, PlaceElem::Deref)) { let source_info = self.body.source_info(location); let lint_root = self.body.source_scopes[source_info.scope] .local_data diff --git a/src/test/ui/lint/lint-const-item-mutation.rs b/src/test/ui/lint/lint-const-item-mutation.rs index ef55f31593b..4bf5e0a9e21 100644 --- a/src/test/ui/lint/lint-const-item-mutation.rs +++ b/src/test/ui/lint/lint-const-item-mutation.rs @@ -30,6 +30,8 @@ const MUTABLE: Mutable = Mutable { msg: "" }; const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; const VEC: Vec = Vec::new(); const PTR: *mut () = 1 as *mut _; +const PTR_TO_ARRAY: *mut [u32; 4] = 0x12345678 as _; +const ARRAY_OF_PTR: [*mut u32; 1] = [1 as *mut _]; fn main() { ARRAY[0] = 5; //~ WARN attempting to modify @@ -55,4 +57,10 @@ fn main() { // Test that we don't warn when converting a raw pointer // into a mutable reference unsafe { &mut *PTR }; + + // Test that we don't warn when there's a dereference involved. + // If we ever 'leave' the const via a deference, we're going + // to end up modifying something other than the temporary + unsafe { (*PTR_TO_ARRAY)[0] = 1 }; + unsafe { *ARRAY_OF_PTR[0] = 25; } } diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr index ae95abc72f3..74505eeb987 100644 --- a/src/test/ui/lint/lint-const-item-mutation.stderr +++ b/src/test/ui/lint/lint-const-item-mutation.stderr @@ -1,5 +1,5 @@ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:35:5 + --> $DIR/lint-const-item-mutation.rs:37:5 | LL | ARRAY[0] = 5; | ^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | const ARRAY: [u8; 1] = [25]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:36:5 + --> $DIR/lint-const-item-mutation.rs:38:5 | LL | MY_STRUCT.field = false; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:37:5 + --> $DIR/lint-const-item-mutation.rs:39:5 | LL | MY_STRUCT.inner_array[0] = 'b'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:38:5 + --> $DIR/lint-const-item-mutation.rs:40:5 | LL | MY_STRUCT.use_mut(); | ^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:39:5 + --> $DIR/lint-const-item-mutation.rs:41:5 | LL | &mut MY_STRUCT; | ^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:40:5 + --> $DIR/lint-const-item-mutation.rs:42:5 | LL | (&mut MY_STRUCT).use_mut(); | ^^^^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:52:5 + --> $DIR/lint-const-item-mutation.rs:54:5 | LL | MUTABLE2.msg = "wow"; | ^^^^^^^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:53:5 + --> $DIR/lint-const-item-mutation.rs:55:5 | LL | VEC.push(0); | ^^^^^^^^^^^