Skip to content

Commit 1a22aee

Browse files
committed
Constants of primitive types are always deterministic.
1 parent 16846c5 commit 1a22aee

6 files changed

+64
-81
lines changed

compiler/rustc_middle/src/mir/consts.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,11 @@ impl<'tcx> Const<'tcx> {
495495
/// Return true if any evaluation of this constant always returns the same value,
496496
/// taking into account even pointer identity tests.
497497
pub fn is_deterministic(&self) -> bool {
498+
// Primitive types cannot contain provenance and always have the same value.
499+
if self.ty().is_primitive() {
500+
return true;
501+
}
502+
498503
// Some constants may generate fresh allocations for pointers they contain,
499504
// so using the same constant twice can yield two different results.
500505
// Notably, valtrees purposefully generate new allocations.
@@ -504,24 +509,19 @@ impl<'tcx> Const<'tcx> {
504509
// A valtree may be a reference. Valtree references correspond to a
505510
// different allocation each time they are evaluated. Valtrees for primitive
506511
// types are fine though.
507-
ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
508-
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
512+
ty::ConstKind::Value(..)
513+
| ty::ConstKind::Expr(..)
514+
| ty::ConstKind::Unevaluated(..)
509515
// This can happen if evaluation of a constant failed. The result does not matter
510516
// much since compilation is doomed.
511-
ty::ConstKind::Error(..) => false,
517+
| ty::ConstKind::Error(..) => false,
512518
// Should not appear in runtime MIR.
513519
ty::ConstKind::Infer(..)
514520
| ty::ConstKind::Bound(..)
515521
| ty::ConstKind::Placeholder(..) => bug!(),
516522
},
517523
Const::Unevaluated(..) => false,
518-
Const::Val(
519-
ConstValue::Slice { .. }
520-
| ConstValue::ZeroSized
521-
| ConstValue::Scalar(_)
522-
| ConstValue::Indirect { .. },
523-
_,
524-
) => true,
524+
Const::Val(..) => true,
525525
}
526526
}
527527
}

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _11: ();
11+
let _10: ();
1212
scope 3 {
13-
let _8: std::ptr::alignment::AlignmentEnum;
13+
let _7: std::ptr::alignment::AlignmentEnum;
1414
scope 4 {
1515
scope 12 (inlined Layout::size) {
1616
}
@@ -25,13 +25,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2525
}
2626
}
2727
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
28-
let mut _9: *mut u8;
28+
let mut _8: *mut u8;
2929
scope 19 (inlined Layout::size) {
3030
}
3131
scope 20 (inlined NonNull::<u8>::as_ptr) {
3232
}
3333
scope 21 (inlined std::alloc::dealloc) {
34-
let mut _10: usize;
34+
let mut _9: usize;
3535
scope 22 (inlined Layout::size) {
3636
}
3737
scope 23 (inlined Layout::align) {
@@ -47,10 +47,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
4747
}
4848
scope 7 (inlined Layout::for_value_raw::<[T]>) {
4949
let mut _5: usize;
50-
let mut _6: usize;
5150
scope 8 {
5251
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
53-
let mut _7: std::ptr::Alignment;
52+
let mut _6: std::ptr::Alignment;
5453
}
5554
}
5655
scope 9 (inlined size_of_val_raw::<[T]>) {
@@ -68,32 +67,29 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
6867
StorageLive(_4);
6968
_3 = copy _2 as *mut [T] (Transmute);
7069
_4 = copy _2 as *const [T] (Transmute);
71-
StorageLive(_6);
7270
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
7371
}
7472

7573
bb1: {
76-
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
77-
StorageLive(_7);
78-
_7 = copy _6 as std::ptr::Alignment (Transmute);
79-
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
80-
StorageDead(_7);
74+
StorageLive(_6);
75+
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
76+
_7 = move (_6.0: std::ptr::alignment::AlignmentEnum);
8177
StorageDead(_6);
8278
StorageDead(_4);
8379
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
8480
}
8581

8682
bb2: {
83+
StorageLive(_8);
84+
_8 = copy _3 as *mut u8 (PtrToPtr);
8785
StorageLive(_9);
88-
_9 = copy _3 as *mut u8 (PtrToPtr);
89-
StorageLive(_10);
90-
_10 = discriminant(_8);
91-
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
86+
_9 = discriminant(_7);
87+
_10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable];
9288
}
9389

9490
bb3: {
95-
StorageDead(_10);
9691
StorageDead(_9);
92+
StorageDead(_8);
9793
goto -> bb4;
9894
}
9995

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _11: ();
11+
let _10: ();
1212
scope 3 {
13-
let _8: std::ptr::alignment::AlignmentEnum;
13+
let _7: std::ptr::alignment::AlignmentEnum;
1414
scope 4 {
1515
scope 12 (inlined Layout::size) {
1616
}
@@ -25,13 +25,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2525
}
2626
}
2727
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
28-
let mut _9: *mut u8;
28+
let mut _8: *mut u8;
2929
scope 19 (inlined Layout::size) {
3030
}
3131
scope 20 (inlined NonNull::<u8>::as_ptr) {
3232
}
3333
scope 21 (inlined std::alloc::dealloc) {
34-
let mut _10: usize;
34+
let mut _9: usize;
3535
scope 22 (inlined Layout::size) {
3636
}
3737
scope 23 (inlined Layout::align) {
@@ -47,10 +47,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
4747
}
4848
scope 7 (inlined Layout::for_value_raw::<[T]>) {
4949
let mut _5: usize;
50-
let mut _6: usize;
5150
scope 8 {
5251
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
53-
let mut _7: std::ptr::Alignment;
52+
let mut _6: std::ptr::Alignment;
5453
}
5554
}
5655
scope 9 (inlined size_of_val_raw::<[T]>) {
@@ -68,32 +67,29 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
6867
StorageLive(_4);
6968
_3 = copy _2 as *mut [T] (Transmute);
7069
_4 = copy _2 as *const [T] (Transmute);
71-
StorageLive(_6);
7270
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
7371
}
7472

7573
bb1: {
76-
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
77-
StorageLive(_7);
78-
_7 = copy _6 as std::ptr::Alignment (Transmute);
79-
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
80-
StorageDead(_7);
74+
StorageLive(_6);
75+
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
76+
_7 = move (_6.0: std::ptr::alignment::AlignmentEnum);
8177
StorageDead(_6);
8278
StorageDead(_4);
8379
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
8480
}
8581

8682
bb2: {
83+
StorageLive(_8);
84+
_8 = copy _3 as *mut u8 (PtrToPtr);
8785
StorageLive(_9);
88-
_9 = copy _3 as *mut u8 (PtrToPtr);
89-
StorageLive(_10);
90-
_10 = discriminant(_8);
91-
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
86+
_9 = discriminant(_7);
87+
_10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable];
9288
}
9389

9490
bb3: {
95-
StorageDead(_10);
9691
StorageDead(_9);
92+
StorageDead(_8);
9793
goto -> bb4;
9894
}
9995

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _11: ();
11+
let _10: ();
1212
scope 3 {
13-
let _8: std::ptr::alignment::AlignmentEnum;
13+
let _7: std::ptr::alignment::AlignmentEnum;
1414
scope 4 {
1515
scope 12 (inlined Layout::size) {
1616
}
@@ -25,13 +25,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2525
}
2626
}
2727
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
28-
let mut _9: *mut u8;
28+
let mut _8: *mut u8;
2929
scope 19 (inlined Layout::size) {
3030
}
3131
scope 20 (inlined NonNull::<u8>::as_ptr) {
3232
}
3333
scope 21 (inlined std::alloc::dealloc) {
34-
let mut _10: usize;
34+
let mut _9: usize;
3535
scope 22 (inlined Layout::size) {
3636
}
3737
scope 23 (inlined Layout::align) {
@@ -47,10 +47,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
4747
}
4848
scope 7 (inlined Layout::for_value_raw::<[T]>) {
4949
let mut _5: usize;
50-
let mut _6: usize;
5150
scope 8 {
5251
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
53-
let mut _7: std::ptr::Alignment;
52+
let mut _6: std::ptr::Alignment;
5453
}
5554
}
5655
scope 9 (inlined size_of_val_raw::<[T]>) {
@@ -68,32 +67,29 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
6867
StorageLive(_4);
6968
_3 = copy _2 as *mut [T] (Transmute);
7069
_4 = copy _2 as *const [T] (Transmute);
71-
StorageLive(_6);
7270
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
7371
}
7472

7573
bb1: {
76-
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
77-
StorageLive(_7);
78-
_7 = copy _6 as std::ptr::Alignment (Transmute);
79-
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
80-
StorageDead(_7);
74+
StorageLive(_6);
75+
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
76+
_7 = move (_6.0: std::ptr::alignment::AlignmentEnum);
8177
StorageDead(_6);
8278
StorageDead(_4);
8379
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
8480
}
8581

8682
bb2: {
83+
StorageLive(_8);
84+
_8 = copy _3 as *mut u8 (PtrToPtr);
8785
StorageLive(_9);
88-
_9 = copy _3 as *mut u8 (PtrToPtr);
89-
StorageLive(_10);
90-
_10 = discriminant(_8);
91-
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
86+
_9 = discriminant(_7);
87+
_10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable];
9288
}
9389

9490
bb3: {
95-
StorageDead(_10);
9691
StorageDead(_9);
92+
StorageDead(_8);
9793
goto -> bb4;
9894
}
9995

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _11: ();
11+
let _10: ();
1212
scope 3 {
13-
let _8: std::ptr::alignment::AlignmentEnum;
13+
let _7: std::ptr::alignment::AlignmentEnum;
1414
scope 4 {
1515
scope 12 (inlined Layout::size) {
1616
}
@@ -25,13 +25,13 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2525
}
2626
}
2727
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
28-
let mut _9: *mut u8;
28+
let mut _8: *mut u8;
2929
scope 19 (inlined Layout::size) {
3030
}
3131
scope 20 (inlined NonNull::<u8>::as_ptr) {
3232
}
3333
scope 21 (inlined std::alloc::dealloc) {
34-
let mut _10: usize;
34+
let mut _9: usize;
3535
scope 22 (inlined Layout::size) {
3636
}
3737
scope 23 (inlined Layout::align) {
@@ -47,10 +47,9 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
4747
}
4848
scope 7 (inlined Layout::for_value_raw::<[T]>) {
4949
let mut _5: usize;
50-
let mut _6: usize;
5150
scope 8 {
5251
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
53-
let mut _7: std::ptr::Alignment;
52+
let mut _6: std::ptr::Alignment;
5453
}
5554
}
5655
scope 9 (inlined size_of_val_raw::<[T]>) {
@@ -68,32 +67,29 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
6867
StorageLive(_4);
6968
_3 = copy _2 as *mut [T] (Transmute);
7069
_4 = copy _2 as *const [T] (Transmute);
71-
StorageLive(_6);
7270
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
7371
}
7472

7573
bb1: {
76-
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
77-
StorageLive(_7);
78-
_7 = copy _6 as std::ptr::Alignment (Transmute);
79-
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
80-
StorageDead(_7);
74+
StorageLive(_6);
75+
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
76+
_7 = move (_6.0: std::ptr::alignment::AlignmentEnum);
8177
StorageDead(_6);
8278
StorageDead(_4);
8379
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
8480
}
8581

8682
bb2: {
83+
StorageLive(_8);
84+
_8 = copy _3 as *mut u8 (PtrToPtr);
8785
StorageLive(_9);
88-
_9 = copy _3 as *mut u8 (PtrToPtr);
89-
StorageLive(_10);
90-
_10 = discriminant(_8);
91-
_11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable];
86+
_9 = discriminant(_7);
87+
_10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable];
9288
}
9389

9490
bb3: {
95-
StorageDead(_10);
9691
StorageDead(_9);
92+
StorageDead(_8);
9793
goto -> bb4;
9894
}
9995

tests/mir-opt/pre-codegen/drop_boxed_slice.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ pub unsafe fn generic_in_place<T: Copy>(ptr: *mut Box<[T]>) {
99
// CHECK-LABEL: fn generic_in_place(_1: *mut Box<[T]>)
1010
// CHECK: (inlined <Box<[T]> as Drop>::drop)
1111
// CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]>
12-
// CHECK: [[ALIGN:_.+]] = const <T as std::mem::SizedTypeProperties>::ALIGN;
13-
// CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute);
14-
// CHECK: [[C:_.+]] = move ([[B]].0: std::ptr::alignment::AlignmentEnum);
12+
// CHECK: [[ALIGN:_.+]] = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
13+
// CHECK: [[C:_.+]] = move ([[ALIGN]].0: std::ptr::alignment::AlignmentEnum);
1514
// CHECK: [[D:_.+]] = discriminant([[C]]);
1615
// CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[D]]) ->
1716
std::ptr::drop_in_place(ptr)

0 commit comments

Comments
 (0)