1

This piece of code calls val.into() function where val is a serde_json::Value enum, but I can't find any description of into function in the Rust docs.

pub fn parse(&self, s: &str) -> Result<RpcObject, ReadError> {
    let val = serde_json::from_str::<Value>(&s)?;
    if !val.is_object() {
        Err(ReadError::NotObject)
    } else {
        Ok(val.into())
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
saga
  • 1,933
  • 2
  • 17
  • 44

1 Answers1

2

Into is a trait with the single method into. Into is implemented for every type that implements From:

impl<T, U> Into<U> for T
where
    U: From<T>, 

serde_json::Value implements many different versions of From

impl From<i8> for Value
impl From<i16> for Value
impl From<i32> for Value
impl From<i64> for Value
impl From<isize> for Value
impl From<u8> for Value
impl From<u16> for Value
impl From<u32> for Value
impl From<u64> for Value
impl From<usize> for Value
impl From<f32> for Value
impl From<f64> for Value
impl From<bool> for Value
impl From<String> for Value
impl<'a> From<&'a str> for Value
impl<'a> From<Cow<'a, str>> for Value
impl From<Map<String, Value>> for Value
impl<T: Into<Value>> From<Vec<T>> for Value
impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value

These two traits are used to provide conversions between types that cannot fail. The traits TryFrom and TryInto allow for fallible conversions starting in Rust 1.34.

See also:


An astute reader will have noticed that what I showed above actually allows you to convert to a serde_json::Value. Technically, the original code converts to a RpcObject from a Value. Somewhere in your code there is impl From<serde_json::Value> for RpcObject, but since that implementation isn't provided, I can't link to any useful documentation for that, but the pattern is the same.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • So implementing `From for V` allows me to use `val.into::()`, where `val` is a `V`. Is it true the other way round? i.e. Does implementing `Into for V` allow me to use `U::from(val)`? – saga Mar 15 '18 at 16:59
  • @saga no; that would cause infinite loops. – Shepmaster Mar 15 '18 at 17:00
  • `no; that would cause infinite loops.` Why? Isn't `val.into::()` equivalent to `U::from(val)`? – saga Mar 15 '18 at 17:01
  • Yes, there is a `From for RpcObject` in the code. The code belongs to `xi-editor`. What I don't understand is why would symmetrical behaviour of `From` and `Into` would cause an infinite loop? – saga Mar 15 '18 at 17:12
  • 1
    @saga Because there would be a blanket implementation of `From` that says "go look at `Into`" and a blanket implementation of `Into` that says "go look at `From`". There would be nowhere you could actually implement any conversion logic, and the compiler would just cycle back and forth forever trying to figure out what implementation to use. [Example](https://play.rust-lang.org/?gist=526c991b8d2eb4d7debec73f6c005ec3&version=stable). – Shepmaster Mar 15 '18 at 17:29
  • That shouldn't be very hard to resolve. The compiler should first check if there is a native implementation for conversion from one type to the other, and it should check for the other one only if that hasn't been implemented. Am I missing something here? Would it cause any other problem? – saga Mar 15 '18 at 17:36
  • @saga if you believe that you can improve the Rust compiler or language, you are certainly encouraged to do so, especially if you believe it to not be hard! Rust is [open-source](https://github.com/rust-lang/rust) and also has an [open RFC process](https://github.com/rust-lang/rfcs/). However, I don't know what you mean by "native" implementation, all implementations are the same from my point of view, modulo the orphan rules. – Shepmaster Mar 15 '18 at 17:54