From df996e8e12b094e3aedfe0e35c2a8ded57f56890 Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Fri, 5 Jun 2020 12:27:43 +0100 Subject: [PATCH 1/2] Make `need_type_info_err` more conservative --- .../infer/error_reporting/need_type_info.rs | 17 +++- ...er-vars-supply-ty-with-bound-region.stderr | 4 +- src/test/ui/issues/issue-23046.rs | 4 +- src/test/ui/issues/issue-23046.stderr | 13 ++- src/test/ui/issues/issue-72690.rs | 62 +++++++++++++ src/test/ui/issues/issue-72690.stderr | 88 +++++++++++++++++++ 6 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/issues/issue-72690.rs create mode 100644 src/test/ui/issues/issue-72690.stderr diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index dfc7177921d31..355d5048d52a7 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -88,6 +88,17 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { if let (None, Some(ty)) = (self.found_local_pattern, self.node_ty_contains_target(local.hir_id)) { + // There's a trade-off here - we can either check that our target span + // is contained in `local.span` or not. If we choose to check containment + // we can avoid some spurious suggestions (see #72690), but we lose + // the ability to report on things like: + // + // ``` + // let x = vec![]; + // ``` + // + // because the target span will be in the macro expansion of `vec![]`. + // At present we choose not to check containment. self.found_local_pattern = Some(&*local.pat); self.found_node_ty = Some(ty); } @@ -99,8 +110,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { if let (None, Some(ty)) = (self.found_arg_pattern, self.node_ty_contains_target(param.hir_id)) { - self.found_arg_pattern = Some(&*param.pat); - self.found_node_ty = Some(ty); + if self.target_span.contains(param.pat.span) { + self.found_arg_pattern = Some(&*param.pat); + self.found_node_ty = Some(ty); + } } } intravisit::walk_body(self, body); diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr index 2005bd4dd5ca7..0c6d11cd3211d 100644 --- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr +++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed - --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 + --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:5 | LL | with_closure(|x: u32, y| {}); - | ^ consider giving this closure parameter a type + | ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23046.rs b/src/test/ui/issues/issue-23046.rs index a68369616d8b6..75be4a11efd22 100644 --- a/src/test/ui/issues/issue-23046.rs +++ b/src/test/ui/issues/issue-23046.rs @@ -14,7 +14,7 @@ pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = |x| { //~ ERROR type annotations needed - let_(add(x,x), |y| { + let ex = |x| { + let_(add(x,x), |y| { //~ ERROR type annotations needed let_(add(x, x), |x|x)})}; } diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr index 12b2eb48e7eaa..77555fce7c460 100644 --- a/src/test/ui/issues/issue-23046.stderr +++ b/src/test/ui/issues/issue-23046.stderr @@ -1,8 +1,13 @@ -error[E0282]: type annotations needed for `Expr<'_, VAR>` - --> $DIR/issue-23046.rs:17:15 +error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>` + --> $DIR/issue-23046.rs:18:9 | -LL | let ex = |x| { - | ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified +LL | let_(add(x,x), |y| { + | ^^^^ cannot infer type for type parameter `VAR` declared on the function `let_` + | +help: give this closure an explicit return type without `_` placeholders + | +LL | let_(add(x, x), |x|-> Expr<'_, _> { x })})}; + | ^^^^^^^^^^^^^^^^ ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs new file mode 100644 index 0000000000000..4edbd9ca15de7 --- /dev/null +++ b/src/test/ui/issues/issue-72690.rs @@ -0,0 +1,62 @@ +fn no_err() { + |x: String| x; + let _ = String::from("x"); +} + +fn err() { + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn arg_pat_closure_err() { + |x| String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn local_pat_closure_err() { + let _ = "x".as_ref(); //~ ERROR type annotations needed +} + +fn err_first_arg_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + |x: String| x; +} + +fn err_second_arg_pat() { + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn err_mid_arg_pat() { + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; +} + +fn err_first_local_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + let _ = String::from("x"); +} + +fn err_second_local_pat() { + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed +} + +fn err_mid_local_pat() { + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); +} + +fn main() {} diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr new file mode 100644 index 0000000000000..64e78ddf60474 --- /dev/null +++ b/src/test/ui/issues/issue-72690.stderr @@ -0,0 +1,88 @@ +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:7:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0282]: type annotations needed + --> $DIR/issue-72690.rs:11:6 + | +LL | |x| String::from("x".as_ref()); + | ^ consider giving this closure parameter a type + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:15:17 + | +LL | let _ = "x".as_ref(); + | ^^^^^^ cannot infer type for type `str` + | + = note: cannot satisfy `str: std::convert::AsRef<_>` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:19:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:25:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:33:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:41:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` +LL | let _ = String::from("x"); + | - consider giving this pattern a type + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:47:5 + | +LL | let _ = String::from("x"); + | - consider giving this pattern a type +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error[E0283]: type annotations needed for `std::string::String` + --> $DIR/issue-72690.rs:55:5 + | +LL | let _ = String::from("x"); + | - consider giving this pattern a type +... +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for struct `std::string::String` + | + = note: cannot satisfy `std::string::String: std::convert::From<&_>` + = note: required by `std::convert::From::from` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. From b4ddd9183103586ba1456241b9c117a420bb6d6b Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Fri, 5 Jun 2020 12:44:56 +0100 Subject: [PATCH 2/2] Add FIXME to comment regarding local patterns Co-authored-by: Bastian Kauschke --- src/librustc_infer/infer/error_reporting/need_type_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index 355d5048d52a7..e097deca33b46 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -88,7 +88,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { if let (None, Some(ty)) = (self.found_local_pattern, self.node_ty_contains_target(local.hir_id)) { - // There's a trade-off here - we can either check that our target span + // FIXME: There's a trade-off here - we can either check that our target span // is contained in `local.span` or not. If we choose to check containment // we can avoid some spurious suggestions (see #72690), but we lose // the ability to report on things like: