Hello, I’m fairly new to Rust and came across this. Can someone explain to me how the following example is able to infer the constant value from the array length passed in? At this point, inferred type generation for function calls are a bit hand wavy, to me, does anyone know of a resource that breaks down all the different ways they can be used (for instance in this example I hadn’t seen them used for consts) and what their limitations are in Rust? I often run across a ‘this type can not be inferred’ error without really knowing why not and just throw in the type to make it go away.

Any other examples people could point me to would be appreciated as well.

Thanks!

#[derive(Debug)]
struct Buffer<T, const LENGTH: usize> {
    buf: [T; LENGTH],
}

impl<T, const LENGTH: usize> From<[T; LENGTH]> for Buffer<T, LENGTH> {
    fn from(buf: [T; LENGTH]) -> Self {
        Buffer { buf }
    }
}

fn main() {
    let buf = Buffer::from([0, 1, 2, 3,5]);
    dbg!(&buf);
}

Edit: for some reason, the code markdown is hiding things inside of the <>'s (at least on my lemmy viewing client)

  • catch22OP
    link
    fedilink
    English
    arrow-up
    1
    ·
    7 days ago

    Got it, this completely made sense after your explanation and a second look. Also before I saw this example I hadn’t thought about being able to pass arrays and tuples as generic parameters types. Thanks

    • calcopiritus@lemmy.world
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      7 days ago

      Technically, this may sound pedantic. You are not passing neither arrays nor tuples as generic parameter types.

      What you are doing is passing an array to a function.

      The type of the array is [i32;5]. Every value has a type.

      By passing the array to a function, you are allowing the compiler to infer what function you are calling, since that function is generic. Using the type of the parameter you passed to it.

      You can only pass values to function parameters. And you can only pass types as generic type parameters.

      Well in this case it’s a little different, since it looks like you are passing a value (5) to a generic type parameter (LENGTH), but the const part of const LENGTH means that it’s a value generic for a type, not a type generic for a type, which is the usual thing.

      EDIT: additionally, the : usize part tells you what type exactly the const parameter for the type has to be.

      Note that you can’t have non-const values as type parameters. Since types are defined at compile time.

      EDIT 2: since type inference just fills some boilerplate for you. If we do that boilerplate manually it’s easier to see what parameters go where.

      When you do Buffer::from([0,1,2,3,4,5]) what you are really doing is: Buffer<i32, 5>::from([0,1,2,3,4,5)]. In fact, if you put that, the code will compile exactly the same. Now if you put a 6 instead, it won’t compile since the type of the buffer and the type of the array you are passing are not the same.