Indicate origin of where type parameter for uninferred types
This commit is contained in:
parent
12307b3b08
commit
8a4632dec6
28 changed files with 97 additions and 41 deletions
|
@ -3,7 +3,7 @@ use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat};
|
|||
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::type_variable::TypeVariableOriginKind;
|
||||
use crate::ty::{self, Ty, Infer, TyVar};
|
||||
use crate::ty::{self, Ty, Infer, TyVar, DefIdTree};
|
||||
use crate::ty::print::Print;
|
||||
use syntax::source_map::DesugaringKind;
|
||||
use syntax::symbol::kw;
|
||||
|
@ -117,6 +117,8 @@ fn closure_return_type_suggestion(
|
|||
descr: &str,
|
||||
name: &str,
|
||||
ret: &str,
|
||||
parent_name: Option<String>,
|
||||
parent_descr: Option<&str>,
|
||||
) {
|
||||
let (arrow, post) = match output {
|
||||
FunctionRetTy::DefaultReturn(_) => ("-> ", " "),
|
||||
|
@ -138,7 +140,12 @@ fn closure_return_type_suggestion(
|
|||
suggestion,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
|
||||
err.span_label(span, InferCtxt::missing_type_msg(
|
||||
&name,
|
||||
&descr,
|
||||
parent_name,
|
||||
parent_descr
|
||||
));
|
||||
}
|
||||
|
||||
/// Given a closure signature, return a `String` containing a list of all its argument types.
|
||||
|
@ -177,16 +184,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
highlight: Option<ty::print::RegionHighlightMode>,
|
||||
) -> (String, Option<Span>, Cow<'static, str>) {
|
||||
) -> (String, Option<Span>, Cow<'static, str>, Option<String>, Option<&'static str>) {
|
||||
if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind {
|
||||
let ty_vars = self.type_variables.borrow();
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind {
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind {
|
||||
let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
|
||||
let (parent_name, parent_desc) = if let Some(parent_def_id) = parent_def_id {
|
||||
let parent_name = self.tcx.def_key(parent_def_id).disambiguated_data.data
|
||||
.get_opt_name().map(|parent_symbol| parent_symbol.to_string());
|
||||
|
||||
let type_parent_desc = self.tcx.def_kind(parent_def_id)
|
||||
.map(|parent_def_kind| parent_def_kind.descr(parent_def_id));
|
||||
|
||||
(parent_name, type_parent_desc)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
if name != kw::SelfUpper {
|
||||
return (
|
||||
name.to_string(),
|
||||
Some(var_origin.span),
|
||||
"type parameter".into(),
|
||||
parent_name,
|
||||
parent_desc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
printer.region_highlight_mode = highlight;
|
||||
}
|
||||
let _ = ty.print(printer);
|
||||
(s, None, ty.prefix_string())
|
||||
(s, None, ty.prefix_string(), None, None)
|
||||
}
|
||||
|
||||
pub fn need_type_info_err(
|
||||
|
@ -209,7 +231,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
error_code: TypeAnnotationNeeded,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
let (name, name_sp, descr) = self.extract_type_name(&ty, None);
|
||||
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
|
||||
|
||||
|
||||
let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir());
|
||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||
|
@ -218,7 +241,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
let ty_vars = self.type_variables.borrow();
|
||||
let getter = move |ty_vid| {
|
||||
let var_origin = ty_vars.var_origin(ty_vid);
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind {
|
||||
if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
|
||||
return Some(name.to_string());
|
||||
}
|
||||
None
|
||||
|
@ -317,6 +340,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
&descr,
|
||||
&name,
|
||||
&ret,
|
||||
parent_name,
|
||||
parent_descr,
|
||||
);
|
||||
// We don't want to give the other suggestions when the problem is the
|
||||
// closure return type.
|
||||
|
@ -433,8 +458,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
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()
|
||||
{ // Avoid multiple labels pointing at `span`.
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
|
||||
{
|
||||
// Avoid multiple labels pointing at `span`.
|
||||
err.span_label(
|
||||
span,
|
||||
InferCtxt::missing_type_msg(&name, &descr, parent_name, parent_descr)
|
||||
);
|
||||
}
|
||||
|
||||
err
|
||||
|
@ -496,19 +525,42 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
let (name, _, descr) = self.extract_type_name(&ty, None);
|
||||
let (name, _, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind,
|
||||
);
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
|
||||
err.span_label(span, InferCtxt::missing_type_msg(
|
||||
&name,
|
||||
&descr,
|
||||
parent_name,
|
||||
parent_descr
|
||||
));
|
||||
err
|
||||
}
|
||||
|
||||
fn missing_type_msg(type_name: &str, descr: &str) -> Cow<'static, str>{
|
||||
fn missing_type_msg(
|
||||
type_name: &str,
|
||||
descr: &str,
|
||||
parent_name: Option<String>,
|
||||
parent_descr: Option<&str>,
|
||||
) -> Cow<'static, str> {
|
||||
if type_name == "_" {
|
||||
"cannot infer type".into()
|
||||
} else {
|
||||
format!("cannot infer type for {} `{}`", descr, type_name).into()
|
||||
let parent_desc = if let Some(parent_name) = parent_name {
|
||||
let parent_type_descr = if let Some(parent_descr) = parent_descr {
|
||||
format!(" the {}", parent_descr)
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
|
||||
format!(" declared on{} `{}`", parent_type_descr, parent_name)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
format!("cannot infer type for {} `{}`{}", descr, type_name, parent_desc).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1135,7 +1135,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.universe(),
|
||||
false,
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(param.name),
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(
|
||||
param.name,
|
||||
Some(param.def_id)
|
||||
),
|
||||
span,
|
||||
},
|
||||
);
|
||||
|
|
|
@ -124,7 +124,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
|
|||
if let ty::TyVar(ty_vid) = infer_ty {
|
||||
let ty_vars = self.infcx.type_variables.borrow();
|
||||
if let TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_),
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
|
||||
span,
|
||||
} = *ty_vars.var_origin(ty_vid)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use crate::ty::{self, Ty, TyVid};
|
||||
use crate::hir::def_id::DefId;
|
||||
|
||||
use std::cmp;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -49,7 +50,7 @@ pub enum TypeVariableOriginKind {
|
|||
MiscVariable,
|
||||
NormalizeProjectionType,
|
||||
TypeInference,
|
||||
TypeParameterDefinition(Symbol),
|
||||
TypeParameterDefinition(Symbol, Option<DefId>),
|
||||
|
||||
/// One of the upvars or closure kind parameters in a `ClosureSubsts`
|
||||
/// (before it has been determined).
|
||||
|
|
|
@ -2113,7 +2113,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.var_map.entry(ty).or_insert_with(||
|
||||
infcx.next_ty_var(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(name),
|
||||
kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0698]: type inside `async fn` body must be known in this context
|
|||
--> $DIR/unresolved_type_param.rs:9:5
|
||||
|
|
||||
LL | bar().await;
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/unresolved_type_param.rs:9:5
|
||||
|
|
|
@ -30,7 +30,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/fn-const-param-infer.rs:22:23
|
||||
|
|
||||
LL | let _ = Checked::<generic>;
|
||||
| ^^^^^^^ cannot infer type for type parameter `T`
|
||||
| ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-const-param-infer.rs:25:40
|
||||
|
|
|
@ -2,13 +2,13 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-64662.rs:2:9
|
||||
|
|
||||
LL | A = foo(),
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the function `foo`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-64662.rs:3:9
|
||||
|
|
||||
LL | B = foo(),
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the function `foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/E0401.rs:11:5
|
||||
|
|
||||
LL | bfnr(x);
|
||||
| ^^^^ cannot infer type for type parameter `U`
|
||||
| ^^^^ cannot infer type for type parameter `U` declared on the function `bfnr`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0284]: type annotations needed
|
|||
--> $DIR/issue-12028.rs:27:14
|
||||
|
|
||||
LL | self.input_stream(&mut stream);
|
||||
| ^^^^^^^^^^^^ cannot infer type for type parameter `H`
|
||||
| ^^^^^^^^^^^^ cannot infer type for type parameter `H` declared on the trait `StreamHash`
|
||||
|
|
||||
= note: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-16966.rs:2:5
|
||||
|
|
||||
LL | panic!(std::default::Default::default());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M` declared on the function `begin_panic`
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `B<T>`
|
|||
--> $DIR/issue-17551.rs:6:15
|
||||
|
|
||||
LL | let foo = B(marker::PhantomData);
|
||||
| --- ^ cannot infer type for type parameter `T`
|
||||
| --- ^ cannot infer type for type parameter `T` declared on the struct `B`
|
||||
| |
|
||||
| consider giving `foo` the explicit type `B<T>`, where the type parameter `T` is specified
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | let (tx, rx) = channel();
|
|||
| -------- consider giving this pattern the explicit type `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`, where the type parameter `T` is specified
|
||||
...
|
||||
LL | tx.send(Foo{ foo: PhantomData });
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the struct `Foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-5062.rs:1:29
|
||||
|
|
||||
LL | fn main() { format!("{:?}", None); }
|
||||
| ^^^^ cannot infer type for type parameter `T`
|
||||
| ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-6458-2.rs:3:21
|
||||
|
|
||||
LL | format!("{:?}", None);
|
||||
| ^^^^ cannot infer type for type parameter `T`
|
||||
| ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-6458-3.rs:4:5
|
||||
|
|
||||
LL | mem::transmute(0);
|
||||
| ^^^^^^^^^^^^^^ cannot infer type for type parameter `U`
|
||||
| ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/issue-6458.rs:9:4
|
||||
|
|
||||
LL | foo(TypeWithState(marker::PhantomData));
|
||||
| ^^^ cannot infer type for type parameter `State`
|
||||
| ^^^ cannot infer type for type parameter `State` declared on the function `foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/missing-type-parameter.rs:4:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^ cannot infer type for type parameter `X`
|
||||
| ^^^ cannot infer type for type parameter `X` declared on the function `foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed
|
|||
LL | let _ = (vec![1,2,3]).into_iter().sum() as f64;
|
||||
| ^^^
|
||||
| |
|
||||
| cannot infer type for type parameter `S`
|
||||
| cannot infer type for type parameter `S` declared on the method `sum`
|
||||
| help: consider specifying the type argument in the method call: `sum::<S>`
|
||||
|
|
||||
= note: type must be known at this point
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/traits-multidispatch-convert-ambig-dest.rs:26:5
|
||||
|
|
||||
LL | test(22, std::default::Default::default());
|
||||
| ^^^^ cannot infer type for type parameter `U`
|
||||
| ^^^^ cannot infer type for type parameter `U` declared on the function `test`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed
|
|||
LL | .or_else(|err| {
|
||||
| ^^^^^^^
|
||||
| |
|
||||
| cannot infer type for type parameter `F`
|
||||
| cannot infer type for type parameter `F` declared on the method `or_else`
|
||||
| help: consider specifying the type arguments in the method call: `or_else::<F, O>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0282]: type annotations needed
|
|||
LL | lst.sort_by_key(|&(v, _)| v.iter().sum());
|
||||
| ^^^^^^^^^^^ --- help: consider specifying the type argument in the method call: `sum::<S>`
|
||||
| |
|
||||
| cannot infer type for type parameter `K`
|
||||
| cannot infer type for type parameter `K` declared on the method `sort_by_key`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ LL | S(std::marker::PhantomData).foo();
|
|||
| ^--------------------------------
|
||||
| |
|
||||
| this method call resolves to `<Self as T>::A`
|
||||
| cannot infer type for type parameter `X`
|
||||
| cannot infer type for type parameter `X` declared on the struct `S`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:8:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the function `foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/unbounded-type-param-in-fn.rs:6:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^ cannot infer type for type parameter `T`
|
||||
| ^^^ cannot infer type for type parameter `T` declared on the function `foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ LL | fn foo<T: Into<String>>(x: i32) {}
|
|||
LL | foo(42);
|
||||
| ^^^
|
||||
| |
|
||||
| cannot infer type for type parameter `T`
|
||||
| cannot infer type for type parameter `T` declared on the function `foo`
|
||||
| help: consider specifying the type argument in the function call: `foo::<T>`
|
||||
|
|
||||
= note: cannot resolve `_: std::convert::Into<std::string::String>`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/unconstrained-none.rs:4:5
|
||||
|
|
||||
LL | None;
|
||||
| ^^^^ cannot infer type for type parameter `T`
|
||||
| ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0282]: type annotations needed
|
|||
--> $DIR/unconstrained-ref.rs:6:5
|
||||
|
|
||||
LL | S { o: &None };
|
||||
| ^ cannot infer type for type parameter `T`
|
||||
| ^ cannot infer type for type parameter `T` declared on the struct `S`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue