Skip to content

Commit 2565349

Browse files
committed
Add some tests for #107975
1 parent 3bec617 commit 2565349

File tree

7 files changed

+188
-0
lines changed

7 files changed

+188
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
See https://github.com/rust-lang/rust/issues/107975
2+
3+
Basically, if you have two pointers with the same address
4+
but from two different allocations,
5+
and then you do something with their addresses as integers,
6+
the compiler may make some very strange assumptions during the compilation,
7+
resulting in some self-contradictory behavior of the compiled code.
8+
9+
This folder contains some examples.
10+
They all boil down to allocating a variable on the stack, taking its address,
11+
getting rid of the variable, and then doing it all again.
12+
This way we end up with two addresses stored in two `usize`s (`a` and `b`).
13+
The addresses are (probably) equal but (definitely) come from two different allocations.
14+
Logically, we would expect that exactly one of the following options holds true:
15+
1. `a == b`
16+
2. `a != b`
17+
Sadly, the compiler does not always agree.
18+
19+
Due to Rust having at least three meaningfully different ways
20+
to get a variable's address as an `usize`,
21+
each example is provided in three versions, each in the corresponding subfolder:
22+
1. `./as-cast/` for `&v as *const _ as usize`,
23+
2. `./strict-provenance/` for `addr_of!(v).addr()`,
24+
2. `./exposed-provenance/` for `addr_of!(v).expose_provenance()`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
fn main() {
5+
let a: usize = {
6+
let v = 0u8;
7+
&v as *const _ as usize
8+
};
9+
let b: usize = {
10+
let v = 0u8;
11+
&v as *const _ as usize
12+
};
13+
14+
// `a` and `b` are not equal.
15+
assert_ne!(a, b);
16+
// But they are the same number.
17+
assert_eq!(format!("{a}"), format!("{b}"));
18+
// But they are not equal.
19+
assert_ne!(a, b);
20+
// But they are the same hex number.
21+
assert_eq!(format!("{a:x}"), format!("{b:x}"));
22+
// But they are not equal.
23+
assert_ne!(a, b);
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
fn main() {
5+
let a: usize = {
6+
let v = 0u8;
7+
&v as *const _ as usize
8+
};
9+
let b: usize = {
10+
let v = 0u8;
11+
&v as *const _ as usize
12+
};
13+
14+
// So, are `a` and `b` equal?
15+
16+
// Let's check their difference.
17+
let i: usize = a - b;
18+
// It's not zero, which means `a` and `b` are not equal.
19+
assert_ne!(i, 0);
20+
// But it looks like zero...
21+
assert_eq!(i.to_string(), "0");
22+
// ...and now it *is* zero?
23+
assert_eq!(i, 0);
24+
// So `a` and `b` are equal after all?
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
#![feature(exposed_provenance)]
5+
6+
use std::ptr::addr_of;
7+
8+
fn main() {
9+
let a: usize = {
10+
let v = 0u8;
11+
addr_of!(v).expose_provenance()
12+
};
13+
let b: usize = {
14+
let v = 0u8;
15+
addr_of!(v).expose_provenance()
16+
};
17+
18+
// `a` and `b` are not equal.
19+
assert_ne!(a, b);
20+
// But they are the same number.
21+
assert_eq!(format!("{a}"), format!("{b}"));
22+
// But they are not equal.
23+
assert_ne!(a, b);
24+
// But they are the same hex number.
25+
assert_eq!(format!("{a:x}"), format!("{b:x}"));
26+
// But they are not equal.
27+
assert_ne!(a, b);
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
#![feature(exposed_provenance)]
5+
6+
use std::ptr::addr_of;
7+
8+
fn main() {
9+
let a: usize = {
10+
let v = 0u8;
11+
addr_of!(v).expose_provenance()
12+
};
13+
let b: usize = {
14+
let v = 0u8;
15+
addr_of!(v).expose_provenance()
16+
};
17+
18+
// So, are `a` and `b` equal?
19+
20+
// Let's check their difference.
21+
let i: usize = a - b;
22+
// It's not zero, which means `a` and `b` are not equal.
23+
assert_ne!(i, 0);
24+
// But it looks like zero...
25+
assert_eq!(i.to_string(), "0");
26+
// ...and now it *is* zero?
27+
assert_eq!(i, 0);
28+
// So `a` and `b` are equal after all?
29+
}
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
#![feature(strict_provenance)]
5+
6+
use std::ptr::addr_of;
7+
8+
fn main() {
9+
let a: usize = {
10+
let v = 0u8;
11+
addr_of!(v).addr()
12+
};
13+
let b: usize = {
14+
let v = 0u8;
15+
addr_of!(v).addr()
16+
};
17+
18+
// `a` and `b` are not equal.
19+
assert_ne!(a, b);
20+
// But they are the same number.
21+
assert_eq!(format!("{a}"), format!("{b}"));
22+
// But they are not equal.
23+
assert_ne!(a, b);
24+
// But they are the same hex number.
25+
assert_eq!(format!("{a:x}"), format!("{b:x}"));
26+
// But they are not equal.
27+
assert_ne!(a, b);
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-pass
2+
//@ known-bug: #107975
3+
4+
#![feature(strict_provenance)]
5+
6+
use std::ptr::addr_of;
7+
8+
fn main() {
9+
let a: usize = {
10+
let v = 0u8;
11+
addr_of!(v).addr()
12+
};
13+
let b: usize = {
14+
let v = 0u8;
15+
addr_of!(v).addr()
16+
};
17+
18+
// So, are `a` and `b` equal?
19+
20+
// Let's check their difference.
21+
let i: usize = a - b;
22+
// It's not zero, which means `a` and `b` are not equal.
23+
assert_ne!(i, 0);
24+
// But it looks like zero...
25+
assert_eq!(i.to_string(), "0");
26+
// ...and now it *is* zero?
27+
assert_eq!(i, 0);
28+
// So `a` and `b` are equal after all?
29+
}

0 commit comments

Comments
 (0)