Closed
Description
Proposal
Problem statement
cc uses Arc<OsStr>
a lot (for env and flags) and we sometimes need them converted to a string.
Since these Arc
s are wrapped with lock, it can't return &str
but would have to convert them to String
.
Motivating examples or use cases
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