Deduplicate logic
This commit is contained in:
parent
12af2561e9
commit
252773af8b
|
@ -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;
|
||||
|
||||
|
|
|
@ -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), .. }) => {
|
||||
|
|
|
@ -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 {
|
||||
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());
|
||||
let mut err = self.need_type_info_err(body_id, span, a, false);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
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,14 +2022,15 @@ 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() {
|
||||
if self.tcx.sess.has_errors() {
|
||||
return;
|
||||
}
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
|
@ -2047,12 +2039,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
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
|
||||
/// to the type parameters.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue