Generic Inference of a slice containing a trait

Playground

I want to infer the type of a struct member this is happening in a proc_macro so I don't (easily/readily) have the type at hand. Unfortunately the compiler seems to be unable to infer the type, or is there something that I can do to convince him?

I think the issue is the compiler only sees the associated type passed as an argument to set_slice and can’t “back out” what the actual U must be - and that makes sense since multiple impls of MyTrait can have Type = MyStruct<T>.

Can you define your OtherStruct as:

pub struct OtherStruct<T: MyTrait> {
    dummy_t: Box<[T::Type]>,
}

? Or does that make it useless for you?

1 Like

That would impose extra rules on the user facing code of the proc macro which I would like to minimize. In that case I’d rather dig though the ast and annotate the type. I think the compiler is bailing a little bit too quickly, forcing the solution to become overly verbose. (Or is there an ambiguity that I have overlooked?) And not all use cases might be within a proc macro and have option b.

Well, what is the type of U: MyTrait in the code you have? The compiler sees that whatever that type is, its Type associated type is MyStruct<T>, but that's not enough to deduce what U itself is.

You can leave the definition of OtherStruct<T> as-is and change the OtherTrait impl block to put the constraint there:

impl<T: MyTrait<Type=MyStruct<T>>> OtherTrait for OtherStruct<T>
{
    fn do_sth(&self)
    {
        Self::set_slice::<T>(&self.dummy_t);
    }
}

But, similarly, I don't know if this works for you :slight_smile:.

That does not really work because the struct members are multiple different types.

I think what this boils down to is that I want to do function overloading based on the parameter type at the callsite.

Yeah, you need to find a way to specify the U: MyTrait you want to dispatch as though. The fundamental problem is all you've told the compiler is you have U::Type = MyStruct<T>, but that's not enough to know what U is. Take this contrived example:

struct Foo<T>(T);

impl<T> MyTrait for Foo<T> {
    type Type = MyStruct<T>;
    
    fn set_slice(values: &[Self::Type]) {
        println!("Foo<T> impl");
    }
}

struct Bar<T>(T);

impl<T> MyTrait for Bar<T> {
    type Type = MyStruct<T>;
    
    fn set_slice(values: &[Self::Type]) {
        println!("Bar<T> impl");
    }
}

Both types have the same Type but dispatch differently.

How about constraining the associated type to the impl type (or some wrapped derivative which will be the same wrapping for all impl)? Because that is the contract which I want to enforce.

I'm not sure I fully understood what you meant. Do you mean something like this? Note the Type associated type is dropped from MyTrait and instead Self is used in set_slice().

1 Like

Yes Indeed!!! I just figured it out myself: Playground

Thanks a lot for being my rubber duck!

1 Like