Skip to content

Improve diagnostics for E0282 #24966

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

Merged
merged 4 commits into from
May 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,74 @@ loop. Without a loop to break out of or continue in, no sensible action can be
taken.
"##,

E0282: r##"
This error indicates that type inference did not result in one unique possible
type, and extra information is required. In most cases this can be provided
by adding a type annotation. Sometimes you need to specify a generic type
parameter manually.

A common example is the `collect` method on `Iterator`. It has a generic type
parameter with a `FromIterator` bound, which for a `char` iterator is
implemented by `Vec` and `String` among others. Consider the following snippet
that reverses the characters of a string:

```
let x = "hello".chars().rev().collect();
```

In this case, the compiler cannot infer what the type of `x` should be:
`Vec<char>` and `String` are both suitable candidates. To specify which type to
use, you can use a type annotation on `x`:

```
let x: Vec<char> = "hello".chars().rev().collect();
```

It is not necessary to annotate the full type. Once the ambiguity is resolved,
the compiler can infer the rest:

```
let x: Vec<_> = "hello".chars().rev().collect();
```

Another way to provide the compiler with enough information, is to specify the
generic type parameter:

```
let x = "hello".chars().rev().collect::<Vec<char>>();
```

Again, you need not specify the full type if the compiler can infer it:

```
let x = "hello".chars().rev().collect::<Vec<_>>();
```

Apart from a method or function with a generic type parameter, this error can
occur when a type parameter of a struct or trait cannot be inferred. In that
case it is not always possible to use a type annotation, because all candidates
have the same return type. For instance:

```
struct Foo<T> {
// Some fields omitted.
}

impl<T> Foo<T> {
fn bar() -> i32 {
0
}

fn baz() {
let number = Foo::bar();
}
}
```

This will fail because the compiler does not know which instance of `Foo` to
call `bar` on. Change `Foo::bar()` to `Foo::<T>::bar()` to resolve the error.
"##,

E0296: r##"
This error indicates that the given recursion limit could not be parsed. Ensure
that the value provided is a positive integer between quotes, like so:
Expand Down Expand Up @@ -515,7 +583,6 @@ register_diagnostics! {
E0279, // requirement is not satisfied
E0280, // requirement is not satisfied
E0281, // type implements trait but other trait is required
E0282, // unable to infer enough type information about
E0283, // cannot resolve type
E0284, // cannot resolve type
E0285, // overflow evaluation builtin bounds
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
{
span_err!(infcx.tcx.sess, obligation.cause.span, E0282,
"unable to infer enough type information about `{}`; \
type annotations required",
type annotations or generic parameter binding required",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ruud-v-a with a change like this, you need to update the test suite to reflect the change to the expected error message.

I highly recommend you do a local make check-stage1-cfail to catch these, and maybe make check-stage1-cfail-full as well ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads-up. I did run make check (on Windows), isn’t it supposed to run all tests? Anyhow, I updated the compile-fail tests and I am running the tests (on Linux) at the moment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe I misinterpreted the log files, but it certainly seemed like the compile-fail tests did need updating. If you did not see failures on a windows make check, then that is quite troubling...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pnkfelix It were definitely those tests that failed. To be sure, I ran make check on 414dfb1 on my Windows box again. There were indeed failures, I missed them the first time. I did see ... FAILED scroll by this time, but the check does not stop on failure. The last few lines of output are these:

test [run-pass] run-pass/xcrate-unit-struct.rs ... ok
test [run-pass] run-pass/zero-size-type-destructors.rs ... ok
test [run-pass] run-pass/zero_sized_subslice_match.rs ... ok

test result: ok. 2034 passed; 0 failed; 33 ignored; 0 measured

make: *** wait: No child processes.  Stop.

Last time I only checked the last line, and I assumed 0 failed meant everything was good. The summary of compile-fail turned out to be hidden 2000 lines earlier between the rest of the test output.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, okay, that is a little bit more comforting, but still a little worrisome. Maybe this is something going wrong with our return codes on Windows, causing the make to miss the fact that the run errored?

self_ty.user_string(infcx.tcx));
} else {
span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-12187-1.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -14,5 +14,5 @@ fn new<T>() -> &'static T {

fn main() {
let &v = new();
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-12187-2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -14,5 +14,5 @@ fn new<'r, T>() -> &'r T {

fn main() {
let &v = new();
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-5062.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -9,4 +9,4 @@
// except according to those terms.

fn main() { format!("{:?}", None); }
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-6458-2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -11,5 +11,5 @@
fn main() {
// Unconstrained type:
format!("{:?}", None);
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-6458-3.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -12,5 +12,5 @@ use std::mem;

fn main() {
mem::transmute(0);
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-6458-4.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -10,7 +10,7 @@

fn foo(b: bool) -> Result<bool,String> {
Err("bar".to_string());
//~^ ERROR type annotations required
//~^ ERROR type annotations or generic parameter binding required
}

fn main() {
Expand Down
5 changes: 3 additions & 2 deletions src/test/compile-fail/issue-6458.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -16,7 +16,8 @@ pub struct MyState;
pub fn foo<State>(_: TypeWithState<State>) {}

pub fn bar() {
foo(TypeWithState(marker::PhantomData)); //~ ERROR type annotations required
foo(TypeWithState(marker::PhantomData));
//~^ ERROR type annotations or generic parameter binding required
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-7813.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -10,5 +10,5 @@

fn main() {
let v = &[];
let it = v.iter(); //~ ERROR type annotations required
let it = v.iter(); //~ ERROR type annotations or generic parameter binding required
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -31,7 +31,8 @@ impl foo for Vec<isize> {

fn m1() {
// we couldn't infer the type of the vector just based on calling foo()...
let mut x = Vec::new(); //~ ERROR type annotations required
let mut x = Vec::new();
//~^ ERROR type annotations or generic parameter binding required
x.foo();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -33,7 +33,8 @@ where T : Convert<U>
}

fn a() {
test(22, std::default::Default::default()); //~ ERROR type annotations required
test(22, std::default::Default::default());
//~^ ERROR type annotations or generic parameter binding required
}

fn main() {}
4 changes: 2 additions & 2 deletions src/test/compile-fail/unconstrained-none.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -11,5 +11,5 @@
// Issue #5062

fn main() {
None; //~ ERROR type annotations required
None; //~ ERROR type annotations or generic parameter binding required
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/unconstrained-ref.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -13,5 +13,5 @@ struct S<'a, T:'a> {
}

fn main() {
S { o: &None }; //~ ERROR type annotations required
S { o: &None }; //~ ERROR type annotations or generic parameter binding required
}
5 changes: 3 additions & 2 deletions src/test/compile-fail/vector-no-ann.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -10,5 +10,6 @@


fn main() {
let _foo = Vec::new(); //~ ERROR type annotations required
let _foo = Vec::new();
//~^ ERROR type annotations or generic parameter binding required
}