Skip to content

Commit 8579218

Browse files
committed
Improve error message for uninferrable types #38812
1 parent eb5cb95 commit 8579218

20 files changed

+96
-48
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ use util::nodemap::{FxHashMap, FxHashSet};
3939
use std::cmp;
4040
use std::fmt;
4141
use syntax::ast;
42+
use hir::{intravisit, Local, Pat};
43+
use hir::intravisit::{Visitor, NestedVisitorMap};
4244
use syntax_pos::{DUMMY_SP, Span};
4345
use errors::DiagnosticBuilder;
4446

@@ -60,6 +62,30 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
6062
}
6163
}
6264

65+
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
66+
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
67+
target_ty: &'a Ty<'tcx>,
68+
found_pattern: Option<&'a Pat>,
69+
}
70+
71+
impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
72+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
73+
NestedVisitorMap::None
74+
}
75+
76+
fn visit_local(&mut self, local: &'a Local) {
77+
if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
78+
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
79+
let is_match = ty.walk().any(|t| t == *self.target_ty);
80+
81+
if is_match && self.found_pattern.is_none() {
82+
self.found_pattern = Some(&*local.pat);
83+
}
84+
}
85+
intravisit::walk_local(self, local);
86+
}
87+
}
88+
6389
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
6490
pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
6591
for error in errors {
@@ -775,7 +801,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
775801
self.tcx.lang_items.sized_trait()
776802
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
777803
{
778-
self.need_type_info(obligation.cause.span, self_ty);
804+
self.need_type_info(obligation, self_ty);
779805
} else {
780806
let mut err = struct_span_err!(self.tcx.sess,
781807
obligation.cause.span, E0283,
@@ -793,7 +819,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
793819
// Same hacky approach as above to avoid deluging user
794820
// with error messages.
795821
if !ty.references_error() && !self.tcx.sess.has_errors() {
796-
self.need_type_info(obligation.cause.span, ty);
822+
self.need_type_info(obligation, ty);
797823
}
798824
}
799825

@@ -858,26 +884,42 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
858884
}
859885

860886

861-
fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
887+
fn need_type_info(&self,
888+
obligation: &PredicateObligation<'tcx>,
889+
ty: Ty<'tcx>) {
890+
862891
let ty = self.resolve_type_vars_if_possible(&ty);
863-
let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty {
864-
let ty_vars = self.type_variables.borrow();
865-
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
866-
*ty_vars.var_origin(ty_vid)
867-
{
868-
name.to_string()
892+
let ref cause = obligation.cause;
893+
894+
let mut err = struct_span_err!(self.tcx.sess,
895+
cause.span,
896+
E0282,
897+
"unable to fully infer type(s)");
898+
899+
err.note("type annotations or generic parameter binding required");
900+
err.span_label(cause.span, &format!("cannot infer type"));
901+
902+
let expr = self.tcx.hir.expect_expr(cause.body_id);
903+
904+
let mut local_visitor = FindLocalByTypeVisitor {
905+
infcx: &self,
906+
target_ty: &ty,
907+
found_pattern: None
908+
};
909+
910+
local_visitor.visit_expr(expr);
911+
912+
if let Some(pattern) = local_visitor.found_pattern {
913+
let pattern_span = pattern.span;
914+
if let Some(n) = pattern.simple_name() {
915+
err.span_label(pattern_span,
916+
&format!("annotating the type for the variable `{}` would help", n));
869917
} else {
870-
ty.to_string()
918+
err.span_label(pattern_span,
919+
&format!("annotating the type of pattern would help"));
871920
}
872-
} else {
873-
ty.to_string()
874-
};
921+
}
875922

876-
let mut err = struct_span_err!(self.tcx.sess, span, E0282,
877-
"unable to infer enough type information about `{}`",
878-
name);
879-
err.note("type annotations or generic parameter binding required");
880-
err.span_label(span, &format!("cannot infer type for `{}`", name));
881923
err.emit();
882924
}
883925

src/test/compile-fail/issue-12187-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn new<T>() -> &'static T {
1414

1515
fn main() {
1616
let &v = new();
17-
//~^ ERROR unable to infer enough type information about `_` [E0282]
18-
//~| NOTE cannot infer type for `_`
17+
//~^ ERROR unable to fully infer type(s) [E0282]
18+
//~| NOTE cannot infer type
1919
//~| NOTE type annotations or generic parameter binding
2020
}

src/test/compile-fail/issue-12187-2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn new<'r, T>() -> &'r T {
1414

1515
fn main() {
1616
let &v = new();
17-
//~^ ERROR unable to infer enough type information about `_` [E0282]
18-
//~| NOTE cannot infer type for `_`
17+
//~^ ERROR unable to fully infer type(s) [E0282]
18+
//~| NOTE cannot infer type
1919
//~| NOTE type annotations or generic parameter binding
2020
}

src/test/compile-fail/issue-17551.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ use std::marker;
1313
struct B<T>(marker::PhantomData<T>);
1414

1515
fn main() {
16-
let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information
16+
let foo = B(marker::PhantomData); //~ ERROR unable to fully infer type(s)
1717
let closure = || foo;
1818
}

src/test/compile-fail/issue-18159.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let x; //~ ERROR unable to infer enough type information
12+
let x; //~ ERROR unable to fully infer type(s)
1313
}

src/test/compile-fail/issue-23041.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ fn main()
1414
fn bar(x:i32) ->i32 { 3*x };
1515
let b:Box<Any> = Box::new(bar as fn(_)->_);
1616
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
17-
//~| NOTE cannot infer type for `_`
17+
//~| NOTE cannot infer type
1818
//~| NOTE type annotations or generic parameter binding required
1919
}

src/test/compile-fail/issue-23046.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
2525

2626
fn main() {
2727
let ex = |x| {
28-
let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `VAR`
28+
let_(add(x,x), |y| { //~ ERROR unable to fully infer type(s)
2929
let_(add(x, x), |x|x)})};
3030
}

src/test/compile-fail/issue-24013.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ fn main() {
1313
let a = 1;
1414
let b = 2;
1515
unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
16-
//~^ ERROR unable to infer enough type information about `_`
16+
//~^ ERROR unable to fully infer type(s)
1717
}

src/test/compile-fail/issue-5062.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
// except according to those terms.
1010

1111
fn main() { format!("{:?}", None); }
12-
//~^ ERROR unable to infer enough type information about `T` [E0282]
12+
//~^ ERROR unable to fully infer type(s) [E0282]

src/test/compile-fail/issue-6458-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
fn main() {
1212
// Unconstrained type:
1313
format!("{:?}", None);
14-
//~^ ERROR unable to infer enough type information about `T` [E0282]
14+
//~^ ERROR unable to fully infer type(s) [E0282]
1515
}

src/test/compile-fail/issue-6458-3.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::mem;
1212

1313
fn main() {
1414
mem::transmute(0);
15-
//~^ ERROR unable to infer enough type information about `U` [E0282]
16-
//~| NOTE cannot infer type for `U`
15+
//~^ ERROR unable to fully infer type(s) [E0282]
16+
//~| NOTE cannot infer type
1717
//~| NOTE type annotations or generic parameter binding
1818
}

src/test/compile-fail/issue-6458.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ pub fn foo<State>(_: TypeWithState<State>) {}
1717

1818
pub fn bar() {
1919
foo(TypeWithState(marker::PhantomData));
20-
//~^ ERROR unable to infer enough type information about `State` [E0282]
21-
//~| NOTE cannot infer type for `State`
20+
//~^ ERROR unable to fully infer type(s) [E0282]
21+
//~| NOTE cannot infer type
2222
//~| NOTE type annotations or generic parameter binding
2323
}
2424

src/test/compile-fail/issue-7813.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
fn main() {
1212
let v = &[];
13-
let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282]
14-
//~| NOTE cannot infer type for `T`
13+
let it = v.iter(); //~ ERROR unable to fully infer type(s) [E0282]
14+
//~| NOTE cannot infer type
15+
//~| NOTE annotating the type for the variable `it` would help
1516
//~| NOTE type annotations or generic parameter binding
1617
}

src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl foo for Vec<isize> {
3232
fn m1() {
3333
// we couldn't infer the type of the vector just based on calling foo()...
3434
let mut x = Vec::new();
35-
//~^ ERROR unable to infer enough type information about `T` [E0282]
35+
//~^ ERROR unable to fully infer type(s) [E0282]
3636
x.foo();
3737
}
3838

src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ where T : Convert<U>
3434

3535
fn a() {
3636
test(22, std::default::Default::default());
37-
//~^ ERROR unable to infer enough type information about `U` [E0282]
38-
//~| NOTE cannot infer type for `U`
37+
//~^ ERROR unable to fully infer type(s) [E0282]
38+
//~| NOTE cannot infer type
3939
//~| NOTE type annotations or generic parameter binding
4040
}
4141

src/test/compile-fail/unconstrained-none.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Issue #5062
1212

1313
fn main() {
14-
None; //~ ERROR unable to infer enough type information about `T` [E0282]
15-
//~| NOTE cannot infer type for `T`
14+
None; //~ ERROR unable to fully infer type(s) [E0282]
15+
//~| NOTE cannot infer type
1616
//~| NOTE type annotations or generic parameter binding
1717
}

src/test/compile-fail/unconstrained-ref.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct S<'a, T:'a> {
1313
}
1414

1515
fn main() {
16-
S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282]
17-
//~| NOTE cannot infer type for `T`
16+
S { o: &None }; //~ ERROR unable to fully infer type(s) [E0282]
17+
//~| NOTE cannot infer type
1818
//~| NOTE type annotations or generic parameter binding
1919
}

src/test/compile-fail/vector-no-ann.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
fn main() {
1313
let _foo = Vec::new();
14-
//~^ ERROR unable to infer enough type information about `T` [E0282]
15-
//~| NOTE cannot infer type for `T`
14+
//~^ ERROR unable to fully infer type(s) [E0282]
15+
//~| NOTE cannot infer type
16+
//~| NOTE annotating the type for the variable `_foo` would help
1617
//~| NOTE type annotations or generic parameter binding
1718
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error[E0282]: unable to infer enough type information about `T`
1+
error[E0282]: unable to fully infer type(s)
22
--> $DIR/repair_span_std_macros.rs:12:13
33
|
44
12 | let x = vec![];
5-
| ^^^^^^ cannot infer type for `T`
5+
| - ^^^^^^ cannot infer type
6+
| |
7+
| annotating the type for the variable `x` would help
68
|
79
= note: type annotations or generic parameter binding required
810
= note: this error originates in a macro outside of the current crate
911

1012
error: aborting due to previous error
1113

14+
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
error[E0282]: unable to infer enough type information about `X`
1+
error[E0282]: unable to fully infer type(s)
22
--> $DIR/missing-type-parameter.rs:14:5
33
|
44
14 | foo();
5-
| ^^^ cannot infer type for `X`
5+
| ^^^ cannot infer type
66
|
77
= note: type annotations or generic parameter binding required
88

99
error: aborting due to previous error
1010

11+

0 commit comments

Comments
 (0)