Skip to content
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

E0277 error is confusing when compile fails using the last implementor for a trait #56368

Closed
ronjouch opened this issue Nov 30, 2018 · 1 comment · Fixed by #65456
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ronjouch
Copy link

ronjouch commented Nov 30, 2018

Description

This is a followup of forum post [Solved] Need help understanding compilation error with str.contains / String / Pattern.

Here's a function that compiles:

fn compiles() -> bool {
    let word = String::from("hello");
    "hello world".contains(&word)
}

But if I omit passing a reference to contains and pass the actual String:

fn wont_compile() -> bool {
    let word = String::from("hello");
    "hello world".contains(word) // <- missing "&" here before "word"
}

, then compilation fails with error

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String`        
  --> src/lib.rs:96:19                                                                          
   |                                                                                            
96 |     "hello world".contains(word)                                                           
   |                   ^^^^^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String`
   |                                                                                            
   = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`    
   = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`

In this context, as a babbling Rustacean, I had zarroo idea of what rustc was trying to tell me and, assuming the solution (which I found by looking up a .contains() example in the Rust book, where a & reference was used), my incorrect concluding puzzlement was:

  • How a String isn't a std::ops::FnMut<(char,)>, but a reference to a String is?
  • And what is a closure even doing here, where we're all talking Strings?

As pointed by forum user krdln, what's happening is that, as documented by str.contains, I should have passed a Pattern, whose 6 implementors are:

impl<'a> Pattern<'a> for char
impl<'a, 'b> Pattern<'a> for &'b str
impl<'a, 'b> Pattern<'a> for &'b String
impl<'a, 'b> Pattern<'a> for &'b [char]
impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str
impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool

, so rustc's logic behind the error message was:

"You’ve passed me something that is not a char, &str, &String, &[char] nor &&str, so it must be some other type F! If you want an F to be a pattern, it must implement FnMut!"

Proposal

When rustc fails to compile using the last (fallback? generic?) implementor for a trait,

  1. Warn that it reached the last implementor.
  2. List the missed implementors (always? If short enough? Abbreviated if too long? Only the count if too long? I don't know).

The updated, friendlier error message could look something like that:

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String`        
  --> src/lib.rs:96:19                                                                          
   |                                                                                            
96 |     "hello world".contains(word)                                                           
   |                   ^^^^^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String`
   |                                                                                            
   = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`    
// START ADDITION PROPOSAL =========================================
   = help: reached last generic implementor for `std::str::pattern::Pattern<'_>`, maybe you meant to use one of the 5 other implementors:
           char, &'b str, &'b String, &'b [char], &'c &'b str
// END ADDITION PROPOSAL   =========================================
   = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`

Note: hope the proposal makes sense, or at least you get the intention! I have no idea what I'm doing! This is my first Rust bug! I haven't even finished the Rust book! One last exclamation mark for the road!

@ronjouch ronjouch changed the title E0277 error is confusing when type error causes last implementor to be reached E0277 error is confusing when compile fails using the last implementor for a trait Nov 30, 2018
@kornelski
Copy link
Contributor

Perhaps even more directly, check whether &T satisfies the requirements, and suggest taking a reference in the error message.

That's likely to be the most common and correct solution.

@jonas-schievink jonas-schievink added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 27, 2019
@estebank estebank added D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 11, 2019
@bors bors closed this as completed in 361791b Nov 18, 2019
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 D-confusing Diagnostics: Confusing error or lint that should be reworked. 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.

4 participants