Safe visibility-aware `as` casts for `repr(transparent)` references

I find myself frequently turning forbid(unsafe_code) cryptography crates into ones with unsafe just to solve this problem, which really feels like absolutely no unsafety should be required.

Given:

#[repr(transparent)]
pub struct Outer(Inner);

I would like to be able to write:

impl Outer {
    // If visibility rules allow us to do this...
    pub fn new(inner: Inner) -> Result<Self, Error>
        assert_valid_outer(&inner)?;
        Ok(Self(inner))
    }

    // then why can't we do this as well?
    pub fn new_ref(inner: &Inner) -> Result<&Self, Error> {
        assert_valid_outer(inner)?;
        Ok(inner as &Self)
    }
}

I would like for constructor methods that have visibility on the inner fields of those repr(transparent) newtypes to be able to "promote" references to being newtype references, following the visibility rules that already exist which would otherwise be enforced if we weren't working with references.

I feel like I've asked this before on IRLO and elsewhere. I'm very much aware of the "safe transmute" working group and just talked to them about TransmuteFrom. It sounds like the reason why TransmuteFrom can't work here is it's a trait and traits aren't visibility-aware.

What it feels like is needed here is a little bit of compiler magic to decide this cast is actually safe.

This becomes pretty important when trying to implement patterns like Borrow and ToOwned, the same way something like std::path::{Path, PathBuf} would, with e.g. newtypes for [u8] and Vec<u8> where you want to enforce some kind of invariant on what contained data is considered acceptable, but still want to be able to impl Borrow and ToOwned in a way that skips the fallible invariant check because both the reference type and owned type have already run it in their respective constructors.

Is anyone aware of an open issue about this, or do I need to open one or try to work on a pre-RFC style document?

3 Likes

See some prior discussion here:

3 Likes

I think this is under the "safe transmute" initiative's purview.

Project safe transmute will eventually allow that. In the meantime you can rely on bytemuck.

1 Like

Yes I covered that:

...but please read everything in my post after that

Thanks, that's exactly what I was looking for!