Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Point at method call when type annotations are needed #65951

Merged
merged 12 commits into from
Dec 14, 2019
42 changes: 27 additions & 15 deletions src/librustc/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use syntax::source_map::DesugaringKind;
use syntax::symbol::kw;
use syntax_pos::Span;
use errors::{Applicability, DiagnosticBuilder};
use std::borrow::Cow;

use rustc_error_codes::*;

Expand Down Expand Up @@ -113,6 +114,7 @@ fn closure_return_type_suggestion(
err: &mut DiagnosticBuilder<'_>,
output: &FunctionRetTy,
body: &Body,
descr: &str,
name: &str,
ret: &str,
) {
Expand All @@ -136,7 +138,7 @@ fn closure_return_type_suggestion(
suggestion,
Applicability::HasPlaceholders,
);
err.span_label(span, InferCtxt::missing_type_msg(&name));
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
}

/// Given a closure signature, return a `String` containing a list of all its argument types.
Expand Down Expand Up @@ -175,13 +177,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self,
ty: Ty<'tcx>,
highlight: Option<ty::print::RegionHighlightMode>,
) -> (String, Option<Span>) {
) -> (String, Option<Span>, Cow<'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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @estebank if we wanted to say more about where the type parameter came from, we would augment this enum with the DefId of the parameter instead of its name (I imagine we can extract the name -- as well as the context -- from that DefId)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #67277 to track this

if name != kw::SelfUpper {
return (name.to_string(), Some(var_origin.span));
return (
name.to_string(),
Some(var_origin.span),
"type parameter".into(),
);
}
}
}
Expand All @@ -192,7 +198,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
printer.region_highlight_mode = highlight;
}
let _ = ty.print(printer);
(s, None)
(s, None, ty.prefix_string())
}

pub fn need_type_info_err(
Expand All @@ -203,7 +209,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
error_code: TypeAnnotationNeeded,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let (name, name_sp) = self.extract_type_name(&ty, None);
let (name, name_sp, 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 {
Expand Down Expand Up @@ -308,6 +314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&mut err,
&decl.output,
&body,
&descr,
&name,
&ret,
);
Expand Down Expand Up @@ -427,7 +434,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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));
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
}

err
Expand Down Expand Up @@ -468,10 +475,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
} else {
let sig = self.tcx.fn_sig(did);
err.span_label(e.span, &format!(
"this method call resolves to `{:?}`",
sig.output().skip_binder(),
));
let bound_output = sig.output();
let output = bound_output.skip_binder();
err.span_label(e.span, &format!("this method call resolves to `{:?}`", output));
let kind = &output.kind;
if let ty::Projection(proj) | ty::UnnormalizedProjection(proj) = kind {
if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) {
err.span_label(span, &format!("`{:?}` defined here", output));
}
}
}
}
}
Expand All @@ -484,19 +496,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
) -> DiagnosticBuilder<'tcx> {
let ty = self.resolve_vars_if_possible(&ty);
let name = self.extract_type_name(&ty, None).0;
let (name, _, 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));
err.span_label(span, InferCtxt::missing_type_msg(&name, &descr));
err
}

fn missing_type_msg(type_name: &str) -> String {
fn missing_type_msg(type_name: &str, descr: &str) -> Cow<'static, str>{
if type_name == "_" {
"cannot infer type".to_owned()
"cannot infer type".into()
} else {
format!("cannot infer type for `{}`", type_name)
format!("cannot infer type for {} `{}`", descr, type_name).into()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0284]: type annotations needed
LL | trait Foo: Iterator<Item = i32> {}
| ------------------------------- required by `Foo`
LL | trait Bar: Foo<Item = u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `Self`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
|
= note: cannot resolve `<Self as std::iter::Iterator>::Item == i32`

Expand All @@ -14,7 +14,7 @@ error[E0284]: type annotations needed
LL | trait I32Iterator = Iterator<Item = i32>;
| ----------------------------------------- required by `I32Iterator`
LL | trait U32Iterator = I32Iterator<Item = u32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `Self`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
|
= note: cannot resolve `<Self as std::iter::Iterator>::Item == i32`

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/unresolved_type_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async fn bar<T>() -> () {}
async fn foo() {
bar().await;
//~^ ERROR type inside `async fn` body must be known in this context
//~| NOTE cannot infer type for `T`
//~| NOTE cannot infer type for type parameter `T`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@estebank do you think it's possible/desirable for us to say "type parameter T declared on bar" or something like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is desirable, but not trivial to accomplish at the moment. The only way I can see of relating a type param and where it came from is with judicious use of a visitor, which I believe will require enough tweaking that would push this PR to not land in the next beta. I can certainly follow up on that. Note that neither this change or that one will address the cases where we say "cannot infer type 🤷" and nothing else.

//~| NOTE the type is part of the `async fn` body because of this `await`
//~| NOTE in this expansion of desugaring of `await`
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/unresolved_type_param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `T`
| ^^^ cannot infer type for type parameter `T`
|
note: the type is part of the `async fn` body because of this `await`
--> $DIR/unresolved_type_param.rs:9:5
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/cannot-infer-const-args.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error[E0282]: type annotations needed
--> $DIR/cannot-infer-const-args.rs:9:5
|
LL | foo();
| ^^^ cannot infer type for `fn() -> usize {foo::<_: usize>}`
| ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/fn-const-param-infer.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `T`
| ^^^^^^^ cannot infer type for type parameter `T`

error[E0308]: mismatched types
--> $DIR/fn-const-param-infer.rs:25:40
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/consts/issue-64662.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ error[E0282]: type annotations needed
--> $DIR/issue-64662.rs:2:9
|
LL | A = foo(),
| ^^^ cannot infer type for `T`
| ^^^ cannot infer type for type parameter `T`

error[E0282]: type annotations needed
--> $DIR/issue-64662.rs:3:9
|
LL | B = foo(),
| ^^^ cannot infer type for `T`
| ^^^ cannot infer type for type parameter `T`

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0401.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ error[E0282]: type annotations needed
--> $DIR/E0401.rs:11:5
|
LL | bfnr(x);
| ^^^^ cannot infer type for `U`
| ^^^^ cannot infer type for type parameter `U`

error: aborting due to 4 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-12028.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `H`
| ^^^^^^^^^^^^ cannot infer type for type parameter `H`
|
= note: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S`

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-16966.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `M`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17551.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `T`
| --- ^ cannot infer type for type parameter `T`
| |
| consider giving `foo` the explicit type `B<T>`, where the type parameter `T` is specified

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-21974.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ LL | | {
LL | | x.foo();
LL | | y.foo();
LL | | }
| |_^ cannot infer type for `&'a T`
| |_^ cannot infer type for reference `&'a T`
|
= note: cannot resolve `&'a T: Foo`
estebank marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-24424.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T0`
|
= note: cannot resolve `T0: Trait0<'l0>`
estebank marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-25368.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `T`
| ^^^ cannot infer type for type parameter `T`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-29147.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | trait Foo { fn xxx(&self); }
| -------------- required by `Foo::xxx`
...
LL | let _ = <S5<_>>::xxx;
| ^^^^^^^^^^^^ cannot infer type for `S5<_>`
| ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
|
= note: cannot resolve `S5<_>: Foo`

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-5062.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-5062.rs:1:29
|
LL | fn main() { format!("{:?}", None); }
| ^^^^ cannot infer type for `T`
| ^^^^ cannot infer type for type parameter `T`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-6458-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-6458-2.rs:3:21
|
LL | format!("{:?}", None);
| ^^^^ cannot infer type for `T`
| ^^^^ cannot infer type for type parameter `T`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-6458-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-6458-3.rs:4:5
|
LL | mem::transmute(0);
| ^^^^^^^^^^^^^^ cannot infer type for `U`
| ^^^^^^^^^^^^^^ cannot infer type for type parameter `U`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-6458.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-6458.rs:9:4
|
LL | foo(TypeWithState(marker::PhantomData));
| ^^^ cannot infer type for `State`
| ^^^ cannot infer type for type parameter `State`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-65611.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | let x = buffer.last().unwrap().0.clone();
| -------^^^^--
| | |
| | cannot infer type for `T`
| | cannot infer type for type parameter `T`
| this method call resolves to `std::option::Option<&T>`
|
= note: type must be known at this point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `std::vec::Vec<T>`
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
|
LL | let mut x = Vec::new();
| ----- ^^^^^^^^ cannot infer type for `T`
| ----- ^^^^^^^^ cannot infer type for type parameter `T`
| |
| consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/missing-type-parameter.rs:4:5
|
LL | foo();
| ^^^ cannot infer type for `X`
| ^^^ cannot infer type for type parameter `X`

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/span/issue-42234-unknown-receiver-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `std::option::Option<_>`
LL | let x: Option<_> = None;
| - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified
LL | x.unwrap().method_that_could_exist_on_some_type();
| ^^^^^^ cannot infer type for `T`
| ^^^^^^ cannot infer type for type parameter `T`
|
= note: type must be known at this point

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/span/type-annotations-needed-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | let _ = (vec![1,2,3]).into_iter().sum() as f64;
| ^^^
| |
| cannot infer type for `S`
| cannot infer type for type parameter `S`
| help: consider specifying the type argument in the method call: `sum::<S>`
|
= note: type must be known at this point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 `U`
| ^^^^ cannot infer type for type parameter `U`

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | .or_else(|err| {
| ^^^^^^^
| |
| cannot infer type for `F`
| cannot infer type for type parameter `F`
| help: consider specifying the type arguments in the method call: `or_else::<F, O>`

error: aborting due to previous error
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/type-inference/sort_by_key.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 `K`
| cannot infer type for type parameter `K`

error: aborting due to previous error

Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/type-inference/unbounded-associated-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait T {
type A;
fn foo(&self) -> Self::A {
panic!()
}
}

struct S<X>(std::marker::PhantomData<X>);

impl<X> T for S<X> {
type A = X;
}

fn main() {
S(std::marker::PhantomData).foo(); //~ ERROR type annotations needed
}
Loading