Skip to content

Commit 8bb094d

Browse files
committed
Add more detail to type inference error
When encountering code where type inference fails, add more actionable information: ``` fn main() { let foo = Vec::new(); } ``` ``` error[E0282]: type annotations needed for `std::vec::Vec<_>` --> $DIR/vector-no-ann.rs:2:16 | LL | let foo = Vec::new(); | --- ^^^^^^^^ cannot infer type for `T` | | | consider giving `foo` the type `std::vec::Vec<_>` with the type parameter `T` specified ``` We still need to modify type printing to optionally accept a `TypeVariableTable` in order to properly print `std::vec::Vec<T>`. CC #25633.
1 parent 7840a0b commit 8bb094d

19 files changed

+82
-42
lines changed

src/librustc/infer/error_reporting/need_type_info.rs

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
1515
hir_map: &'a hir::map::Map<'gcx>,
1616
found_local_pattern: Option<&'gcx Pat>,
1717
found_arg_pattern: Option<&'gcx Pat>,
18+
found_ty: Option<Ty<'tcx>>,
1819
}
1920

2021
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
21-
fn node_matches_type(&mut self, hir_id: HirId) -> bool {
22+
fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
2223
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
2324
tables.borrow().node_type_opt(hir_id)
2425
});
2526
match ty_opt {
2627
Some(ty) => {
2728
let ty = self.infcx.resolve_vars_if_possible(&ty);
28-
ty.walk().any(|inner_ty| {
29+
if ty.walk().any(|inner_ty| {
2930
inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
3031
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
3132
self.infcx
@@ -35,9 +36,13 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
3536
}
3637
_ => false,
3738
}
38-
})
39+
}) {
40+
Some(ty)
41+
} else {
42+
None
43+
}
3944
}
40-
None => false,
45+
None => None,
4146
}
4247
}
4348
}
@@ -48,16 +53,21 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
4853
}
4954

5055
fn visit_local(&mut self, local: &'gcx Local) {
51-
if self.found_local_pattern.is_none() && self.node_matches_type(local.hir_id) {
56+
if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
5257
self.found_local_pattern = Some(&*local.pat);
58+
self.found_ty = Some(ty);
5359
}
5460
intravisit::walk_local(self, local);
5561
}
5662

5763
fn visit_body(&mut self, body: &'gcx Body) {
5864
for argument in &body.arguments {
59-
if self.found_arg_pattern.is_none() && self.node_matches_type(argument.hir_id) {
65+
if let (None, Some(ty)) = (
66+
self.found_arg_pattern,
67+
self.node_matches_type(argument.hir_id),
68+
) {
6069
self.found_arg_pattern = Some(&*argument.pat);
70+
self.found_ty = Some(ty);
6171
}
6272
}
6373
intravisit::walk_body(self, body);
@@ -106,13 +116,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
106116
hir_map: &self.tcx.hir(),
107117
found_local_pattern: None,
108118
found_arg_pattern: None,
119+
found_ty: None,
109120
};
110121

111122
if let Some(body_id) = body_id {
112123
let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id);
113124
local_visitor.visit_expr(expr);
114125
}
115126

127+
let ty_msg = match local_visitor.found_ty {
128+
Some(ty) if &ty.to_string() != "_" => format!(" for `{}`", ty),
129+
_ => String::new(),
130+
};
116131
if let Some(pattern) = local_visitor.found_arg_pattern {
117132
err_span = pattern.span;
118133
// We don't want to show the default label for closures.
@@ -131,13 +146,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
131146
// ^ consider giving this closure parameter a type
132147
// ```
133148
labels.clear();
134-
labels.push(
135-
(pattern.span, "consider giving this closure parameter a type".to_owned()));
149+
labels.push((pattern.span, format!(
150+
"consider giving this closure parameter {}",
151+
match local_visitor.found_ty {
152+
Some(ty) if &ty.to_string() != "_" => format!(
153+
"the type `{}` with the type parameter `{}` specified",
154+
ty,
155+
name,
156+
),
157+
_ => "a type".to_owned(),
158+
},
159+
)));
136160
} else if let Some(pattern) = local_visitor.found_local_pattern {
137161
if let Some(simple_ident) = pattern.simple_ident() {
138162
match pattern.span.compiler_desugaring_kind() {
139-
None => labels.push((pattern.span,
140-
format!("consider giving `{}` a type", simple_ident))),
163+
None => labels.push((
164+
pattern.span,
165+
format!(
166+
"consider giving `{}` {}",
167+
simple_ident,
168+
match local_visitor.found_ty {
169+
Some(ty) if &ty.to_string() != "_" => format!(
170+
"the type `{}` with the type parameter `{}` specified",
171+
ty,
172+
name,
173+
),
174+
_ => "a type".to_owned(),
175+
},
176+
),
177+
)),
141178
Some(CompilerDesugaringKind::ForLoop) => labels.push((
142179
pattern.span,
143180
"the element type for this iterator is not specified".to_owned(),
@@ -147,12 +184,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
147184
} else {
148185
labels.push((pattern.span, "consider giving the pattern a type".to_owned()));
149186
}
150-
}
187+
};
151188

152-
let mut err = struct_span_err!(self.tcx.sess,
153-
err_span,
154-
E0282,
155-
"type annotations needed");
189+
let mut err = struct_span_err!(
190+
self.tcx.sess,
191+
err_span,
192+
E0282,
193+
"type annotations needed{}",
194+
ty_msg,
195+
);
156196

157197
for (target_span, label_message) in labels {
158198
err.span_label(target_span, label_message);

src/test/ui/issues/issue-12187-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ fn new<T>() -> &'static T {
44

55
fn main() {
66
let &v = new();
7-
//~^ ERROR type annotations needed [E0282]
7+
//~^ ERROR type annotations needed
88
}

src/test/ui/issues/issue-12187-1.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `&_`
22
--> $DIR/issue-12187-1.rs:6:10
33
|
44
LL | let &v = new();

src/test/ui/issues/issue-12187-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ fn new<'r, T>() -> &'r T {
44

55
fn main() {
66
let &v = new();
7-
//~^ ERROR type annotations needed [E0282]
7+
//~^ ERROR type annotations needed
88
}

src/test/ui/issues/issue-12187-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `&_`
22
--> $DIR/issue-12187-2.rs:6:10
33
|
44
LL | let &v = new();

src/test/ui/issues/issue-17551.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `B<_>`
22
--> $DIR/issue-17551.rs:6:15
33
|
44
LL | let foo = B(marker::PhantomData);
55
| --- ^ cannot infer type for `T`
66
| |
7-
| consider giving `foo` a type
7+
| consider giving `foo` the type `B<_>` with the type parameter `T` specified
88

99
error: aborting due to previous error
1010

src/test/ui/issues/issue-20261.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `&(_,)`
22
--> $DIR/issue-20261.rs:4:11
33
|
44
LL | for (ref i,) in [].iter() {

src/test/ui/issues/issue-23046.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `Expr<'_, _>`
22
--> $DIR/issue-23046.rs:17:15
33
|
44
LL | let ex = |x| {
5-
| ^ consider giving this closure parameter a type
5+
| ^ consider giving this closure parameter the type `Expr<'_, _>` with the type parameter `VAR` specified
66

77
error: aborting due to previous error
88

src/test/ui/issues/issue-25368.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `(std::sync::mpsc::Sender<Foo<_>>, std::sync::mpsc::Receiver<Foo<_>>)`
22
--> $DIR/issue-25368.rs:11:17
33
|
44
LL | let (tx, rx) = channel();

src/test/ui/issues/issue-7813.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `&[_; 0]`
22
--> $DIR/issue-7813.rs:2:13
33
|
44
LL | let v = &[];
55
| - ^^^ cannot infer type
66
| |
7-
| consider giving `v` a type
7+
| consider giving `v` the type `&[_; 0]` with the type parameter `_` specified
88

99
error: aborting due to previous error
1010

src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl Foo for Vec<isize> {
2222
fn m1() {
2323
// we couldn't infer the type of the vector just based on calling foo()...
2424
let mut x = Vec::new();
25-
//~^ ERROR type annotations needed [E0282]
25+
//~^ ERROR type annotations needed
2626
x.foo();
2727
}
2828

src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `std::vec::Vec<_>`
22
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
33
|
44
LL | let mut x = Vec::new();
55
| ----- ^^^^^^^^ cannot infer type for `T`
66
| |
7-
| consider giving `x` a type
7+
| consider giving `x` the type `std::vec::Vec<_>` with the type parameter `T` specified
88

99
error[E0308]: mismatched types
1010
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20

src/test/ui/span/issue-42234-unknown-receiver-type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `std::option::Option<_>`
22
--> $DIR/issue-42234-unknown-receiver-type.rs:7:5
33
|
44
LL | let x: Option<_> = None;
5-
| - consider giving `x` a type
5+
| - consider giving `x` the type `std::option::Option<_>` with the type parameter `T` specified
66
LL | x.unwrap().method_that_could_exist_on_some_type();
77
| ^^^^^^^^^^ cannot infer type for `T`
88
|

src/test/ui/type/type-check/cannot_infer_local_or_array.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `[_; 0]`
22
--> $DIR/cannot_infer_local_or_array.rs:2:13
33
|
44
LL | let x = [];
55
| - ^^ cannot infer type
66
| |
7-
| consider giving `x` a type
7+
| consider giving `x` the type `[_; 0]` with the type parameter `_` specified
88

99
error: aborting due to previous error
1010

src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `std::vec::Vec<_>`
22
--> $DIR/cannot_infer_local_or_vec.rs:2:13
33
|
44
LL | let x = vec![];
55
| - ^^^^^^ cannot infer type for `T`
66
| |
7-
| consider giving `x` a type
7+
| consider giving `x` the type `std::vec::Vec<_>` with the type parameter `T` specified
88
|
99
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1010

src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `(std::vec::Vec<_>,)`
22
--> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18
33
|
44
LL | let (x, ) = (vec![], );

src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `std::option::Option<_>`
22
--> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
33
|
44
LL | let mut closure0 = None;
5-
| ------------ consider giving `closure0` a type
5+
| ------------ consider giving `closure0` the type `std::option::Option<_>` with the type parameter `_` specified
66
...
77
LL | return c();
88
| ^^^ cannot infer type

src/test/ui/vector-no-ann.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
fn main() {
22
let _foo = Vec::new();
3-
//~^ ERROR type annotations needed [E0282]
3+
//~^ ERROR type annotations needed
44
}

src/test/ui/vector-no-ann.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0282]: type annotations needed
1+
error[E0282]: type annotations needed for `std::vec::Vec<_>`
22
--> $DIR/vector-no-ann.rs:2:16
33
|
44
LL | let _foo = Vec::new();
55
| ---- ^^^^^^^^ cannot infer type for `T`
66
| |
7-
| consider giving `_foo` a type
7+
| consider giving `_foo` the type `std::vec::Vec<_>` with the type parameter `T` specified
88

99
error: aborting due to previous error
1010

0 commit comments

Comments
 (0)