Generic trait implementation not consistently recognized by the compiler

Hello rustaceans :wave: ,

I am trying to get the following to work:

// Some trait with a function that returns a slice:
pub trait AsSlice {
    type Element;
    fn as_slice(&self) -> &[Self::Element];
}

// Some type
pub struct A<Cont>(Cont);

// Here we say that if A wraps a slice, then it implements AsSlice
impl<'a, Element> AsSlice for A<&'a [Element]> {
    type Element = Element;
    fn as_slice(&self) -> &[Self::Element] {
        self.0
    }
}

impl<Cont> A<Cont> {
    // We want this function to work
    pub fn failing<Coef>(&self)
    where
        Self: AsSlice<Element = Coef>,
    {
        // This works, meaning that A<&[<Self as AsSlice>::Element]> is recognized to be AsSlice.
        self.as_ref_a().some_func();
        // This does not, meaning that A<&[<Self as AsSlice>::Element]> is not recognized to be
        // AsSlice.
        self.as_ref_a().as_ref_a();
    }

    pub fn as_ref_a<Coef>(&self) -> A<&[<Self as AsSlice>::Element]>
    where
        Self: AsSlice<Element = Coef>,
    {
        A(self.as_slice())
    }

    pub fn some_func<Coef>(&self)
    where
        Self: AsSlice<Element = Coef>,
    {
        println!("{}", self.as_slice().len());
    }

    pub fn workaround<Coef>(&self)
        where
            Self: AsSlice<Element = Coef>,
            for<'a> A<&'a [Coef]>: AsSlice<Element = Coef>,
    {
        self.as_ref_a().some_func();
        self.as_ref_a().as_ref_a();
    }
}

fn main() {
    println!("Hello, world!");
}

The issue is the following: The failing method calls the as_ref_a method to build a A(&[T]) type. Depending on the method that is called next ( as_ref_a again, or some_func ), the A(&[T]) is recognized to implement AsSlice or not. The workaround is to use a HKTB to explicitly state that AsSlice is implemented, but I would prefer to not have it.

My first question is why does it happen? My second question is how to get rid of the HKTB?

Thanks for your help :slight_smile:

Interestingly the problem goes away, if you change the way you write the return type:

pub fn as_ref_a<Coef>(&self) -> A<&[Coef]>
1 Like

Interestingly the problem also goes away if you remove the kind-of unnecessary parameter Coef from failing

pub fn failing(&self)
    where
        Self: AsSlice,

All in all, this feels like a bug. You might want to open an issue :wink:

2 Likes

Hey @steffahn ,

Thanks for having a look !

Good catch on the fixes you found. Unfortunately, I can't reproduce the fix on the actual (richer) problem I experience (more traits and generics involved). That is interesting nonetheless !

As you proposed, I filled an issue:

I am curious to see what comes out of it !

1 Like