Mixing const generics and generics

Hi all,

When mixing const generics and generic types for a function, it seems we have to add _ for the generic type:


use std::fmt::Debug;

fn foo1<const C: u8, const D: u8, T: Into<u16>+Debug>(a: T) {
    let m = a.into();
    println!("C={} D={} m={:?}", C, D, m);
}

fn foo2<T: Into<u16>+Debug>(a: T) {
    let m = a.into();
    println!("msg={:?}", m);
}

fn main() {
    foo1::<1,2, _>(10_u8); 

   // the compiler is able to detect the type of T
    foo2(11_u8);    
    
    // not compiling:  the compiler is not able to detect the type of T
    foo1::<1,2>(10_u8);
}

Is this being relaxed in the future to be able to not use the placeholder for the T parameter ?

Thanks for your help.

I believe this is intentional. The function has 3 generic parameters, after all, so if you set out to specify them, it would be misleading to the reader of the code to see 2 arguments when there are 3 in reality.

There are a couple ways you can make this friendlier.

  1. Use a struct to specify the const parameters
  2. Use Argument Position impl Trait (APIT) so T can never be specified in a turbofish
use std::fmt::Debug;

struct Consts<const C: u8, const D: u8>;

impl<const C: u8, const D: u8> Consts<C, D> {
    fn foo<T: Into<u16> + Debug>(a: T) {
        let m = a.into();
        println!("C={} D={} m={:?}", C, D, m);
    }
}

fn foo1<const C: u8, const D: u8, T: Into<u16> + Debug>(a: T, _: Consts<C, D>) {
    let m = a.into();
    println!("C={} D={} m={:?}", C, D, m);
}

fn foo_apit<const C: u8, const D: u8>(a: impl Into<u16> + Debug) {
    let m = a.into();
    println!("C={} D={} m={:?}", C, D, m);
}

fn main() {
    foo1(10_u8, Consts::<1, 2>);
    foo1::<1, 2, u8>(10, Consts);
    Consts::<1, 2>::foo(10_u8);

    foo_apit::<1, 2>(10_u8);
}

Using an APIT here could harm usability in some cases[1] so I personally probably wouldn't go with that.

I think the syntax of Consts::<1, 2>::foo(10_u8) is a bit nicer than foo1(10_u8, Consts::<1, 2>) but there isn't that much difference.


  1. when manually specifying the type is necessary at the call site ↩︎

@semicoleon Thanks for the hint, very clever :wink: