From 252773af8ba86a644ccf3ff0b0cc06cc3857c7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 29 Oct 2019 17:28:39 -0700 Subject: [PATCH] Deduplicate logic --- src/librustc/infer/error_reporting/mod.rs | 1 + .../infer/error_reporting/need_type_info.rs | 36 ++++++++-- src/librustc/traits/error_reporting.rs | 72 +++++++++---------- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/check/writeback.rs | 3 +- src/test/ui/associated-const/issue-63496.rs | 4 +- .../ui/associated-const/issue-63496.stderr | 12 ++-- .../ui/associated-item/issue-48027.stderr | 6 +- src/test/ui/error-codes/E0283.stderr | 6 +- src/test/ui/issues/issue-21974.stderr | 6 +- src/test/ui/issues/issue-24424.rs | 2 +- src/test/ui/issues/issue-24424.stderr | 6 +- src/test/ui/issues/issue-29147.rs | 2 +- src/test/ui/issues/issue-29147.stderr | 6 +- src/test/ui/issues/issue-54954.stderr | 6 +- src/test/ui/issues/issue-58022.rs | 2 +- src/test/ui/issues/issue-58022.stderr | 6 +- ...ait-static-method-generic-inference.stderr | 6 +- src/test/ui/type/type-annotation-needed.rs | 2 + .../ui/type/type-annotation-needed.stderr | 6 +- .../ui/type/type-check/issue-40294.stderr | 6 +- 21 files changed, 121 insertions(+), 78 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 58c1498faa9..c9d57706d55 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -70,6 +70,7 @@ use std::{cmp, fmt}; mod note; mod need_type_info; +pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 118fd186b1c..98134915b45 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -151,6 +151,25 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { .unwrap_or_default() } +pub enum TypeAnnotationNeeded { + E0282, + E0283, + E0284, +} + +impl Into for TypeAnnotationNeeded { + fn into(self) -> errors::DiagnosticId { + syntax::diagnostic_used!(E0282); + syntax::diagnostic_used!(E0283); + syntax::diagnostic_used!(E0284); + errors::DiagnosticId::Error(match self { + Self::E0282 => "E0282".to_string(), + Self::E0283 => "E0283".to_string(), + Self::E0284 => "E0284".to_string(), + }) + } +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn extract_type_name( &self, @@ -181,7 +200,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option, span: Span, ty: Ty<'tcx>, - is_projection: bool, + error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); let (name, name_sp) = self.extract_type_name(&ty, None); @@ -217,7 +236,9 @@ 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 { + } 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 @@ -268,11 +289,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | consider giving `b` the explicit type `std::result::Result`, where // | the type parameter `E` is specified // ``` - 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 error_code = error_code.into(); + let mut err = self.tcx.sess.struct_span_err_with_code( + err_span, + &format!("type annotations needed{}", ty_msg), + error_code, + ); let suffix = match local_visitor.found_ty { Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2b00861188e..6b9e413be13 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -22,6 +22,7 @@ use crate::hir; use crate::hir::Node; use crate::hir::def_id::DefId; use crate::infer::{self, InferCtxt}; +use crate::infer::error_reporting::TypeAnnotationNeeded::*; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::session::DiagnosticMessageId; use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; @@ -1951,7 +1952,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return; } - match predicate { + let mut err = match predicate { ty::Predicate::Trait(ref data) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); @@ -1985,45 +1986,35 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and dont add the obligations to // begin with in those cases. - if - self.tcx.lang_items().sized_trait() + if 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, false).emit(); - } else { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0283, - "type annotations needed: cannot resolve `{}`", - predicate, - ); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + self.need_type_info_err(body_id, span, self_ty, E0282).emit(); + return; } + let mut err = self.need_type_info_err(body_id, span, self_ty, E0283); + err.note(&format!("cannot resolve `{}`", predicate)); + err } ty::Predicate::WellFormed(ty) => { // Same hacky approach as above to avoid deluging user // with error messages. - if !ty.references_error() && !self.tcx.sess.has_errors() { - let mut err = self.need_type_info_err(body_id, span, ty, false); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + if ty.references_error() || self.tcx.sess.has_errors() { + return; } + self.need_type_info_err(body_id, span, ty, E0282) } ty::Predicate::Subtype(ref data) => { if data.references_error() || self.tcx.sess.has_errors() { // no need to overload user in such cases - } else { - 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()); - let mut err = self.need_type_info_err(body_id, span, a, false); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + return } + 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, span, a, E0282) } ty::Predicate::Projection(ref data) => { let trait_ref = data.to_poly_trait_ref(self.tcx); @@ -2031,27 +2022,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if predicate.references_error() { return; } - let mut err = self.need_type_info_err(body_id, span, self_ty, true); + let mut err = self.need_type_info_err(body_id, span, self_ty, E0284); err.note(&format!("cannot resolve `{}`", predicate)); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + err } _ => { - if !self.tcx.sess.has_errors() { - let mut err = struct_span_err!( - self.tcx.sess, - 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(); + if self.tcx.sess.has_errors() { + return; } + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot resolve `{}`", + predicate, + ); + err.span_label(span, &format!("cannot resolve `{}`", predicate)); + err } - } + }; + self.note_obligation_cause(&mut err, obligation); + err.emit(); } /// Returns `true` if the trait predicate may apply for *some* assignment diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c8f1e025bae..43e7bbcf0c0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,6 +103,7 @@ use rustc_index::vec::Idx; use rustc_target::spec::abi::Abi; use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; @@ -5359,7 +5360,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, false) + self.need_type_info_err((**self).body_id, sp, ty, E0282) .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 e5f1e2cc34c..35f25b322e0 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -8,6 +8,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::InferCtxt; +use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; @@ -717,7 +718,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, false) + .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282) .emit(); } } diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs index 311c48b5e48..f9f663af5e2 100644 --- a/src/test/ui/associated-const/issue-63496.rs +++ b/src/test/ui/associated-const/issue-63496.rs @@ -2,8 +2,8 @@ trait A { const C: usize; fn f() -> ([u8; A::C], [u8; A::C]); - //~^ ERROR: type annotations needed: cannot resolve - //~| ERROR: type annotations needed: cannot resolve + //~^ ERROR: type annotations needed + //~| ERROR: type annotations needed } fn main() {} diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr index 70bb12de1fb..23916a3ba44 100644 --- a/src/test/ui/associated-const/issue-63496.stderr +++ b/src/test/ui/associated-const/issue-63496.stderr @@ -1,20 +1,24 @@ -error[E0283]: type annotations needed: cannot resolve `_: A` +error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:21 | LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ + | ^^^^ cannot infer type + | + = note: cannot resolve `_: A` -error[E0283]: type annotations needed: cannot resolve `_: A` +error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:33 | LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ + | ^^^^ cannot infer type + | + = note: cannot resolve `_: A` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 562146a426d..9c825d593d3 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -7,13 +7,15 @@ LL | const X: usize; LL | impl dyn Bar {} | ^^^^^^^ the trait `Bar` cannot be made into an object -error[E0283]: type annotations needed: cannot resolve `_: Bar` +error[E0283]: type annotations needed --> $DIR/issue-48027.rs:3:32 | LL | const X: usize; | --------------- required by `Bar::X` LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ + | ^^^^^^ cannot infer type + | + = note: cannot resolve `_: Bar` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index aba649d83ec..ae5b7c3ae8f 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `_: Generator` +error[E0283]: type annotations needed --> $DIR/E0283.rs:18:21 | LL | fn create() -> u32; | ------------------- required by `Generator::create` ... LL | let cont: u32 = Generator::create(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: Generator` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index 7ceb2bd23f6..4002c1eac2e 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed --> $DIR/issue-21974.rs:10:1 | LL | trait Foo { @@ -11,7 +11,9 @@ LL | | { LL | | x.foo(); LL | | y.foo(); LL | | } - | |_^ + | |_^ cannot infer type for `&'a T` + | + = note: cannot resolve `&'a T: Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24424.rs b/src/test/ui/issues/issue-24424.rs index 9b74cd1230e..22bf513afe8 100644 --- a/src/test/ui/issues/issue-24424.rs +++ b/src/test/ui/issues/issue-24424.rs @@ -2,6 +2,6 @@ trait Trait1<'l0, T0> {} trait Trait0<'l0> {} impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} -//~^ ERROR type annotations needed: cannot resolve `T0: Trait0<'l0>` +//~^ ERROR type annotations needed fn main() {} diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 8c539f7cedd..87214f56a1b 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `T0: Trait0<'l0>` +error[E0283]: type annotations needed --> $DIR/issue-24424.rs:4:1 | LL | trait Trait0<'l0> {} | ----------------- required by `Trait0` LL | LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `T0` + | + = note: cannot resolve `T0: Trait0<'l0>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29147.rs b/src/test/ui/issues/issue-29147.rs index 7ec96b97eef..271bc526033 100644 --- a/src/test/ui/issues/issue-29147.rs +++ b/src/test/ui/issues/issue-29147.rs @@ -18,5 +18,5 @@ impl Foo for S5 { fn xxx(&self) {} } impl Foo for S5 { fn xxx(&self) {} } fn main() { - let _ = >::xxx; //~ ERROR cannot resolve `S5<_>: Foo` + let _ = >::xxx; //~ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index c9dd92fca7d..4de6a7c8514 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `S5<_>: Foo` +error[E0283]: type annotations needed --> $DIR/issue-29147.rs:21:13 | LL | trait Foo { fn xxx(&self); } | -------------- required by `Foo::xxx` ... LL | let _ = >::xxx; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ cannot infer type for `S5<_>` + | + = note: cannot resolve `S5<_>: Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 56ccdaf7aac..d99a5772e8a 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -4,14 +4,16 @@ error[E0379]: trait fns cannot be declared const LL | const fn const_val() -> usize { | ^^^^^ trait fns cannot be const -error[E0283]: type annotations needed: cannot resolve `_: Tt` +error[E0283]: type annotations needed --> $DIR/issue-54954.rs:3:24 | LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type ... LL | const fn const_val() -> usize { | --------- - required by this bound in `Tt::const_val` + | + = note: cannot resolve `_: Tt` error[E0080]: evaluation of constant value failed --> $DIR/issue-54954.rs:13:15 diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs index 30527903ed0..e4b9b3b53a6 100644 --- a/src/test/ui/issues/issue-58022.rs +++ b/src/test/ui/issues/issue-58022.rs @@ -2,7 +2,7 @@ pub trait Foo: Sized { const SIZE: usize; fn new(slice: &[u8; Foo::SIZE]) -> Self; - //~^ ERROR: type annotations needed: cannot resolve `_: Foo` + //~^ ERROR: type annotations needed } pub struct Bar(T); diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index a3e4cb63202..ef0d66d7ad6 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -4,14 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo LL | Foo(Box::new(*slice)) | ^^^ not a function, tuple struct or tuple variant -error[E0283]: type annotations needed: cannot resolve `_: Foo` +error[E0283]: type annotations needed --> $DIR/issue-58022.rs:4:25 | LL | const SIZE: usize; | ------------------ required by `Foo::SIZE` LL | LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ + | ^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr index 22931c5ba32..f9718dac354 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.stderr +++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `_: base::HasNew` +error[E0283]: type annotations needed --> $DIR/trait-static-method-generic-inference.rs:24:25 | LL | fn new() -> T; | -------------- required by `base::HasNew::new` ... LL | let _f: base::Foo = base::HasNew::new(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: base::HasNew` error: aborting due to previous error diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs index 3b1521d5c02..a420515be49 100644 --- a/src/test/ui/type/type-annotation-needed.rs +++ b/src/test/ui/type/type-annotation-needed.rs @@ -5,4 +5,6 @@ fn foo>(x: i32) {} fn main() { foo(42); //~^ ERROR type annotations needed + //~| NOTE cannot infer type + //~| NOTE cannot resolve } diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 460bbe9dbc4..f30bbf6b7db 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into` +error[E0283]: type annotations needed --> $DIR/type-annotation-needed.rs:6:5 | LL | fn foo>(x: i32) {} | --- ------------ required by this bound in `foo` ... LL | foo(42); - | ^^^ + | ^^^ cannot infer type for `T` + | + = note: cannot resolve `_: std::convert::Into` error: aborting due to previous error diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 508783aaf2b..f2bfd9ba541 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed --> $DIR/issue-40294.rs:5:1 | LL | trait Foo: Sized { @@ -11,7 +11,9 @@ LL | | { LL | | x.foo(); LL | | y.foo(); LL | | } - | |_^ + | |_^ cannot infer type for `&'a T` + | + = note: cannot resolve `&'a T: Foo` error: aborting due to previous error