Why a string can be "into"ed to a complicated object?

In the lib document, I am curious why a string has an "into" method to into the "Element" object since the string is in std lib, how can the authors know there is an Element object that can be "into"ed?

That is because the Element implements From<&str>. The Into implementation comes from the stdlib here:

// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T, U> const Into<U> for T
where
    U: ~const From<T>,
{
    /// Calls `U::from(self)`.
    ///
    /// That is, this conversion is whatever the implementation of
    /// <code>[From]&lt;T&gt; for U</code> chooses to do.
    fn into(self) -> U {
        U::from(self)
    }
}

Generally, the idiomatic way to implement Into is to implement From on the other type.


Further note that it is possible to implement a trait for a foreign type, depending on orphan rules. I.e. you can implement From<MyType> for ForeignType if MyType is defined in your crate.


Example:

pub struct Name(String);

// allowed because `Name` is a local type
impl From<String> for Name {
    fn from(inner: String) -> Name {
        Name(inner)
    }
}

// allowed due to orphan rules because `Name` is a local type
impl From<Name> for String {
    fn from(name: Name) -> String {
        name.0
    }
}

fn main() {
    let a: String = "Rusty".to_string();
    let b: Name = a.into();
    let c: String = b.into();
    assert_eq!(c, "Rusty".to_string());
}

(Playground)

Both From implementations (and the corresponding Into implementations added by std) could be used outside the crate.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.