Skip to content

Generic trait implementation not consistently recognized by the compiler #85671

Closed
@aPere3

Description

@aPere3

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>, // I would like to avoid this ugly HKTB
    {
        self.as_ref_a().some_func();
        self.as_ref_a().as_ref_a();
    }
}

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

I expected to see this happen:

The line 28 of the method failing should compile, as it it calls as_ref_a to build a A(&[T]) type, which implement AsSlice for all T. When calling as_ref_a on that value, the compiler should recognize that A(&[T]) is indeed AsSlice.

Instead this happened:

The second call to as_ref_a does not recognize that A&[T] implements AsSlice, and fails to compile.

Meta

rustc --version --verbose:

rustc 1.52.1 (9bc8c42bb 2021-05-09)
binary: rustc
commit-hash: 9bc8c42bb2f19e745a63f3445f1ac248fb015e53
commit-date: 2021-05-09
host: x86_64-unknown-linux-gnu
release: 1.52.1
LLVM version: 12.0.0
Backtrace

error[E0599]: no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope
  --> src/main.rs:28:25
   |
8  | pub struct A<Cont>(Cont);
   | ------------------------- method `as_ref_a` not found for this
...
28 |         self.as_ref_a().as_ref_a();
   |                         ^^^^^^^^ method not found in `A<&[Coef]>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions