diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 661d47199df13..024c14ce9d922 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -39,6 +39,8 @@ use util::nodemap::{FxHashMap, FxHashSet}; use std::cmp; use std::fmt; use syntax::ast; +use hir::{intravisit, Local, Pat}; +use hir::intravisit::{Visitor, NestedVisitorMap}; use syntax_pos::{DUMMY_SP, Span}; use errors::DiagnosticBuilder; @@ -60,6 +62,30 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> { } } +struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + target_ty: &'a Ty<'tcx>, + found_pattern: Option<&'a Pat>, +} + +impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> { + NestedVisitorMap::None + } + + fn visit_local(&mut self, local: &'a Local) { + if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + let is_match = ty.walk().any(|t| t == *self.target_ty); + + if is_match && self.found_pattern.is_none() { + self.found_pattern = Some(&*local.pat); + } + } + intravisit::walk_local(self, local); + } +} + impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_fulfillment_errors(&self, errors: &Vec>) { for error in errors { @@ -775,7 +801,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.lang_items.sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - self.need_type_info(obligation.cause.span, self_ty); + self.need_type_info(obligation, self_ty); } else { let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0283, @@ -793,7 +819,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Same hacky approach as above to avoid deluging user // with error messages. if !ty.references_error() && !self.tcx.sess.has_errors() { - self.need_type_info(obligation.cause.span, ty); + self.need_type_info(obligation, ty); } } @@ -857,27 +883,53 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }) } - - fn need_type_info(&self, span: Span, ty: Ty<'tcx>) { - let ty = self.resolve_type_vars_if_possible(&ty); - let name = if let ty::TyInfer(ty::TyVar(ty_vid)) = ty.sty { + fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { + if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { let ty_vars = self.type_variables.borrow(); if let TypeVariableOrigin::TypeParameterDefinition(_, name) = - *ty_vars.var_origin(ty_vid) - { + *ty_vars.var_origin(ty_vid) { name.to_string() } else { ty.to_string() } } else { ty.to_string() + } + } + + fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) { + let ty = self.resolve_type_vars_if_possible(&ty); + let name = self.extract_type_name(&ty); + let ref cause = obligation.cause; + + let mut err = struct_span_err!(self.tcx.sess, + cause.span, + E0282, + "type annotations needed"); + + err.span_label(cause.span, &format!("cannot infer type for `{}`", name)); + + let expr = self.tcx.hir.expect_expr(cause.body_id); + + let mut local_visitor = FindLocalByTypeVisitor { + infcx: &self, + target_ty: &ty, + found_pattern: None, }; - let mut err = struct_span_err!(self.tcx.sess, span, E0282, - "unable to infer enough type information about `{}`", - name); - err.note("type annotations or generic parameter binding required"); - err.span_label(span, &format!("cannot infer type for `{}`", name)); + local_visitor.visit_expr(expr); + + if let Some(pattern) = local_visitor.found_pattern { + let pattern_span = pattern.span; + if let Some(simple_name) = pattern.simple_name() { + err.span_label(pattern_span, + &format!("consider giving `{}` a type", + simple_name)); + } else { + err.span_label(pattern_span, &format!("consider giving a type to pattern")); + } + } + err.emit(); } diff --git a/src/test/compile-fail/issue-12187-1.rs b/src/test/compile-fail/issue-12187-1.rs index 001e4b51bebc4..346fae11070e1 100644 --- a/src/test/compile-fail/issue-12187-1.rs +++ b/src/test/compile-fail/issue-12187-1.rs @@ -14,7 +14,6 @@ fn new() -> &'static T { fn main() { let &v = new(); - //~^ ERROR unable to infer enough type information about `_` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `_` - //~| NOTE type annotations or generic parameter binding } diff --git a/src/test/compile-fail/issue-12187-2.rs b/src/test/compile-fail/issue-12187-2.rs index 7cbee402b3682..848174d6fe1e0 100644 --- a/src/test/compile-fail/issue-12187-2.rs +++ b/src/test/compile-fail/issue-12187-2.rs @@ -14,7 +14,6 @@ fn new<'r, T>() -> &'r T { fn main() { let &v = new(); - //~^ ERROR unable to infer enough type information about `_` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `_` - //~| NOTE type annotations or generic parameter binding } diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs index 508442fcb9453..ecf81c8af17f6 100644 --- a/src/test/compile-fail/issue-16966.rs +++ b/src/test/compile-fail/issue-16966.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:type annotations or generic parameter binding required +// error-pattern:type annotations needed fn main() { panic!( std::default::Default::default() diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs index 5e69553d3a485..b55863f0dda7a 100644 --- a/src/test/compile-fail/issue-17551.rs +++ b/src/test/compile-fail/issue-17551.rs @@ -13,6 +13,6 @@ use std::marker; struct B(marker::PhantomData); fn main() { - let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information + let foo = B(marker::PhantomData); //~ ERROR type annotations needed let closure = || foo; } diff --git a/src/test/compile-fail/issue-18159.rs b/src/test/compile-fail/issue-18159.rs index e46bcf46cc398..8991eded3d6b8 100644 --- a/src/test/compile-fail/issue-18159.rs +++ b/src/test/compile-fail/issue-18159.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - let x; //~ ERROR unable to infer enough type information + let x; //~ ERROR type annotations needed } diff --git a/src/test/compile-fail/issue-23041.rs b/src/test/compile-fail/issue-23041.rs index 1be082ba9bbba..4dfad4ee3c385 100644 --- a/src/test/compile-fail/issue-23041.rs +++ b/src/test/compile-fail/issue-23041.rs @@ -15,5 +15,4 @@ fn main() let b:Box = Box::new(bar as fn(_)->_); b.downcast_ref::_>(); //~ ERROR E0282 //~| NOTE cannot infer type for `_` - //~| NOTE type annotations or generic parameter binding required } diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index c274665530fdb..28109747b7557 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -25,6 +25,6 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> fn main() { let ex = |x| { - let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `VAR` + let_(add(x,x), |y| { //~ ERROR type annotations needed let_(add(x, x), |x|x)})}; } diff --git a/src/test/compile-fail/issue-24013.rs b/src/test/compile-fail/issue-24013.rs index df857a2e6eb1f..a7232781f6fbc 100644 --- a/src/test/compile-fail/issue-24013.rs +++ b/src/test/compile-fail/issue-24013.rs @@ -13,5 +13,5 @@ fn main() { let a = 1; let b = 2; unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; - //~^ ERROR unable to infer enough type information about `_` + //~^ ERROR type annotations needed } diff --git a/src/test/compile-fail/issue-5062.rs b/src/test/compile-fail/issue-5062.rs index cf78d6d8c0ad4..ebfa4975d4d75 100644 --- a/src/test/compile-fail/issue-5062.rs +++ b/src/test/compile-fail/issue-5062.rs @@ -9,4 +9,4 @@ // except according to those terms. fn main() { format!("{:?}", None); } - //~^ ERROR unable to infer enough type information about `T` [E0282] + //~^ ERROR type annotations needed [E0282] diff --git a/src/test/compile-fail/issue-6458-2.rs b/src/test/compile-fail/issue-6458-2.rs index 3816896d43d1f..87cf2b3f740c1 100644 --- a/src/test/compile-fail/issue-6458-2.rs +++ b/src/test/compile-fail/issue-6458-2.rs @@ -11,5 +11,5 @@ fn main() { // Unconstrained type: format!("{:?}", None); - //~^ ERROR unable to infer enough type information about `T` [E0282] + //~^ ERROR type annotations needed [E0282] } diff --git a/src/test/compile-fail/issue-6458-3.rs b/src/test/compile-fail/issue-6458-3.rs index 8029522f5d3cc..1503da2baa73d 100644 --- a/src/test/compile-fail/issue-6458-3.rs +++ b/src/test/compile-fail/issue-6458-3.rs @@ -12,7 +12,6 @@ use std::mem; fn main() { mem::transmute(0); - //~^ ERROR unable to infer enough type information about `U` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `U` - //~| NOTE type annotations or generic parameter binding } diff --git a/src/test/compile-fail/issue-6458.rs b/src/test/compile-fail/issue-6458.rs index f8354ddbf12a5..db4d4e76c11c9 100644 --- a/src/test/compile-fail/issue-6458.rs +++ b/src/test/compile-fail/issue-6458.rs @@ -17,9 +17,8 @@ pub fn foo(_: TypeWithState) {} pub fn bar() { foo(TypeWithState(marker::PhantomData)); - //~^ ERROR unable to infer enough type information about `State` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `State` - //~| NOTE type annotations or generic parameter binding } fn main() { diff --git a/src/test/compile-fail/issue-7813.rs b/src/test/compile-fail/issue-7813.rs index e37a881642393..fdd89058fd397 100644 --- a/src/test/compile-fail/issue-7813.rs +++ b/src/test/compile-fail/issue-7813.rs @@ -10,7 +10,7 @@ fn main() { let v = &[]; - let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282] + let it = v.iter(); //~ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `T` - //~| NOTE type annotations or generic parameter binding + //~| NOTE consider giving `it` a type } diff --git a/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs index 1cf41f95a2d6d..9acf5a52166e0 100644 --- a/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs +++ b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs @@ -32,7 +32,7 @@ impl foo for Vec { fn m1() { // we couldn't infer the type of the vector just based on calling foo()... let mut x = Vec::new(); - //~^ ERROR unable to infer enough type information about `T` [E0282] + //~^ ERROR type annotations needed [E0282] x.foo(); } diff --git a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs index ed2ffa995e521..2e115431c92c4 100644 --- a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs +++ b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs @@ -34,9 +34,8 @@ where T : Convert fn a() { test(22, std::default::Default::default()); - //~^ ERROR unable to infer enough type information about `U` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `U` - //~| NOTE type annotations or generic parameter binding } fn main() {} diff --git a/src/test/compile-fail/unconstrained-none.rs b/src/test/compile-fail/unconstrained-none.rs index 88080bc70cab4..52ca91e62f8df 100644 --- a/src/test/compile-fail/unconstrained-none.rs +++ b/src/test/compile-fail/unconstrained-none.rs @@ -11,7 +11,6 @@ // Issue #5062 fn main() { - None; //~ ERROR unable to infer enough type information about `T` [E0282] + None; //~ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `T` - //~| NOTE type annotations or generic parameter binding } diff --git a/src/test/compile-fail/unconstrained-ref.rs b/src/test/compile-fail/unconstrained-ref.rs index 12278549215ed..6aaed789716a3 100644 --- a/src/test/compile-fail/unconstrained-ref.rs +++ b/src/test/compile-fail/unconstrained-ref.rs @@ -13,7 +13,6 @@ struct S<'a, T:'a> { } fn main() { - S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282] + S { o: &None }; //~ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `T` - //~| NOTE type annotations or generic parameter binding } diff --git a/src/test/compile-fail/vector-no-ann.rs b/src/test/compile-fail/vector-no-ann.rs index d559caf77a1a3..de229ded463f6 100644 --- a/src/test/compile-fail/vector-no-ann.rs +++ b/src/test/compile-fail/vector-no-ann.rs @@ -11,7 +11,7 @@ fn main() { let _foo = Vec::new(); - //~^ ERROR unable to infer enough type information about `T` [E0282] + //~^ ERROR type annotations needed [E0282] //~| NOTE cannot infer type for `T` - //~| NOTE type annotations or generic parameter binding + //~| NOTE consider giving `_foo` a type } diff --git a/src/test/ui/codemap_tests/issue-38812-2.rs b/src/test/ui/codemap_tests/issue-38812-2.rs new file mode 100644 index 0000000000000..c476657d20796 --- /dev/null +++ b/src/test/ui/codemap_tests/issue-38812-2.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let (x,) = (vec![],); +} diff --git a/src/test/ui/codemap_tests/issue-38812-2.stderr b/src/test/ui/codemap_tests/issue-38812-2.stderr new file mode 100644 index 0000000000000..156a6bdee9979 --- /dev/null +++ b/src/test/ui/codemap_tests/issue-38812-2.stderr @@ -0,0 +1,12 @@ +error[E0282]: type annotations needed + --> $DIR/issue-38812-2.rs:12:17 + | +12 | let (x,) = (vec![],); + | ---- ^^^^^^ cannot infer type for `T` + | | + | consider giving a type to pattern + | + = note: this error originates in a macro outside of the current crate + +error: aborting due to previous error + diff --git a/src/test/ui/codemap_tests/repair_span_std_macros.rs b/src/test/ui/codemap_tests/issue-38812.rs similarity index 87% rename from src/test/ui/codemap_tests/repair_span_std_macros.rs rename to src/test/ui/codemap_tests/issue-38812.rs index 3abc91d4f5ff1..a9943f753366d 100644 --- a/src/test/ui/codemap_tests/repair_span_std_macros.rs +++ b/src/test/ui/codemap_tests/issue-38812.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/ui/codemap_tests/issue-38812.stderr b/src/test/ui/codemap_tests/issue-38812.stderr new file mode 100644 index 0000000000000..6365e761453f9 --- /dev/null +++ b/src/test/ui/codemap_tests/issue-38812.stderr @@ -0,0 +1,12 @@ +error[E0282]: type annotations needed + --> $DIR/issue-38812.rs:12:13 + | +12 | let x = vec![]; + | - ^^^^^^ cannot infer type for `T` + | | + | consider giving `x` a type + | + = note: this error originates in a macro outside of the current crate + +error: aborting due to previous error + diff --git a/src/test/ui/codemap_tests/repair_span_std_macros.stderr b/src/test/ui/codemap_tests/repair_span_std_macros.stderr deleted file mode 100644 index 7e0d778a3b205..0000000000000 --- a/src/test/ui/codemap_tests/repair_span_std_macros.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0282]: unable to infer enough type information about `T` - --> $DIR/repair_span_std_macros.rs:12:13 - | -12 | let x = vec![]; - | ^^^^^^ cannot infer type for `T` - | - = note: type annotations or generic parameter binding required - = note: this error originates in a macro outside of the current crate - -error: aborting due to previous error - diff --git a/src/test/ui/missing-items/missing-type-parameter.rs b/src/test/ui/missing-items/missing-type-parameter.rs index 3671abd66246d..79368587062e8 100644 --- a/src/test/ui/missing-items/missing-type-parameter.rs +++ b/src/test/ui/missing-items/missing-type-parameter.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr index 2d007af4980b2..a16ae5538bf92 100644 --- a/src/test/ui/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -1,10 +1,8 @@ -error[E0282]: unable to infer enough type information about `X` +error[E0282]: type annotations needed --> $DIR/missing-type-parameter.rs:14:5 | 14 | foo(); | ^^^ cannot infer type for `X` - | - = note: type annotations or generic parameter binding required error: aborting due to previous error