Improve error message for uninferrable types #38812
This commit is contained in:
parent
eb5cb9545c
commit
8579218b27
20 changed files with 97 additions and 49 deletions
|
|
@ -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<FulfillmentError<'tcx>>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -858,26 +884,42 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
|
||||
fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
|
||||
fn need_type_info(&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
ty: Ty<'tcx>) {
|
||||
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
let name = 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)
|
||||
{
|
||||
name.to_string()
|
||||
} else {
|
||||
ty.to_string()
|
||||
}
|
||||
} else {
|
||||
ty.to_string()
|
||||
let ref cause = obligation.cause;
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
cause.span,
|
||||
E0282,
|
||||
"unable to fully infer type(s)");
|
||||
|
||||
err.note("type annotations or generic parameter binding required");
|
||||
err.span_label(cause.span, &format!("cannot infer type"));
|
||||
|
||||
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(n) = pattern.simple_name() {
|
||||
err.span_label(pattern_span,
|
||||
&format!("annotating the type for the variable `{}` would help", n));
|
||||
} else {
|
||||
err.span_label(pattern_span,
|
||||
&format!("annotating the type of pattern would help"));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn new<T>() -> &'static T {
|
|||
|
||||
fn main() {
|
||||
let &v = new();
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn new<'r, T>() -> &'r T {
|
|||
|
||||
fn main() {
|
||||
let &v = new();
|
||||
//~^ ERROR unable to infer enough type information about `_` [E0282]
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ use std::marker;
|
|||
struct B<T>(marker::PhantomData<T>);
|
||||
|
||||
fn main() {
|
||||
let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information
|
||||
let foo = B(marker::PhantomData); //~ ERROR unable to fully infer type(s)
|
||||
let closure = || foo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let x; //~ ERROR unable to infer enough type information
|
||||
let x; //~ ERROR unable to fully infer type(s)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ fn main()
|
|||
fn bar(x:i32) ->i32 { 3*x };
|
||||
let b:Box<Any> = Box::new(bar as fn(_)->_);
|
||||
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
|
||||
//~| NOTE cannot infer type for `_`
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding required
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 unable to fully infer type(s)
|
||||
let_(add(x, x), |x|x)})};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 unable to fully infer type(s)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main() { format!("{:?}", None); }
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@
|
|||
fn main() {
|
||||
// Unconstrained type:
|
||||
format!("{:?}", None);
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use std::mem;
|
|||
|
||||
fn main() {
|
||||
mem::transmute(0);
|
||||
//~^ ERROR unable to infer enough type information about `U` [E0282]
|
||||
//~| NOTE cannot infer type for `U`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ pub fn foo<State>(_: TypeWithState<State>) {}
|
|||
|
||||
pub fn bar() {
|
||||
foo(TypeWithState(marker::PhantomData));
|
||||
//~^ ERROR unable to infer enough type information about `State` [E0282]
|
||||
//~| NOTE cannot infer type for `State`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
fn main() {
|
||||
let v = &[];
|
||||
let it = v.iter(); //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
let it = v.iter(); //~ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE annotating the type for the variable `it` would help
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ 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 unable to infer enough type information about `T` [E0282]
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
x.foo();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ where T : Convert<U>
|
|||
|
||||
fn a() {
|
||||
test(22, std::default::Default::default());
|
||||
//~^ ERROR unable to infer enough type information about `U` [E0282]
|
||||
//~| NOTE cannot infer type for `U`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
// Issue #5062
|
||||
|
||||
fn main() {
|
||||
None; //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
None; //~ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct S<'a, T:'a> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
S { o: &None }; //~ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
S { o: &None }; //~ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
|
||||
fn main() {
|
||||
let _foo = Vec::new();
|
||||
//~^ ERROR unable to infer enough type information about `T` [E0282]
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~^ ERROR unable to fully infer type(s) [E0282]
|
||||
//~| NOTE cannot infer type
|
||||
//~| NOTE annotating the type for the variable `_foo` would help
|
||||
//~| NOTE type annotations or generic parameter binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
error[E0282]: unable to infer enough type information about `T`
|
||||
error[E0282]: unable to fully infer type(s)
|
||||
--> $DIR/repair_span_std_macros.rs:12:13
|
||||
|
|
||||
12 | let x = vec![];
|
||||
| ^^^^^^ cannot infer type for `T`
|
||||
| - ^^^^^^ cannot infer type
|
||||
| |
|
||||
| annotating the type for the variable `x` would help
|
||||
|
|
||||
= 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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
error[E0282]: unable to infer enough type information about `X`
|
||||
error[E0282]: unable to fully infer type(s)
|
||||
--> $DIR/missing-type-parameter.rs:14:5
|
||||
|
|
||||
14 | foo();
|
||||
| ^^^ cannot infer type for `X`
|
||||
| ^^^ cannot infer type
|
||||
|
|
||||
= note: type annotations or generic parameter binding required
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue