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

Surpress, mark, or order superflous trait resolution type errors correctly #19406

Open
Kimundi opened this issue Nov 29, 2014 · 13 comments
Open
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Kimundi
Copy link
Member

Kimundi commented Nov 29, 2014

During a rusti session on IRC, a confusing class of type errors has been discovered. This piece of code:

fn main() {
    "1 2 3".split(" ").collect::<Vec<_>>()
}

Currently emits these two error messages:

figment_sketch.rs:2:13: 2:23 error: the trait `core::str::CharEq` is not implemented for the type `&str`
figment_sketch.rs:2     "1 2 3".split(" ").collect::<Vec<_>>()
                                ^~~~~~~~~~
figment_sketch.rs:2:24: 2:43 error: type `core::str::CharSplits<'_, &str>` does not implement any method in scope named `collect`
figment_sketch.rs:2     "1 2 3".split(" ").collect::<Vec<_>>()
                                           ^~~~~~~~~~~~~~~~~~~

Where &str does not implement CharEq and split() is defined as fn split<Sep: CharEq>(&self, s: Sep) -> CharSplit<, Sep>

Both are correct type errors, however the second error is confusing because its not he actual cause, AND it depends on the other type error existing, which IS the actual cause.
Furthermore, sometimes those two errors are emitted in a different order, making it even more confusing to understand.

The basic reasoning here is "&str does not implement CharEq" and "CharSplits<'_, &str> does not Implement something that provides collect() because the only candidate, Iterator, is only implemented if &str implements CharEq". However, the split invocation only typechecks if &str implements CharEq, and hence any type error on the return type becomes irrelevant, as the type would not be valid to begin with.

If possible, typecheck should construct a dependency graph between the type errors it encounters, so that for every pair of type errors a, b it is known if b depends on a.

Using this information, the error messages could be improved in a few ways:

  1. Only emit all type errors that are not depended on other type errors (suppressing the superfluous errors)
  2. Emit all errors, but in the order of their dependencies so that the actual relevant errors are always the first ones.
  3. Emit all errors, but mark all that have any dependencies with a note like "This might be a spurious error"
@Kimundi
Copy link
Member Author

Kimundi commented Nov 29, 2014

cc @nikomatsakis

@sfackler sfackler added the A-diagnostics Area: Messages for errors, warnings, and lints label Nov 29, 2014
@nham
Copy link
Contributor

nham commented Jul 1, 2015

I'm not able to reproduce the error messages described above. In fact, the following code currently compiles on nightly:

fn main() {
    let _x = "1 2 3".split(" ").collect::<Vec<_>>();
}

@bluss
Copy link
Member

bluss commented Jul 1, 2015

Yes split(&str) is now implemented. If we try to split by a type that's not supported, the errors look a bit different:

 let v: Vec<_> = "1, 2, 3".split(b',').collect();
<anon>:2:43: 2:52 error: no method named `collect` found for type `core::str::Split<'_, u8>` in the current scope
<anon>:2     let v: Vec<_> = "1, 2, 3".split(b',').collect();
                                                   ^~~~~~~~~
<anon>:2:43: 2:52 note: the method `collect` exists but the following trait bounds were not satisfied: `u8 : core::str::pattern::Pattern<'static>`, `core::str::Split<'_, u8> : core::iter::Iterator`
<anon>:2:31: 2:42 error: the trait `core::ops::FnMut<(char,)>` is not implemented for the type `u8` [E0277]
<anon>:2     let v: Vec<_> = "1, 2, 3".split(b',').collect();
                                       ^~~~~~~~~~~
<anon>:2:31: 2:42 error: the trait `core::ops::FnOnce<(char,)>` is not implemented for the type `u8` [E0277]
<anon>:2     let v: Vec<_> = "1, 2, 3".split(b',').collect();

The new version seems a bit better, with the note!

@bluss
Copy link
Member

bluss commented Jul 1, 2015

I don't understand why the closure traits are “privileged” in that they are explicitly mentioned.

@Kimundi
Copy link
Member Author

Kimundi commented Jul 2, 2015

I'm not sure if this means that the kinds of error messages that this issue are talking about are gone now, but that new NOTE definitely improves matters for this specific kind of type error.

@steveklabnik
Copy link
Member

Triage: @bluss's example with the new format

error[E0277]: the trait bound `u8: std::ops::FnMut<(char,)>` is not satisfied
 --> <anon>:2:28
  |
2 |  let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                            ^^^^^ the trait `std::ops::FnMut<(char,)>` is not implemented for `u8`
  |
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `u8`

error[E0277]: the trait bound `u8: std::ops::FnOnce<(char,)>` is not satisfied
 --> <anon>:2:28
  |
2 |  let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                            ^^^^^ the trait `std::ops::FnOnce<(char,)>` is not implemented for `u8`
  |
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `u8`

error: no method named `collect` found for type `std::str::Split<'_, u8>` in the current scope
 --> <anon>:2:40
  |
2 |  let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                        ^^^^^^^
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied: `u8 : std::str::pattern::Pattern`, `std::str::Split<'_, u8> : std::iter::Iterator`

can this be closed?

@nikomatsakis
Copy link
Contributor

I think we can close, but I'm having a hard time understanding exactly what @Kimundi was trying to highlight in their example.

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 22, 2017
@estebank
Copy link
Contributor

estebank commented Jan 28, 2018

I believe the idea originally proposed is that only the first trait error should be emitted. In some way, the entire statement should be "poisoned" after encountering a trait bound error so that no other error is generated in that line, much like #46732 does for blocks that encounter a parse error.


For the record, the current output is shorter still:

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `u8`
 --> src/main.rs:2:32
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                ^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
  |
  = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `u8`
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `u8`

error[E0599]: no method named `collect` found for type `std::str::Split<'_, u8>` in the current scope
 --> src/main.rs:2:44
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                            ^^^^^^^
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied:
          `std::str::Split<'_, u8> : std::iter::Iterator`
          `&mut std::str::Split<'_, u8> : std::iter::Iterator`

error: aborting due to 2 previous errors

@estebank
Copy link
Contributor

I believe the ideal output would avoid emitting the E0599 which is a knock down effect of the E0277 error. That being said, I believe all we could do is always hide it (even if it would fail regardless). As things stand, I don't think we'll improve this diagnostic any time soon.

@estebank
Copy link
Contributor

Current output:

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `u8`
 --> src/main.rs:2:38
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                      ^^^^ expected an `FnMut<(char,)>` closure, found `u8`
  |
  = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `u8`
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `u8`

error[E0599]: no method named `collect` found for type `std::str::Split<'_, u8>` in the current scope
 --> src/main.rs:2:44
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                            ^^^^^^^ method not found in `std::str::Split<'_, u8>`
  |
  = note: the method `collect` exists but the following trait bounds were not satisfied:
          `&mut std::str::Split<'_, u8> : std::iter::Iterator`
          `std::str::Split<'_, u8> : std::iter::Iterator`

@estebank
Copy link
Contributor

Current output:

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `u8`
 --> src/main.rs:2:38
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                      ^^^^ expected an `FnMut<(char,)>` closure, found `u8`
  |
  = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `u8`
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `u8`

error[E0599]: no method named `collect` found for struct `std::str::Split<'_, u8>` in the current scope
   --> src/main.rs:2:44
    |
2   |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
    |                                            ^^^^^^^ method not found in `std::str::Split<'_, u8>`
    |
    = note: the method `collect` exists but the following trait bounds were not satisfied:
            `u8: std::str::pattern::Pattern<'_>`
            which is required by `std::str::Split<'_, u8>: std::iter::Iterator`
            `std::str::Split<'_, u8>: std::iter::Iterator`
            which is required by `&mut std::str::Split<'_, u8>: std::iter::Iterator`

@estebank
Copy link
Contributor

estebank commented Jun 8, 2022

Current output:

error[E0277]: expected a `FnMut<(char,)>` closure, found `u8`
 --> src/main.rs:2:38
  |
2 |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                ----- ^^^^ expected an `FnMut<(char,)>` closure, found `u8`
  |                                |
  |                                required by a bound introduced by this call
  |
  = help: the trait `FnMut<(char,)>` is not implemented for `u8`
  = help: the following other types implement trait `Pattern<'a>`:
            &'b String
            &'b [char; N]
            &'b [char]
            &'b str
            &'c &'b str
            [char; N]
            char
            pattern::MultiCharEqPattern<C>
  = note: required because of the requirements on the impl of `Pattern<'_>` for `u8`
note: required by a bound in `core::str::<impl str>::split`

error[E0599]: the method `collect` exists for struct `std::str::Split<'_, u8>`, but its trait bounds were not satisfied
 --> src/main.rs:2:44
  |
2 |        let v: Vec<_> = "1, 2, 3".split(b',').collect();
  |                                              ^^^^^^^ method cannot be called on `std::str::Split<'_, u8>` due to unsatisfied trait bounds
  |
  = note: the following trait bounds were not satisfied:
          `u8: Pattern<'_>`
          which is required by `std::str::Split<'_, u8>: Iterator`
          `std::str::Split<'_, u8>: Iterator`
          which is required by `&mut std::str::Split<'_, u8>: Iterator`

@estebank
Copy link
Contributor

Current output:

error[E0277]: the trait bound `u8: Pattern` is not satisfied
    --> src/main.rs:2:38
     |
2    |      let v: Vec<_> = "1, 2, 3".split(b',').collect();
     |                                ----- ^^^^ the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern`
     |                                |
     |                                required by a bound introduced by this call
     |
     = help: the following other types implement trait `Pattern`:
               &'b String
               &'b [char; N]
               &'b [char]
               &'b str
               &'c &'b str
               [char; N]
               char
     = note: required for `u8` to implement `Pattern`
note: required by a bound in `core::str::<impl str>::split`
    --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/str/mod.rs:1400:21
     |
1400 |     pub fn split<P: Pattern>(&self, pat: P) -> Split<'_, P> {
     |                     ^^^^^^^ required by this bound in `core::str::<impl str>::split`

error[E0599]: the method `collect` exists for struct `Split<'_, u8>`, but its trait bounds were not satisfied
   --> src/main.rs:2:44
    |
2   |        let v: Vec<_> = "1, 2, 3".split(b',').collect();
    |                                              ^^^^^^^ method cannot be called on `Split<'_, u8>` due to unsatisfied trait bounds
    |
   ::: /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/str/iter.rs:778:1
    |
778 | / generate_pattern_iterators! {
779 | |     forward:
780 | |         /// Created with the method [`split`].
781 | |         ///
...   |
793 | |     delegate double ended;
794 | | }
    | |_- doesn't satisfy `std::str::Split<'_, u8>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `u8: Pattern`
            which is required by `std::str::Split<'_, u8>: Iterator`
            `std::str::Split<'_, u8>: Iterator`
            which is required by `&mut std::str::Split<'_, u8>: Iterator`

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-enhancement Category: An issue proposing an enhancement or a PR with one. 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

8 participants