Why can’t I write TryFrom>?

⚓ rust    📅 2025-07-05    👤 surdeus    👁️ 1      

surdeus

I have an API that I want to call that takes C strings. I don’t want to pass in a string which contains a \0 character, and to avoid adding another case to the Result type I’m returning, I want to just protect against that at the type level, so I do something like this:

use std::ffi::OsStr;

struct SpecialStr(OsStr);

impl SpecialStr {
    unsafe fn new_unchecked(source: &OsStr) -> &Self {
        unsafe { &*(source as *const OsStr as *const SpecialStr) }
    }
}

impl<'a, S: AsRef<OsStr>> TryFrom<&'a S> for &'a SpecialStr {
    type Error = ();
    fn try_from(value: &'a S) -> Result<Self, Self::Error> {
        Ok(unsafe { SpecialStr::new_unchecked(value.as_ref()) })
    }
}

But when doing so, I get the error:

error[E0119]: conflicting implementations of trait `TryFrom<&_>` for type `&SpecialStr`
  --> src/lib.rs:18:1
   |
18 | impl<'a, S: AsRef<OsStr>> TryFrom<&'a S> for &'a SpecialStr {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T, U> TryFrom<U> for T
             where U: Into<T>;

where there is decidedly not an implementation of S.into() -> &SpecialStr for any S (or any type at all).

I’ve also tried the version where I don’t play the same stupid pointer tricks and do this instead:

struct FancyStr<'a>(&'a OsStr);

and it has the same problem.

I know I can just try being less clever, but also I really don’t understand why it seems to be giving me a diagnostic about an impl that clearly does not exist.

(At this point, I am also sorely tempted by the prospect of Just Panic When You Get A String With A Zero Byte In It because what reasonable person would do such a thing?)

Playground link

2 posts - 1 participant

Read full topic

🏷️ rust_feed