diff --git a/tests/ui/codegen/equal-pointers-unequal/README.md b/tests/ui/codegen/equal-pointers-unequal/README.md new file mode 100644 index 0000000000000..343f9646a32cb --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/README.md @@ -0,0 +1,22 @@ +See https://github.com/rust-lang/rust/issues/107975 + +Basically, if you have two pointers with the same address but from two different allocations, +the compiler gets confused whether their addresses are equal or not, +resulting in some self-contradictory behavior of the compiled code. + +This folder contains some examples. +They all boil down to allocating a variable on the stack, taking its address, +getting rid of the variable, and then doing it all again. +This way we end up with two addresses stored in two `usize`s (`a` and `b`). +The addresses are (probably) equal but (definitely) come from two different allocations. +Logically, we would expect that exactly one of the following options holds true: +1. `a == b` +2. `a != b` +Sadly, the compiler does not always agree. + +Due to Rust having at least three meaningfully different ways +to get a variable's address as an `usize`, +each example is provided in three versions, each in the corresponding subfolder: +1. `./as-cast/` for `&v as *const _ as usize`, +2. `./strict-provenance/` for `addr_of!(v).addr()`, +2. `./exposed-provenance/` for `addr_of!(v).expose_provenance()`. diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs new file mode 100644 index 0000000000000..e2a00ce173d14 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs @@ -0,0 +1,21 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +fn main() { + let a: usize = { + let v = 0u8; + &v as *const _ as usize + }; + let b: usize = { + let v = 0u8; + &v as *const _ as usize + }; + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs new file mode 100644 index 0000000000000..15434de50f76c --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs @@ -0,0 +1,22 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 + +fn f() -> usize { + let v = 0; + &v as *const _ as usize +} + +fn main() { + let a = f(); + let b = f(); + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs new file mode 100644 index 0000000000000..2544923f033b6 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs @@ -0,0 +1,30 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + &v as *const _ as usize + }; + let b = { + let v = 0; + &v as *const _ as usize + }; + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); + assert_eq!(a.to_string(), b.to_string()); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.run.stdout b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.run.stdout new file mode 100644 index 0000000000000..bf061737348e5 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: false, cmp_in: false, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs new file mode 100644 index 0000000000000..5d441fd5c555a --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs @@ -0,0 +1,30 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + &v as *const _ as usize + }; + let b = { + let v = 0; + &v as *const _ as usize + }; + assert_eq!(a.to_string(), b.to_string()); + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.run.stdout b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.run.stdout new file mode 100644 index 0000000000000..581a9c6efd61d --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: true, cmp_in: true, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs new file mode 100644 index 0000000000000..6ee17ae0dffbc --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs @@ -0,0 +1,22 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +fn main() { + let a = { + let v = 0; + &v as *const _ as usize + }; + let b = { + let v = 0; + &v as *const _ as usize + }; + + println!("{}", a == b); // prints false + println!("{a}"); // or b + println!("{}", a == b); // prints true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print.run.stdout b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.run.stdout new file mode 100644 index 0000000000000..e9997f6521e95 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.run.stdout @@ -0,0 +1,3 @@ +false +<..> +true diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs new file mode 100644 index 0000000000000..1a6cea9ff5e7a --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs @@ -0,0 +1,25 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +fn main() { + let a = { + let v = 0; + &v as *const _ as usize + }; + let b = { + let v = 0; + &v as *const _ as usize + }; + + println!("{}", a == b); // false + println!("{}", a == b); // false + let c = a; + println!("{} {} {}", a == b, a == c, b == c); // false true false + println!("{a} {b}"); + println!("{} {} {}", a == b, a == c, b == c); // true true true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.run.stdout b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.run.stdout new file mode 100644 index 0000000000000..03b7976944f4b --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.run.stdout @@ -0,0 +1,5 @@ +false +false +false true false +<..> <..> +true true true diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs new file mode 100644 index 0000000000000..e462408916c2f --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs @@ -0,0 +1,35 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-fail +//@ check-run-results + +// This one should segfault. +// I don't know a better way to check for segfault other than +// check that it fails and that the output is empty. + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +use std::cell::RefCell; + +fn main() { + let a = { + let v = 0u8; + &v as *const _ as usize + }; + let b = { + let v = 0u8; + &v as *const _ as usize + }; + let i = b - a; + let arr = [ + RefCell::new(Some(Box::new(1))), + RefCell::new(None), + RefCell::new(None), + RefCell::new(None), + ]; + assert_ne!(i, 0); + let r = arr[i].borrow(); + let r = r.as_ref().unwrap(); + *arr[0].borrow_mut() = None; + println!("{}", *r); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs new file mode 100644 index 0000000000000..d1aa95a9a569d --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs @@ -0,0 +1,28 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +fn main() { + let a: usize = { + let v = 0u8; + &v as *const _ as usize + }; + let b: usize = { + let v = 0u8; + &v as *const _ as usize + }; + + // So, are `a` and `b` equal? + + // Let's check their difference. + let i: usize = a - b; + // It's not zero, which means `a` and `b` are not equal. + assert_ne!(i, 0); + // But it looks like zero... + assert_eq!(i.to_string(), "0"); + // ...and now it *is* zero? + assert_eq!(i, 0); + // So `a` and `b` are equal after all? +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs new file mode 100644 index 0000000000000..bc22a3903720c --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs @@ -0,0 +1,25 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a: usize = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + let b: usize = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs new file mode 100644 index 0000000000000..7885af145e1b7 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs @@ -0,0 +1,26 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +fn f() -> usize { + let v = 0; + addr_of!(v).expose_provenance() +} + +fn main() { + let a = f(); + let b = f(); + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs new file mode 100644 index 0000000000000..9c1ecea47b0f2 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs @@ -0,0 +1,35 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + addr_of!(v).expose_provenance() + }; + let b = { + let v = 0; + addr_of!(v).expose_provenance() + }; + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); + assert_eq!(a.to_string(), b.to_string()); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.run.stdout b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.run.stdout new file mode 100644 index 0000000000000..bf061737348e5 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: false, cmp_in: false, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs new file mode 100644 index 0000000000000..3e71869cec55d --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs @@ -0,0 +1,34 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + addr_of!(v).expose_provenance() + }; + let b = { + let v = 0; + addr_of!(v).expose_provenance() + }; + assert_eq!(a.to_string(), b.to_string()); + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.run.stdout b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.run.stdout new file mode 100644 index 0000000000000..581a9c6efd61d --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: true, cmp_in: true, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs new file mode 100644 index 0000000000000..17a754d6df4f4 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs @@ -0,0 +1,26 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a = { + let v = 0; + addr_of!(v).expose_provenance() + }; + let b = { + let v = 0; + addr_of!(v).expose_provenance() + }; + + println!("{}", a == b); // prints false + println!("{a}"); // or b + println!("{}", a == b); // prints true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.run.stdout b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.run.stdout new file mode 100644 index 0000000000000..e9997f6521e95 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.run.stdout @@ -0,0 +1,3 @@ +false +<..> +true diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs new file mode 100644 index 0000000000000..0b6c6ad47c7d7 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs @@ -0,0 +1,29 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a = { + let v = 0; + addr_of!(v).expose_provenance() + }; + let b = { + let v = 0; + addr_of!(v).expose_provenance() + }; + + println!("{}", a == b); // false + println!("{}", a == b); // false + let c = a; + println!("{} {} {}", a == b, a == c, b == c); // false true false + println!("{a} {b}"); + println!("{} {} {}", a == b, a == c, b == c); // true true true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.run.stdout b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.run.stdout new file mode 100644 index 0000000000000..03b7976944f4b --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.run.stdout @@ -0,0 +1,5 @@ +false +false +false true false +<..> <..> +true true true diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs new file mode 100644 index 0000000000000..9db23ba3339aa --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs @@ -0,0 +1,37 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-fail +//@ check-run-results + +// This one should segfault. +// I don't know a better way to check for segfault other than +// check that it fails and that the output is empty. + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +#![feature(exposed_provenance)] + +use std::{cell::RefCell, ptr::addr_of}; + +fn main() { + let a = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + let b = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + let i = b - a; + let arr = [ + RefCell::new(Some(Box::new(1))), + RefCell::new(None), + RefCell::new(None), + RefCell::new(None), + ]; + assert_ne!(i, 0); + let r = arr[i].borrow(); + let r = r.as_ref().unwrap(); + *arr[0].borrow_mut() = None; + println!("{}", *r); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs new file mode 100644 index 0000000000000..a5a975317749a --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs @@ -0,0 +1,32 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +#![feature(exposed_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a: usize = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + let b: usize = { + let v = 0u8; + addr_of!(v).expose_provenance() + }; + + // So, are `a` and `b` equal? + + // Let's check their difference. + let i: usize = a - b; + // It's not zero, which means `a` and `b` are not equal. + assert_ne!(i, 0); + // But it looks like zero... + assert_eq!(i.to_string(), "0"); + // ...and now it *is* zero? + assert_eq!(i, 0); + // So `a` and `b` are equal after all? +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs new file mode 100644 index 0000000000000..8ac998fbaffb6 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs @@ -0,0 +1,25 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a: usize = { + let v = 0u8; + addr_of!(v).addr() + }; + let b: usize = { + let v = 0u8; + addr_of!(v).addr() + }; + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs new file mode 100644 index 0000000000000..e09c73742ed58 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs @@ -0,0 +1,26 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +fn f() -> usize { + let v = 0; + addr_of!(v).addr() +} + +fn main() { + let a = f(); + let b = f(); + + // `a` and `b` are not equal. + assert_ne!(a, b); + // But they are the same number. + assert_eq!(format!("{a}"), format!("{b}")); + // And they are equal. + assert_eq!(a, b); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs new file mode 100644 index 0000000000000..cc7e68db98680 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs @@ -0,0 +1,35 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + addr_of!(v).addr() + }; + let b = { + let v = 0; + addr_of!(v).addr() + }; + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); + assert_eq!(a.to_string(), b.to_string()); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.run.stdout b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.run.stdout new file mode 100644 index 0000000000000..bf061737348e5 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: false, cmp_in: false, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs new file mode 100644 index 0000000000000..48ca543b08569 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs @@ -0,0 +1,34 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +#[inline(never)] +fn cmp(a: usize, b: usize) -> bool { + a == b +} + +#[inline(always)] +fn cmp_in(a: usize, b: usize) -> bool { + a == b +} + +fn main() { + let a = { + let v = 0; + addr_of!(v).addr() + }; + let b = { + let v = 0; + addr_of!(v).addr() + }; + assert_eq!(a.to_string(), b.to_string()); + println!("{a:?} == {b:?} -> ==: {}, cmp_in: {}, cmp: {}", a == b, cmp_in(a, b), cmp(a, b)); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.run.stdout b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.run.stdout new file mode 100644 index 0000000000000..581a9c6efd61d --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.run.stdout @@ -0,0 +1 @@ +<..> == <..> -> ==: true, cmp_in: true, cmp: true diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs new file mode 100644 index 0000000000000..72a5de72d4731 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs @@ -0,0 +1,26 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a = { + let v = 0; + addr_of!(v).addr() + }; + let b = { + let v = 0; + addr_of!(v).addr() + }; + + println!("{}", a == b); // prints false + println!("{a}"); // or b + println!("{}", a == b); // prints true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.run.stdout b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.run.stdout new file mode 100644 index 0000000000000..e9997f6521e95 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.run.stdout @@ -0,0 +1,3 @@ +false +<..> +true diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs new file mode 100644 index 0000000000000..c096e0df35739 --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs @@ -0,0 +1,29 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass +//@ check-run-results +//@ normalize-stdout-test: "\d+" -> "<..>" + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a = { + let v = 0; + addr_of!(v).addr() + }; + let b = { + let v = 0; + addr_of!(v).addr() + }; + + println!("{}", a == b); // false + println!("{}", a == b); // false + let c = a; + println!("{} {} {}", a == b, a == c, b == c); // false true false + println!("{a} {b}"); + println!("{} {} {}", a == b, a == c, b == c); // true true true +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.run.stdout b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.run.stdout new file mode 100644 index 0000000000000..03b7976944f4b --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.run.stdout @@ -0,0 +1,5 @@ +false +false +false true false +<..> <..> +true true true diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs new file mode 100644 index 0000000000000..4a997659f7afe --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs @@ -0,0 +1,37 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-fail +//@ check-run-results + +// This one should segfault. +// I don't know a better way to check for segfault other than +// check that it fails and that the output is empty. + +// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +#![feature(strict_provenance)] + +use std::{cell::RefCell, ptr::addr_of}; + +fn main() { + let a = { + let v = 0u8; + addr_of!(v).addr() + }; + let b = { + let v = 0u8; + addr_of!(v).addr() + }; + let i = b - a; + let arr = [ + RefCell::new(Some(Box::new(1))), + RefCell::new(None), + RefCell::new(None), + RefCell::new(None), + ]; + assert_ne!(i, 0); + let r = arr[i].borrow(); + let r = r.as_ref().unwrap(); + *arr[0].borrow_mut() = None; + println!("{}", *r); +} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs new file mode 100644 index 0000000000000..be2346488728a --- /dev/null +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs @@ -0,0 +1,32 @@ +//@ known-bug: #107975 +//@ compile-flags: -Copt-level=2 +//@ run-pass + +// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 + +#![feature(strict_provenance)] + +use std::ptr::addr_of; + +fn main() { + let a: usize = { + let v = 0u8; + addr_of!(v).addr() + }; + let b: usize = { + let v = 0u8; + addr_of!(v).addr() + }; + + // So, are `a` and `b` equal? + + // Let's check their difference. + let i: usize = a - b; + // It's not zero, which means `a` and `b` are not equal. + assert_ne!(i, 0); + // But it looks like zero... + assert_eq!(i.to_string(), "0"); + // ...and now it *is* zero? + assert_eq!(i, 0); + // So `a` and `b` are equal after all? +}