1

One can write something like the following, in which an associated type is populated by a concrete implementation that then uses that associated type within a method:

use num;
use std::marker::PhantomData;

trait MyTrait {
    type Type: num::Unsigned;

    fn do_something(val: <Self as MyTrait>::Type) -> <Self as MyTrait>::Type;
}

struct U32Type {}

impl MyTrait for U32Type {
    type Type = u32;

    fn do_something(val: <Self as MyTrait>::Type) -> <Self as MyTrait>::Type {
        val & (10 as Self::Type)
    }
}

struct MyStruct <T>
where T: MyTrait
{
    marker_t: PhantomData<T>,
}

impl <T> MyStruct <T>
where T: MyTrait
{
    fn foo(val: T::Type) -> T::Type{
        T::do_something(val)
    }
}

fn main() {

    let a: u32 = MyStruct::<U32Type>::foo(10u32);
    println!("Value {}", a);
}

Looking at the above, it seems to me that U32Type.do_something() does not specify anything that is not directly inferable from the type system. As such, I would have thought I could specify a default implementation on the trait itself. The following is an attempt to do that (with the additional trait bounds I would have thought necessary for the generic case):

use num;
use std::ops::BitAnd;
use std::marker::PhantomData;

trait MyTrait {
    type Type: num::Unsigned + BitAnd;

    fn do_something(val: <Self as MyTrait>::Type) -> <Self as MyTrait>::Type {
        val & (10 as <Self as MyTrait>::Type)
    }

}

struct U32Type {}

impl MyTrait for U32Type {
    type Type = u32;
}

struct MyStruct <T>
where T: MyTrait
{
    marker_t: PhantomData<T>,
}

impl <T> MyStruct <T>
where T: MyTrait
{
    fn foo(val: T::Type) -> T::Type{
        T::do_something(val)
    }
}

fn main() {

    let a: u32 = MyStruct::<U32Type>::foo(10u32);
    println!("Value {}", a);
}

Unfortunately, this does not work - the compiler fails with the complaint that the output of do_something is of type <<Self as MyTrait>::Type as std::ops::BitAnd>::Output as well as about the non-primitive cast within do_something.

Is this something that is possible with some correct set of trait bounds (say), or is it something that one cannot do? If the latter, can anybody clarify what the problem is?

Henry Gomersall
  • 8,434
  • 3
  • 31
  • 54
  • I think your question is answered by [How do I use integer number literals when using generic types?](https://stackoverflow.com/q/28565440/3650362) (addresses the non-primitive cast) and [How do I specify the expected result of a `std::ops::Mul` in a trait bound?](https://stackoverflow.com/q/49973888/3650362) (addresses how to bound an associated type). – trent Feb 13 '20 at 17:33
  • [Here's one way to apply those answers to your problem.](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=30c1d276ce309d271b5352f33a17000e). – trent Feb 13 '20 at 17:33
  • Ah nice, I'll have a play! Thanks :) – Henry Gomersall Feb 13 '20 at 17:56
  • @edwardw partly, but trentcl also solved the other part on the bitand output bound. – Henry Gomersall Feb 13 '20 at 21:09
  • The idea that just because someone has answered a question that is can be presented in the same way as mine means mine should be closed rather misses the fact that different presentations of the same problem are valuable. Clearly I failed to find the solution from existing solutions. Perhaps having different questions with suitable references adds value to SO. – Henry Gomersall Feb 13 '20 at 21:14
  • 1
    Questions closed as duplicates don't get deleted (unless the author deletes it themselves). They serve exactly the purpose you suggest: some people may end up on this question because it better fits their search terms, but it's better to have answers centralized in one question, so that if the answers need to change (e.g. because the language has evolved), then we don't have to fix answers in many questions. – Francis Gagné Feb 14 '20 at 01:49
  • @HenryGomersall what's up? Why @ me? I don't remember saying anything in this thread. – edwardw Feb 14 '20 at 07:44
  • @edwardw now I'm just super confused! Please ignore me :) – Henry Gomersall Feb 14 '20 at 10:56
  • @FrancisGagné You're quite right - I apologise to the community. – Henry Gomersall Feb 14 '20 at 10:57

0 Answers0