about summary refs log tree commit diff
diff options
context:
space:
mode:
authorwhtahy <whtahy@users.noreply.github.com>2023-04-18 19:42:48 -0400
committerwhtahy <whtahy@users.noreply.github.com>2023-04-22 00:47:07 -0400
commit2fb20985a000a8f1cd891ef484f7265a55c1612f (patch)
tree547ba84b3dc4060bea8feeaa652e7a3e082acdbb
parentadb5ded7a71911f66e20dd3a85dd39fb236c476d (diff)
downloadrust-2fb20985a000a8f1cd891ef484f7265a55c1612f.tar.gz
rust-2fb20985a000a8f1cd891ef484f7265a55c1612f.zip
add known-bug test for unsound issue 49206
-rw-r--r--tests/ui/consts/non-sync-references-in-const.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/tests/ui/consts/non-sync-references-in-const.rs b/tests/ui/consts/non-sync-references-in-const.rs
new file mode 100644
index 00000000000..0f668b8d469
--- /dev/null
+++ b/tests/ui/consts/non-sync-references-in-const.rs
@@ -0,0 +1,38 @@
+// check-pass
+// known-bug: #49206
+
+// Should fail. Compiles and prints 2 identical addresses, which shows 2 threads
+// with the same `'static` reference to non-`Sync` struct. The problem is that
+// promotion to static does not check if the type is `Sync`.
+
+#[allow(dead_code)]
+#[derive(Debug)]
+struct Foo {
+    value: u32,
+}
+
+// stable negative impl trick from https://crates.io/crates/negative-impl
+// see https://github.com/taiki-e/pin-project/issues/102#issuecomment-540472282
+// for details.
+struct Wrapper<'a, T>(::std::marker::PhantomData<&'a ()>, T);
+unsafe impl<T> Sync for Wrapper<'_, T> where T: Sync {}
+unsafe impl<'a> std::marker::Sync for Foo where Wrapper<'a, *const ()>: Sync {}
+fn _assert_sync<T: Sync>() {}
+
+fn inspect() {
+    let foo: &'static Foo = &Foo { value: 1 };
+    println!(
+        "I am in thread {:?}, address: {:p}",
+        std::thread::current().id(),
+        foo as *const Foo,
+    );
+}
+
+fn main() {
+    // _assert_sync::<Foo>(); // uncomment this line causes compile error
+    // "`*const ()` cannot be shared between threads safely"
+
+    let handle = std::thread::spawn(inspect);
+    inspect();
+    handle.join().unwrap();
+}