Skip to content

Generic trait implementation not consistently recognized by the compiler #85671

@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`

Activity

steffahn

steffahn commented on May 25, 2021

@steffahn
Member

Related / coming from: This discussion on URLO.

Inparticular, changing as_ref_a to

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

and/or changing failing to

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

makes the error go away.

@rustbot label A-traits, A-associated-items, T-compiler

added
A-associated-itemsArea: Associated items (types, constants & functions)
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on May 25, 2021
added 2 commits that reference this issue on Oct 8, 2021
9d1dc71
3250240
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

      Participants

      @steffahn@aPere3@rustbot

      Issue actions

        Generic trait implementation not consistently recognized by the compiler · Issue #85671 · rust-lang/rust