Skip to content

Spurious error about Sized bound when trait needs to be imported #35976

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
alexcrichton opened this issue Aug 25, 2016 · 8 comments
Closed

Spurious error about Sized bound when trait needs to be imported #35976

alexcrichton opened this issue Aug 25, 2016 · 8 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

First reported at rust-lang/futures-rs#97

xx.rs:

use futures::*;

pub fn yy() -> BoxFuture<u32, ::std::io::Error> {
    done(Ok(1)).boxed()
}

main.rs:

extern crate futures;

mod xx;

use futures::Future;

fn main() {
    let f = xx::yy();

    println!("wait: {:?}", f.wait());
}

This code works.

If use futures::Future is commented out in main.rs, compiler complains:

src/main.rs:10:30: 10:34 error: the trait bound `futures::Future<Error=std::io::Error, Item=u32> + Send: std::marker::Sized` is not satisfied [E0277]
src/main.rs:10     println!("wait: {:?}", f.wait());
                                            ^~~~
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:10:5: 10:38 note: in this expansion of println! (defined in <std macros>)
src/main.rs:10:30: 10:34 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:10:30: 10:34 note: `futures::Future<Error=std::io::Error, Item=u32> + Send` does not have a constant size known at compile-time
error: aborting due to previous error
error: Could not compile `futures-rs-td`.

I'm not sure if is it a bug, or just a usability problem, is it in futures-rs or in rust language, but it is hard to understand error message.

rustc 1.11.0 (9b21dcd 2016-08-15), futures-rs from master

cc @stepancheg
cc @jonathandturner
cc @nikomatsakis

@luser
Copy link
Contributor

luser commented Nov 2, 2016

This is seriously confusing. I just spend 30 minutes trying to figure it out before googling and finding this.

@nikomatsakis
Copy link
Contributor

I believe what is happening is this:

  • What we want to do is invoke the trait method <Box<Future> as Future>::wait(&f) (presuming wait() is an &self method)
  • But because the trait is not imported, we don't consider the trait method, and instead look for an inherent method
    • in particular, trait object methods are considered inherent, meaning you don't have to have the trait imported to call them
    • so we wind up converting this (effectively) to <Future as Future>::wait(&*f)
    • this fails because the Self type is Future, and I imagine that wait() is defined with where Self: Sized

Given the popularity of this pattern (e.g., iterators work the same way), it's probably worth trying to tailor an error message for this case if we can.

@nikomatsakis
Copy link
Contributor

I imagine something like this:

  • if we are invoked a trait method on a trait object
    • we can check whether the trait method has a where Self: Sized message

The trick is...what do we say in this scenario? Advising to import the trait may not be a good fix, though we could look for trait impls on Box<Trait> and/or &Trait etc and only give the message in that case.

@luser
Copy link
Contributor

luser commented Nov 3, 2016

Giving the existing "import the trait" error would at least be an improvement.

@Mark-Simulacrum
Copy link
Member

Marking as a diagnostics issue. cc @rust-lang/compiler, perhaps we could prioritize this? It's possible that even small wins ("import the trait") here would be very good. Even just almost always doing this might be a lot better if given with the right wording.

@Mark-Simulacrum Mark-Simulacrum added A-diagnostics Area: Messages for errors, warnings, and lints I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 15, 2017
@nikomatsakis
Copy link
Contributor

OK, so, the challenge here is that method resolution succeeds. I am a bit torn. Perhaps the easiest (and maybe even best) way to solve this is to modify method resolution itself to check for this particular case. That is, when method resolution succeeds, if this is a trait method, we could quickly scan the where-clauses for the method, looking specifically for Self: Sized. If we find it, we can remove it from the list and issue a customized error. I think this is how I would go about it.

I'm out of time this morning for writing detailed mentoring instructions, but let me give a few pointers. I'm happy to elaborate further in the future. The method searching code is found in this module. It works in two phases: the first phase, probing, finds which method applies. That doesn't have to change here, I think.

The second phase, confirmation, does a bit of further work. Here is the implementation of the confirm_method() function. As part of its work, it invokes add_obligations(), which is what records the where clauses (later on, we will check that they are satisfied).

So basically my proposal is to interject there and detect this particular case and issue a custom error.

@nikomatsakis
Copy link
Contributor

triage: P-medium

@trishume
Copy link

@raphlinus and I ran into this bug this morning when using and_then on a BoxFuture without importing the trait. It took us 10+ minutes working together and replicating a skeleton of our code in play.rust-lang.org and looking for differences before we figured it out.

I think @nikomatsakis's solution would have worked well for us. If it detects you trying to call a trait method with a Self: Sized bound it could jump up a deref-level and use the same logic that failed method resolution normally uses to suggest traits applicable to Box<Future> you might want to import, which would find that futures::Future has an and_then method.

scalexm added a commit to scalexm/rust that referenced this issue Aug 3, 2017
When trying to perform static dispatch on something which derefs
to a trait object, and the target trait is not in scope, we had
confusing error messages if the target method had a
`Self: Sized` bound. We add a more precise error message in this
case: "consider using trait ...".

Fixes rust-lang#35976.
bors added a commit that referenced this issue Aug 4, 2017
Add a more precise error message for issue #35976

When trying to perform static dispatch on something which derefs to a trait object, and the target trait is not in scope, we had confusing error messages if the target method had a `Self: Sized` bound. We add a more precise error message in this case: "consider using trait ...".

Fixes #35976.

r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants