Difficulty aggregating matches with |

2020-08-01 02:34发布

问题:

I'm trying to pack columnar data so that it can be sent to a server.

I wanted to be able to pass any suitable vector to the sending function, so I did this (brief version):

enum Column {
    Short(Vec<i16>),
    Int(Vec<i32>),
}

impl Column {
    fn as_bytes(&mut self) -> &[u8] {
        use Column::*; // weird
        match self {
            Short(vec) => unsafe { (vec.align_to::<u8>()).1 }, //why the ::?
            Int(vec) => unsafe { (vec.align_to::<u8>()).1 },
        }
    }
}

This works ok. However, if I rewrite the match with an or pipe:

impl Column {
    fn as_bytes_succinct(&mut self) -> &[u8] {
        use Column::*;

        match self {
            Short(vec) | Int(vec) => unsafe { (vec.align_to::<u8>()).1 },
        }
    }
}

I get

expected i16, found i32

How/Why is the brief writing different from the explicit one?

回答1:

Rust is a statically typed language, so every object has a known type at compile-time. Your match in the last example is equivalent to the following code:

let vec: Vec<???> = match self {
    Short(v) | Int(v) => v,
};

unsafe { vec.align_to() }.1

What type type should vec have then? Moreover, there are 2 different paths for align_to, i.e. <[i16]>::align_to and <[i32]>::align_to, which may have a different implementation with a specialization feature.



标签: rust match