Skip to content

CoerceShared can violate privacy #156566

@theemathas

Description

@theemathas

The CoerceShared trait can be implemented to allow coercing from a local type to a foreign type. (Notably, the foreign crate does not need to use feature(reborrow) at all.) This allows creating an instance of that foreign type without going through public API, which can be used to violate invariants of the type.

As an example, the following code compiles and causes a null pointer dereference at run time.

dep/src/lib.rs:

use std::marker::PhantomData;

// SAFETY invariant: the pointer is valid as &'a i32
#[derive(Clone, Copy)]
pub struct MyRef<'a>((*const i32, PhantomData<&'a ()>));
// Note: This needs to be a tuple nested inside, since CoerceShared currently requires exactly 1 field

impl<'a> MyRef<'a> {
    pub fn new(r: &'a i32) -> Self {
        MyRef((r, PhantomData))
    }

    pub fn to_ref(self) -> &'a i32 {
        unsafe { &*self.0.0 }
    }
}

src/main.rs:

#![feature(reborrow)]

use std::marker::{CoerceShared, PhantomData, Reborrow};
use std::ptr;

use dep::MyRef;

#[expect(dead_code)]
struct MyMut<'a>((*const i32, PhantomData<&'a ()>));
impl Reborrow for MyMut<'_> {}
impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}

fn main() {
    let my_mut = MyMut((ptr::null(), PhantomData));
    let my_ref: MyRef<'_> = my_mut;
    println!("{}", my_ref.to_ref());
}

cc @aapoalas

Meta

rustc --version --verbose:

rustc 1.97.0-nightly (ff9a9ea07 2026-05-13)
binary: rustc
commit-hash: ff9a9ea07bdc74e9555126464b02be8ff277f521
commit-date: 2026-05-13
host: aarch64-apple-darwin
release: 1.97.0-nightly
LLVM version: 22.1.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coherenceArea: CoherenceA-visibilityArea: Visibility / privacyC-bugCategory: This is a bug.F-reborrow`#![feature(reborrow)]`; see #145612I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions