Skip to content

Generic trait implementation not consistently recognized by the compiler #85671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
aPere3 opened this issue May 25, 2021 · 1 comment · Fixed by #86506
Closed

Generic trait implementation not consistently recognized by the compiler #85671

aPere3 opened this issue May 25, 2021 · 1 comment · Fixed by #86506
Labels
A-associated-items Area: Associated items (types, constants & functions) A-trait-system Area: Trait system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@aPere3
Copy link

aPere3 commented May 25, 2021

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`

@aPere3 aPere3 added the C-bug Category: This is a bug. label May 25, 2021
@steffahn
Copy link
Member

steffahn commented May 25, 2021

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

@rustbot rustbot added A-associated-items Area: Associated items (types, constants & functions) A-trait-system Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 25, 2021
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Oct 8, 2021
…, r=jackh726

Don't normalize xform_ret_ty during method candidate assembly

Fixes rust-lang#85671

Normalizing the return type of a method candidate together with the expected receiver type of the method can lead to valid method candidates being rejected during probing. Specifically in the example of the fixed issue we have a `self_ty` of the form `&A<&[Coef]>` whereas the `impl_ty` of the method would be `&A<_>`, if we normalize the projection in the return type we unify the inference variable with `Cont`, which will lead us to reject the candidate in the sup type check in `consider_probe`. Since we don't actually need the normalized return type during candidate assembly, we postpone the normalization until we consider candidates in `consider_probe`.
@bors bors closed this as completed in 3250240 Oct 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-trait-system Area: Trait system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants