Skip to content

Trait bound is ignored #65149

Closed
Closed

Description

@fuchsnj

I have a simple program below that is trying to call poll_next on a T: Stream. The compiler seems to ignore the trait bound, and suggests adding the exact trait bound that is already in use.

This is using the current beta rust version:
rustc 1.39.0-beta.5 (fa5c2f3e5 2019-10-02)

pub struct StreamForwarder<T> {
    upstream: T,
}

impl<T: futures_core::stream::Stream> Stream for StreamForwarder<T> {
    type Item = ();

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.upstream.poll_next()
    }
}
error[E0599]: no method named `poll_next` found for type `T` in the current scope
  --> src/main.rs:13:23
   |
13 |         self.upstream.poll_next()
   |                       ^^^^^^^^^ method not found in `T`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll_next`, perhaps you need to restrict type parameter `T` with it:
   |
9  | impl<T: futures_core::stream::Stream + futures_core::stream::Stream> Stream for StreamForwarder<T> {
   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

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

A complete git repo reproducing the issue is here: https://github.com/fuchsnj/poll_next_bug
(remember to run rustup override set beta)

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 6, 2019
  2. nagisa commented on Oct 7, 2019

    @nagisa
    Member

    Seems like it is related entirely to the "arbitrary" self types thing. poll_next requires Pin<_> as a self, and self.upstream is not Pin. We likely never encountered this before Pin, because with & and &mut, "receivers" were autoref'd.

    MCVE:

    use std::pin::Pin;
    
    pub trait Foo {
        fn pin_recv(self: Pin<&mut Self>);
    }
    
    impl Foo for u64 {
        fn pin_recv(self: Pin<&mut u64>) {}
    }
    
    pub struct Wrapped<T> {
        num: T,
    }
    
    impl<T: Foo> Foo for Wrapped<T> {
        fn pin_recv(self: Pin<&mut Self>) {
            self.num.pin_recv()
            // correct: `Pin::new(&mut self.num).pin_recv()`
        }
    }
  3. nagisa commented on Oct 7, 2019

    @nagisa
    Member

    This also affects other stable "receivers" that are not subject to autoref, such as Rc or Arc.

    cc #56805 @mikeyhew

  4. Rantanen commented on Oct 10, 2019

    @Rantanen
    Contributor

    Another example

    trait Bounded {
        const COUNT : usize;
    }
    
    fn make_array<B : Bounded>() -> [bool; B::COUNT] {
        [false; B::COUNT]
    }

    Playground

    (Also note the formatting error in the text - rustc inserts the new bound after the current type, assuming that's where the colon is. Thus in this specific example the suggestion has invalid syntax due to the space before the colon in the code.)

  5. fenhl commented on Oct 25, 2019

    @fenhl
    Contributor

    Is there a way to work around this?

  6. sfackler commented on Oct 25, 2019

    @sfackler
    Member

    @fenhl see nagisa's comment above. poll_next must be called on Pin<&mut T>, not T.

  7. added
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    on Nov 8, 2019
  8. estebank commented on Feb 17, 2020

    @estebank
    Contributor

    Current output, we no longer provide the incorrect suggestions:

    error[E0599]: no method named `poll_next` found for type parameter `T` in the current scope
      --> src/lib.rs:14:23
       |
    14 |         self.upstream.poll_next()
       |                       ^^^^^^^^^ method not found in `T`
       |
       = help: items from traits can only be used if the type parameter is bounded by the trait
    

    This is another case of #69069.

  9. nagisa commented on Feb 18, 2020

    @nagisa
    Member

    Should we close the duplicates? And also this issue, given that we no longer suggest wrong?

  10. estebank commented on Feb 18, 2020

    @estebank
    Contributor

    Should we close the duplicates?

    Maybe, but let's make sure we link them up.

    And also this issue, given that we no longer suggest wrong?

    No, we need to improve the output when dealing with arbitrary self types. The current output is at least no longer wrong but it is misleading and actively confusing for anyone not intimately knowledgeable about the language.

  11. added 2 commits that reference this issue on Feb 27, 2020
  12. added a commit that references this issue on Feb 29, 2020
  13. SkiFire13 commented on Jun 6, 2020

    @SkiFire13
    Contributor

    @Rantanen your example gives me a different error.

    error[E0599]: no associated item named `COUNT` found for type parameter `B` in the current scope
     --> src/lib.rs:5:43
      |
    5 | fn make_array<B : Bounded>() -> [bool; B::COUNT] {
      |                                           ^^^^^ associated item not found in `B`
      |
      = help: items from traits can only be used if the type parameter is bounded by the trait
    

    This example instead:

    trait Bounded {
        const COUNT : usize;
    }
    
    fn make_array<B : Bounded>() -> [bool; <B as Bounded>::COUNT] {
        [false; B::COUNT]
    }

    gives the following error:

    error[E0277]: the trait bound `B: Bounded` is not satisfied
     --> src/lib.rs:5:40
      |
    2 |     const COUNT : usize;
      |     -------------------- required by `Bounded::COUNT`
    ...
    5 | fn make_array<B : Bounded>() -> [bool; <B as Bounded>::COUNT] {
      |                                        ^^^^^^^^^^^^^^^^^^^^^ the trait `Bounded` is not implemented for `B`
      |
    help: consider further restricting this bound
      |
    5 | fn make_array<B : Bounded + Bounded>() -> [bool; <B as Bounded>::COUNT] {
      |                           ^^^^^^^^^
    

    Playground

    Also notice that this example isn't related to arbitrary self types but gives the same wrong suggestion.

  14. estebank commented on Sep 10, 2021

    @estebank
    Contributor

    We now suggest an appropriate fix for the original report (although a few extra changes are needed to get to working code, the suggestions lead you all the way there):

    error[E0599]: no method named `pin_recv` found for type parameter `T` in the current scope
      --> src/lib.rs:17:18
       |
    4  |     fn pin_recv(self: Pin<&mut Self>);
       |        --------       -------------- the method might not be found because of this arbitrary self type
       |        |
       |        the method is available for `Pin<&mut T>` here
    ...
    17 |         self.num.pin_recv()
       |                  ^^^^^^^^ method not found in `T`
       |
    help: consider wrapping the receiver expression with the appropriate type
       |
    17 |         Pin::new(&mut self.num).pin_recv()
       |         +++++++++++++         +
    

    We no longer suggest adding a bound when it was used in a const expression:

    error: generic parameters may not be used in const operations
     --> src/lib.rs:5:40
      |
    5 | fn make_array<B : Bounded>() -> [bool; B::COUNT] {
      |                                        ^^^^^^^^ cannot perform const operation using `B`
      |
      = note: type parameters may not be used in const expressions
    
    error: constant expression depends on a generic parameter
     --> src/lib.rs:6:13
      |
    6 |     [false; B::COUNT]
      |             ^^^^^^^^
      |
      = note: this may fail depending on what value the parameter takes
    
    error: generic parameters may not be used in const operations
     --> src/lib.rs:5:41
      |
    5 | fn make_array<B : Bounded>() -> [bool; <B as Bounded>::COUNT] {
      |                                         ^ cannot perform const operation using `B`
      |
      = note: type parameters may not be used in const expressions
    
    error: constant expression depends on a generic parameter
     --> src/lib.rs:6:13
      |
    6 |     [false; B::COUNT]
      |             ^^^^^^^^
      |
      = note: this may fail depending on what value the parameter takes
    
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-diagnosticsArea: Messages for errors, warnings, and lintsA-trait-systemArea: Trait systemC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.F-arbitrary_self_types`#![feature(arbitrary_self_types)]`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