diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index e1a2a237c2324..9df769d99ed34 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -617,6 +617,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }); if let Some((decl, body_id)) = closure_decl_and_body_id { + for arg in fn_sig.inputs().skip_binder().iter() { + if let Some((ty, ty_span)) = self.unresolved_type_vars(arg) { + let ty_span = match ty_span { + Some(ty_span) => ty_span, + None => match ty.ty_vid() { + Some(ty_vid) => { + self.inner + .borrow_mut() + .type_variables() + .var_origin(ty_vid) + .span + } + None => continue, + }, + }; + err.span_label( + ty_span, + "give this closure parameter an explicit type instead of `_`", + ); + // We don't want to give the other suggestions when the problem is + // a closure parameter type. + return err; + } + } + + // Parameters were all fine, assume there was an issue with the return type closure_return_type_suggestion( &mut err, &decl.output, diff --git a/src/test/ui/closures/closure-signature/unspecified-output.rs b/src/test/ui/closures/closure-signature/unspecified-output.rs new file mode 100644 index 0000000000000..655da4765af37 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-output.rs @@ -0,0 +1,3 @@ +fn main() { + let a = |a: i32, b: &i32| Vec::new(); //~ ERROR E0282 +} diff --git a/src/test/ui/closures/closure-signature/unspecified-output.stderr b/src/test/ui/closures/closure-signature/unspecified-output.stderr new file mode 100644 index 0000000000000..144d4b1f81299 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-output.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for the closure `fn(i32, &i32) -> Vec<_>` + --> $DIR/unspecified-output.rs:2:31 + | +LL | let a = |a: i32, b: &i32| Vec::new(); + | ^^^^^^^^ cannot infer type for type parameter `T` + | +help: give this closure an explicit return type without `_` placeholders + | +LL | let a = |a: i32, b: &i32| -> Vec<_> { Vec::new() }; + | +++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-fn.rs b/src/test/ui/closures/closure-signature/unspecified-parameter-fn.rs new file mode 100644 index 0000000000000..7c0cab2877547 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-fn.rs @@ -0,0 +1,3 @@ +fn main() { + let a = |a: i32, b: fn(i32) -> _| -> Vec { Vec::new() }; //~ ERROR E0282 +} diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-fn.stderr b/src/test/ui/closures/closure-signature/unspecified-parameter-fn.stderr new file mode 100644 index 0000000000000..942aa4147f551 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-fn.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for the closure `fn(i32, fn(i32) -> _) -> Vec` + --> $DIR/unspecified-parameter-fn.rs:2:13 + | +LL | let a = |a: i32, b: fn(i32) -> _| -> Vec { Vec::new() }; + | ^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | give this closure parameter an explicit type instead of `_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-ref.rs b/src/test/ui/closures/closure-signature/unspecified-parameter-ref.rs new file mode 100644 index 0000000000000..d3464fa49a6f1 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-ref.rs @@ -0,0 +1,3 @@ +fn main() { + let a = |a: i32, b: &_| -> Vec { Vec::new() }; //~ ERROR E0282 +} diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-ref.stderr b/src/test/ui/closures/closure-signature/unspecified-parameter-ref.stderr new file mode 100644 index 0000000000000..31b3d9ab82bb4 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-ref.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for the closure `fn(i32, &_) -> Vec` + --> $DIR/unspecified-parameter-ref.rs:2:13 + | +LL | let a = |a: i32, b: &_| -> Vec { Vec::new() }; + | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | give this closure parameter an explicit type instead of `_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.rs b/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.rs new file mode 100644 index 0000000000000..c1ba8c3714d24 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.rs @@ -0,0 +1,3 @@ +fn main() { + let a = |a: i32, b: Vec<_>| -> Vec { Vec::new() }; //~ ERROR E0282 +} diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.stderr b/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.stderr new file mode 100644 index 0000000000000..b1adafd3e9d1f --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter-type-param.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for the closure `fn(i32, Vec<_>) -> Vec` + --> $DIR/unspecified-parameter-type-param.rs:2:13 + | +LL | let a = |a: i32, b: Vec<_>| -> Vec { Vec::new() }; + | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | give this closure parameter an explicit type instead of `_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter.rs b/src/test/ui/closures/closure-signature/unspecified-parameter.rs new file mode 100644 index 0000000000000..c7cd6ba3a4a29 --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter.rs @@ -0,0 +1,3 @@ +fn main() { + let a = |a: _, b: &i32| -> Vec { Vec::new() }; //~ ERROR E0282 +} diff --git a/src/test/ui/closures/closure-signature/unspecified-parameter.stderr b/src/test/ui/closures/closure-signature/unspecified-parameter.stderr new file mode 100644 index 0000000000000..447fa43afadae --- /dev/null +++ b/src/test/ui/closures/closure-signature/unspecified-parameter.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/unspecified-parameter.rs:2:14 + | +LL | let a = |a: _, b: &i32| -> Vec { Vec::new() }; + | ^ consider giving this closure parameter a type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`.