Skip to content

Static promotion allows sharing non-Sync values across threads (maybe unsound?) #142233

Closed as duplicate of#49206
@theemathas

Description

@theemathas
use std::marker::PhantomData;

// Doesn't implement Sync or Send
#[allow(dead_code)] 
struct Foo(i32, PhantomData<*mut ()>);

const X: &Foo = &Foo(123, PhantomData);

fn main() {
    let thread = std::thread::spawn(|| {
        println!("{:p}", X);
    });
    println!("{:p}", X);
    thread.join().unwrap();
}

Since Foo does not implement Sync, Rust is supposed to prevent me from getting a &Foo that points to the same place, and access it from two different threads at the same time.

However, the above code manages to obtain a &Foo in two different threads simultaneously. The code then prints the addresses of the two references. This code somehow compiles, and it prints the same address twice, demonstrating that the two references indeed point to the same address.

I suspect that this is probably unsound, because this may break invariants that external libraries rely on. (For example, a library might define a non-Sync type, and assume that if two references to this type have the same address, then they are from the same thread.) Although, I am unable to find a way to cause undefined behavior using just std, since trying to put interior mutability inside Foo causes the code to stop compiling.

@rustbot labels +I-unsound

Meta

Reproducible on the playground with 1.89.0-nightly (2025-06-08 6ccd4476036edfce364e)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions