Deduplicate logic

This commit is contained in:
Esteban Küber 2019-10-29 17:28:39 -07:00
parent 12af2561e9
commit 252773af8b
21 changed files with 121 additions and 78 deletions

View File

@ -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;

View File

@ -151,6 +151,25 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
.unwrap_or_default()
}
pub enum TypeAnnotationNeeded {
E0282,
E0283,
E0284,
}
impl Into<errors::DiagnosticId> 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<hir::BodyId>,
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<i32, E>`, 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), .. }) => {

View File

@ -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

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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() {}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() {}

View File

@ -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

View File

@ -18,5 +18,5 @@ impl Foo for S5<u32> { fn xxx(&self) {} }
impl Foo for S5<u64> { fn xxx(&self) {} }
fn main() {
let _ = <S5<_>>::xxx; //~ ERROR cannot resolve `S5<_>: Foo`
let _ = <S5<_>>::xxx; //~ ERROR type annotations needed
}

View File

@ -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 _ = <S5<_>>::xxx;
| ^^^^^^^^^^^^
| ^^^^^^^^^^^^ cannot infer type for `S5<_>`
|
= note: cannot resolve `S5<_>: Foo`
error: aborting due to previous error

View File

@ -4,14 +4,16 @@ error[E0379]: trait fns cannot be declared const
LL | const fn const_val<T: Sized>() -> 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<T: Sized>() -> 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

View File

@ -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: ?Sized>(T);

View File

@ -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

View File

@ -1,11 +1,13 @@
error[E0283]: type annotations needed: cannot resolve `_: base::HasNew<base::Foo>`
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<base::Foo>`
error: aborting due to previous error

View File

@ -5,4 +5,6 @@ fn foo<T: Into<String>>(x: i32) {}
fn main() {
foo(42);
//~^ ERROR type annotations needed
//~| NOTE cannot infer type
//~| NOTE cannot resolve
}

View File

@ -1,11 +1,13 @@
error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into<std::string::String>`
error[E0283]: type annotations needed
--> $DIR/type-annotation-needed.rs:6:5
|
LL | fn foo<T: Into<String>>(x: i32) {}
| --- ------------ required by this bound in `foo`
...
LL | foo(42);
| ^^^
| ^^^ cannot infer type for `T`
|
= note: cannot resolve `_: std::convert::Into<std::string::String>`
error: aborting due to previous error

View File

@ -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