diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-10-29 16:49:01 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-12-10 12:02:18 -0800 |
| commit | 12af2561e9936add8fab4b96ff206b00a5877efe (patch) | |
| tree | b5b5410af50110a0231f489451b3611ab6adf644 /src | |
| parent | 7dbfb0a8ca4ab74ee3111e57a024f9e6257ce37c (diff) | |
| download | rust-12af2561e9936add8fab4b96ff206b00a5877efe.tar.gz rust-12af2561e9936add8fab4b96ff206b00a5877efe.zip | |
Point at method call when type annotations are needed
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/infer/error_reporting/need_type_info.rs | 59 | ||||
| -rw-r--r-- | src/librustc/traits/error_reporting.rs | 26 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/writeback.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/associated-types/associated-types-overridden-binding.stderr | 17 | ||||
| -rw-r--r-- | src/test/ui/associated-types/associated-types-unconstrained.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-12028.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-65611.stderr | 5 | ||||
| -rw-r--r-- | src/test/ui/question-mark-type-infer.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/question-mark-type-infer.stderr | 11 | ||||
| -rw-r--r-- | src/test/ui/span/issue-42234-unknown-receiver-type.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/span/issue-42234-unknown-receiver-type.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/span/type-annotations-needed-expr.stderr | 5 |
13 files changed, 108 insertions, 44 deletions
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 32eecdf01a3..118fd186b1c 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -6,6 +6,7 @@ use crate::infer::type_variable::TypeVariableOriginKind; use crate::ty::{self, Ty, Infer, TyVar}; use crate::ty::print::Print; use syntax::source_map::DesugaringKind; +use syntax::symbol::kw; use syntax_pos::Span; use errors::{Applicability, DiagnosticBuilder}; @@ -19,6 +20,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { found_arg_pattern: Option<&'tcx Pat>, found_ty: Option<Ty<'tcx>>, found_closure: Option<&'tcx ExprKind>, + found_method_call: Option<&'tcx ExprKind>, } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { @@ -35,6 +37,7 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { found_arg_pattern: None, found_ty: None, found_closure: None, + found_method_call: None, } } @@ -93,11 +96,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr) { - if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = ( - &expr.kind, - self.node_matches_type(expr.hir_id), - ) { - self.found_closure = Some(&expr.kind); + if self.node_matches_type(expr.hir_id).is_some() { + match expr.kind { + ExprKind::Closure(..) => self.found_closure = Some(&expr.kind), + ExprKind::MethodCall(..) => self.found_method_call = Some(&expr.kind), + _ => {} + } } intravisit::walk_expr(self, expr); } @@ -157,7 +161,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty_vars = self.type_variables.borrow(); let var_origin = ty_vars.var_origin(ty_vid); if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { - return (name.to_string(), Some(var_origin.span)); + if name != kw::SelfUpper { + return (name.to_string(), Some(var_origin.span)); + } } } @@ -175,6 +181,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>, + is_projection: bool, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); let (name, name_sp) = self.extract_type_name(&ty, None); @@ -210,6 +217,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 3 | let _ = x.sum() as f64; // | ^^^ cannot infer type for `S` span + } else if let Some(ExprKind::MethodCall(_, call_span, _)) = local_visitor.found_method_call { + // Point at the call instead of the whole expression: + // error[E0284]: type annotations needed + // --> file.rs:2:5 + // | + // 2 | vec![Ok(2)].into_iter().collect()?; + // | ^^^^^^^ cannot infer type + // | + // = note: cannot resolve `<_ as std::ops::Try>::Ok == _` + if span.contains(*call_span) { + *call_span + } else { + span + } } else { span }; @@ -247,13 +268,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where // | the type parameter `E` is specified // ``` - let mut err = struct_span_err!( - self.tcx.sess, - err_span, - E0282, - "type annotations needed{}", - ty_msg, - ); + let mut err = if is_projection { + struct_span_err!(self.tcx.sess, err_span, E0284, "type annotations needed{}", ty_msg) + } else { + struct_span_err!(self.tcx.sess, err_span, E0282, "type annotations needed{}", ty_msg) + }; let suffix = match local_visitor.found_ty { Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { @@ -334,6 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!("consider giving this pattern {}", suffix) }; err.span_label(pattern.span, msg); + } else if let Some(ExprKind::MethodCall(segment, ..)) = local_visitor.found_method_call { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(segment.ident.span) { + if segment.args.is_none() { + err.span_suggestion( + segment.ident.span, + "consider specifying the type argument in the method call", + // FIXME: we don't know how many type arguments should be set here. + format!("{}::<_>", snippet), + Applicability::HasPlaceholders, + ); + } + } } // Instead of the following: // error[E0282]: type annotations needed @@ -351,7 +382,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | ^^^ cannot infer type for `S` // | // = note: type must be known at this point - let span = name_sp.unwrap_or(span); + let span = name_sp.unwrap_or(err_span); if !err.span.span_labels().iter().any(|span_label| { span_label.label.is_some() && span_label.span == span }) && local_visitor.found_arg_pattern.is_none() diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 35017d6330d..2b00861188e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1989,7 +1989,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.lang_items().sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - self.need_type_info_err(body_id, span, self_ty).emit(); + self.need_type_info_err(body_id, span, self_ty, false).emit(); } else { let mut err = struct_span_err!( self.tcx.sess, @@ -2007,7 +2007,9 @@ impl<'a, 'tcx> InferCtxt<'a, '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_err(body_id, span, ty).emit(); + let mut err = self.need_type_info_err(body_id, span, ty, false); + self.note_obligation_cause(&mut err, obligation); + err.emit(); } } @@ -2018,21 +2020,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info_err(body_id, - obligation.cause.span, - a).emit(); + let mut err = self.need_type_info_err(body_id, span, a, false); + self.note_obligation_cause(&mut err, obligation); + err.emit(); + } + } + ty::Predicate::Projection(ref data) => { + let trait_ref = data.to_poly_trait_ref(self.tcx); + let self_ty = trait_ref.self_ty(); + if predicate.references_error() { + return; } + let mut err = self.need_type_info_err(body_id, span, self_ty, true); + err.note(&format!("cannot resolve `{}`", predicate)); + self.note_obligation_cause(&mut err, obligation); + err.emit(); } _ => { if !self.tcx.sess.has_errors() { let mut err = struct_span_err!( self.tcx.sess, - obligation.cause.span, + span, E0284, "type annotations needed: cannot resolve `{}`", predicate, ); + err.span_label(span, &format!("cannot resolve `{}`", predicate)); self.note_obligation_cause(&mut err, obligation); err.emit(); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a956aba4f62..c8f1e025bae 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5359,7 +5359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info_err((**self).body_id, sp, ty) + self.need_type_info_err((**self).body_id, sp, ty, false) .note("type must be known at this point") .emit(); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 3113e9b241d..e5f1e2cc34c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -717,7 +717,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t) + .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, false) .emit(); } } diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index 5ef1b23cbcd..dd6bde0c14d 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -1,18 +1,23 @@ -error[E0284]: type annotations needed: cannot resolve `<Self as std::iter::Iterator>::Item == i32` +error[E0284]: type annotations needed --> $DIR/associated-types-overridden-binding.rs:4:1 | LL | trait Foo: Iterator<Item = i32> {} | ------------------------------- required by `Foo` LL | trait Bar: Foo<Item = u32> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `Self` + | + = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32` -error[E0282]: type annotations needed +error[E0284]: type annotations needed --> $DIR/associated-types-overridden-binding.rs:7:1 | +LL | trait I32Iterator = Iterator<Item = i32>; + | ----------------------------------------- required by `I32Iterator` LL | trait U32Iterator = I32Iterator<Item = u32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `Self` + | + = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32` error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 4e9e54d3688..14ce4836f97 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as Foo>::A == _` +error[E0284]: type annotations needed --> $DIR/associated-types-unconstrained.rs:14:20 | LL | let x: isize = Foo::bar(); - | ^^^^^^^^ + | ^^^^^^^^ cannot infer type + | + = note: cannot resolve `<_ as Foo>::A == _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index ff92d01a69e..5f23b4f559f 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S` +error[E0284]: type annotations needed --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ cannot infer type for `H` + | + = note: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr index cb441c13c6b..905c5ae9461 100644 --- a/src/test/ui/issues/issue-65611.stderr +++ b/src/test/ui/issues/issue-65611.stderr @@ -2,7 +2,10 @@ error[E0282]: type annotations needed --> $DIR/issue-65611.rs:59:20 | LL | let x = buffer.last().unwrap().0.clone(); - | ^^^^ cannot infer type for `T` + | ^^^^ + | | + | cannot infer type for `T` + | help: consider specifying the type argument in the method call: `last::<_>` | = note: type must be known at this point diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/question-mark-type-infer.rs index 95ee01a70ce..2ef8618192f 100644 --- a/src/test/ui/question-mark-type-infer.rs +++ b/src/test/ui/question-mark-type-infer.rs @@ -9,7 +9,7 @@ fn f(x: &i32) -> Result<i32, ()> { fn g() -> Result<Vec<i32>, ()> { let l = [1, 2, 3, 4]; - l.iter().map(f).collect()? //~ ERROR type annotations needed: cannot resolve + l.iter().map(f).collect()? //~ ERROR type annotations needed } fn main() { diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 53a170e7d43..d32d9497645 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,8 +1,13 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as std::ops::Try>::Ok == _` - --> $DIR/question-mark-type-infer.rs:12:5 +error[E0284]: type annotations needed + --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ + | | + | cannot infer type + | help: consider specifying the type argument in the method call: `collect::<_>` + | + = note: cannot resolve `<_ as std::ops::Try>::Ok == _` error: aborting due to previous error diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs index 58138e21bc0..d3292bbecba 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.rs +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs @@ -9,8 +9,8 @@ fn shines_a_beacon_through_the_darkness() { } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { - data.iter() //~ ERROR type annotations needed - .sum::<_>() + data.iter() + .sum::<_>() //~ ERROR type annotations needed .to_string() } diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 30c9adb1dce..093a6f6f3eb 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -9,11 +9,10 @@ LL | x.unwrap().method_that_could_exist_on_some_type(); = note: type must be known at this point error[E0282]: type annotations needed - --> $DIR/issue-42234-unknown-receiver-type.rs:12:5 + --> $DIR/issue-42234-unknown-receiver-type.rs:13:10 | -LL | / data.iter() -LL | | .sum::<_>() - | |___________________^ cannot infer type +LL | .sum::<_>() + | ^^^ cannot infer type | = note: type must be known at this point diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr index e32a542bb7a..1efb2720e0c 100644 --- a/src/test/ui/span/type-annotations-needed-expr.stderr +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -2,7 +2,10 @@ error[E0282]: type annotations needed --> $DIR/type-annotations-needed-expr.rs:2:39 | LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; - | ^^^ cannot infer type for `S` + | ^^^ + | | + | cannot infer type for `S` + | help: consider specifying the type argument in the method call: `sum::<_>` | = note: type must be known at this point |
