-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Iterator composition: Poor error message when Clone trait bound is missing #9082
Comments
The reason this happens is because you're iterating over While Adding the trait bound makes the method call resolve to the Updated testcase: #![allow(unused_imports)]
use std::collections::hashmap::{HashSet, SetItems};
use std::hash::Hash;
#[cfg(not(illustrate_poor_error_msg), not(illustrate_fine_error_msg))]
fn iter_to_vec<'a, 'b, X:Clone>(i: SetItems<'b, X>) -> Vec<X> {
// ^~~~~~
// missing clone is the only difference
let i = i.map(|x| x.clone());
// ^~~~~~
// Here is the call to clone
let mut i = i;
i.collect()
}
#[cfg(illustrate_poor_error_msg)]
fn iter_to_vec<'a, 'b, X >(i: SetItems<'b, X>) -> Vec<X> {
// ^~~~~~
// missing clone is the only difference
let i = i.map(|x| x.clone());
// ^~~~~~
// Here is the call to clone
let mut i = i;
i.collect()
}
#[cfg(illustrate_fine_error_msg)]
fn iter_to_vec<'a, 'b, X >(i: SetItems<'b, X>) -> Vec<X> {
// ^~~~~~
// missing clone is the only difference
let i = i.map(|x| x.enolc());
// ^~~~~~
// Here is a call to something other than clone
let mut i = i;
i.collect()
}
#[cfg(illustrate_original_poor_error_msg)]
fn set_to_vec<X:Eq+Hash >(s: &HashSet<X>) -> Vec<X> {
// ^~~~~~
// missing clone is the only difference
let i = s.iter();
let mut i = i.map(|x| x.clone());
i.collect()
}
#[cfg(not(illustrate_original_poor_error_msg))]
fn set_to_vec<X:Eq+Hash+Clone>(s: &HashSet<X>) -> Vec<X> {
// ^~~~~~
// (the aforementioned clone)
let i = s.iter();
let mut i = i.map(|x| x.clone());
i.collect()
}
fn main() {
let mut s = HashSet::new();
s.insert(1i);
s.insert(100);
s.insert(10211201);
println!("{}", set_to_vec(&s));
} |
Updated testcase: use std::collections::hash_set::Iter;
use std::collections::HashSet;
fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
let i = i.map(|x| x.clone());
i.collect()
}
fn main() {
let mut s = HashSet::new();
s.insert(1u8);
println!("{:?}", iter_to_vec(s.iter()));
} Currently gives:
Not sure it's possible to do much better than that given the current semantics of Rust. |
Triage: no change with @eefriedman 's example |
Current output, no change other than update to "new style" diagnostics:
The diagnostic should check for possible trait implementations for the current struct/enum that would be acceptable when ignoring the trait bounds, and suggest a note about this:
|
Current output, no real change:
|
From my point of view, the reason this case is confusing is because of method autoref being willing to turn the In other words, I think the spot where my mental model diverged from the compiler is along the lines of what @eddyb described here; this is different than what @estebank described later, because (if I understand correctly) in that latter case according to the compiler's internal model, the Since autoref is special magic built into the language, it might be helpful to users if diagnostics generated by the method search system also consider what method candidates would arise if you filtered out the candidates only available due to trait implementations on In other words, I suspect our method search mechanism when analyzing the call to |
Triage: no change. |
Add more context to E0599 errors Point at the intermediary unfulfilled trait bounds. Fix rust-lang#52523, fix rust-lang#61661, cc rust-lang#36513, fix rust-lang#68131, fix rust-lang#64417, fix rust-lang#61768, cc rust-lang#57457, cc rust-lang#9082, fix rust-lang#57994, cc rust-lang#64934, cc rust-lang#65149.
Add more context to E0599 errors Point at the intermediary unfulfilled trait bounds. Fix rust-lang#52523, fix rust-lang#61661, cc rust-lang#36513, fix rust-lang#68131, fix rust-lang#64417, fix rust-lang#61768, cc rust-lang#57457, cc rust-lang#9082, fix rust-lang#57994, cc rust-lang#64934, cc rust-lang#65149.
Triage: no change. I was expecting this example to trip the |
Fix direct `#[allow]` attributes in `let_unit_value` Fixes part of rust-lang#9080 Not sure why it doesn't work when the lint is emitted at the statement, but switching it to the local works fine changelog: Fix direct `#[allow]` attributes in [`let_unit_value`]
Current output: no real change with
|
Current output:
We now provide a fighting chance of realizing that the The only outstanding thing would be to suggest constraining |
Point at method chains on `E0271` errors Follow up to rust-lang#105332. Fix rust-lang#33941. CC rust-lang#9082. r? `@oli-obk`
Point at method chains on `E0271` errors Follow up to rust-lang#105332. Fix rust-lang#33941. CC rust-lang#9082. r? ``@oli-obk``
Point at method chains on `E0271` errors Follow up to rust-lang#105332. Fix rust-lang#33941. CC rust-lang#9082. r? ```@oli-obk```
Point at method chains on `E0271` errors Follow up to rust-lang#105332. Fix rust-lang#33941. CC rust-lang#9082. r? `@oli-obk`
Still missing the
|
Special case iterator chain checks for suggestion When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`. Fix rust-lang#9082.
Special case iterator chain checks for suggestion When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`. Fix rust-lang#9082.
Rollup merge of rust-lang#116717 - estebank:issue-9082, r=oli-obk Special case iterator chain checks for suggestion When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`. Fix rust-lang#9082.
I am not sure if we can do anything about this, but I thought I should at least note the problem: In the code below, there is a iterator composition (
iter().map(..).collect()
) that is going wrong because of a missingClone
trait bound.The fact that the code cannot be compiled is fine. My question is, can we make the error message better? Invocations of methods other than
clone
yield coherent error messages from rustc; why isclone
different in this case? (is this an artifact of someimpl<Bounds...> Clone for X
floating around, for appropriate substitutions for Bounds and X?)Test case:
Transcript:
The text was updated successfully, but these errors were encountered: