Skip to content

New failable API for SmartPointer<OsStr> to SmartPointer<str>, etc #399

Closed
@NobodyXu

Description

@NobodyXu

Proposal

Problem statement

cc uses Arc<OsStr> a lot (for env and flags) and we sometimes need them converted to a string.

Since these Arcs are wrapped with lock, it can't return &str but would have to convert them to String.

Motivating examples or use cases

https://github.com/rust-lang/cc-rs/blob/6fa9ea631509f0dc2f6373121e2ec9db4e5f8001/src/lib.rs#L3558

while we can always convert it to String it is less efficient and less ergonomic over an API to convert Arc<OsStr> to Arc<str> in a faillable way.

Solution sketch

impl TryFrom<Arc<OsStr>> for Arc<str> {
    type Err = Utf8Error;
    fn try_from(os_str: Arc<OsStr>) -> Self;
}
impl TryFrom<Rc<OsStr>> for Rc<str> {
    type Err = Utf8Error;
    fn try_from(os_str: Rc<OsStr>) -> Self;
}
impl TryFrom<Box<OsStr>> for Box<str> {
    type Err = Utf8Error;
    fn try_from(os_str: Box<OsStr>) -> Self;
}

impl From<Arc<OsStr>> for Arc<Path> {}
impl From<Rc<OsStr>> for Rc<Path> {}
impl From<Box<OsStr>> for Box<Path> {}

impl From<Arc<str>> for Arc<OsStr> {}
impl From<Rc<str>> for Rc<OsStr> {}
impl From<Box<str>> for Box<OsStr> {}

impl From<Arc<Path>> for Arc<OsStr> {}
impl From<Rc<Path>> for Rc<OsStr> {}
impl From<Box<Path>> for Box<OsStr> {}

Alternatives

While the proposed API would fix it for smart pointers in stdlib, it won't work for custom smart pointers.

And adding such APIs to every string type is annoying and it doesn't scale, makes it harder to write custom smart pointers.

Perhaps rust should consider introduce a trait for smart pointers to make such conversion trivial:

trait SafeCastable<T>
where
    T: ?Sized,
    layout(T) == layout(Self),
{
   fn cast(self) -> T;
}

impl<T, U> SafeCastable<U> for T
where
    T: AsRef<U> + ?Sized,
    U: ?Sized,
    layout(T) == layout(U),
{...}

impl<T, U> SafeCastable<U> for T
where
    T: Into<U> + ?Sized,
    U: ?Sized,
    layout(T) == layout(U),
{...}

trait SafeTryCastable<T>
where
    T: ?Sized,
    layout(T) == layout(U),
{
   type R: Try<T>;
   fn cast(self) -> R;
}

impl<T, U> SafeTryCastable<U> for T
where
    T: TryInto<U> + ?Sized,
    U: ?Sized,
    layout(T) == layout(U),
{...}

trait CastableSmartPtr {
    type Item: ?Sized;
    type SmartPtr<T: ?Sized>;

    unsafe fn cast_unchecked<T>(self) -> Self::SmartPtr<T>
    where
        T: ?Sized,
        layout(T) == layout(Self::Item); // either need const generics or compiler-generated auto-imlemented traits

    // provided methods
    fn cast<T>(self) -> Self::SmartPtr<T>
    where
        T: ?Sized,
        Self::Item: SafeCastable<T>,
    {...}

    fn try_cast<T>(self) -> Try<Self::SmartPtr<T>, <Self::Item as SafeTryCastable<T>>::R::Residual>
    where
        T: ?Sized,
        Self::Item: SafeTryCastable<T>,
    {...}
}

Related: rust-lang/rust#44874

Metadata

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)I-libs-api-nominatedIndicates that an issue has been nominated for discussion during a team meeting.T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions