From 71ca239f8019755eb67a255fbf73450bae8ad4c2 Mon Sep 17 00:00:00 2001 From: SNCPlay42 Date: Mon, 19 Oct 2020 17:42:57 +0100 Subject: [PATCH 1/2] don't assume trait ambiguity happens in `Self` --- .../src/traits/error_reporting/mod.rs | 30 ++++++------- src/test/ui/issues/issue-72690.stderr | 33 ++++++-------- src/test/ui/traits/issue-77982.rs | 40 +++++++++++++++++ src/test/ui/traits/issue-77982.stderr | 44 +++++++++++++++++++ 4 files changed, 113 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/traits/issue-77982.rs create mode 100644 src/test/ui/traits/issue-77982.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f53465266d2ac..f8bd3ab96e254 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1462,9 +1462,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let bound_predicate = predicate.bound_atom(); let mut err = match bound_predicate.skip_binder() { ty::PredicateAtom::Trait(data, _) => { - let self_ty = data.trait_ref.self_ty(); let trait_ref = bound_predicate.rebind(data.trait_ref); - debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind(), trait_ref); + debug!("trait_ref {:?}", trait_ref); if predicate.references_error() { return; @@ -1479,6 +1478,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // known, since we don't dispatch based on region // relationships. + // Pick the first substitution that still contains inference variables as the one + // we're going to emit an error for. If there are none (see above), fall back to + // the substitution for `Self`. + let subst = { + let substs = data.trait_ref.substs; + substs + .iter() + .find(|s| s.has_infer_types_or_consts()) + .unwrap_or_else(|| substs[0]) + }; + // This is kind of a hack: it frequently happens that some earlier // error prevents types from being fully inferred, and then we get // a bunch of uninteresting errors saying something like " InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - self.emit_inference_failure_err( - body_id, - span, - self_ty.into(), - ErrorCode::E0282, - ) - .emit(); + self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0282).emit(); return; } - let mut err = self.emit_inference_failure_err( - body_id, - span, - self_ty.into(), - ErrorCode::E0283, - ); + let mut err = + self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283); err.note(&format!("cannot satisfy `{}`", predicate)); if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index feb1316357e5c..3443cca5f3270 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:7:5 | LL | String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for struct `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` @@ -13,11 +13,13 @@ error[E0282]: type annotations needed LL | |x| String::from("x".as_ref()); | ^ consider giving this closure parameter a type -error[E0283]: type annotations needed +error[E0283]: type annotations needed for `&T` --> $DIR/issue-72690.rs:15:17 | LL | let _ = "x".as_ref(); - | ^^^^^^ cannot infer type for type `str` + | - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef` + | | + | consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified | = note: cannot satisfy `str: AsRef<_>` @@ -25,7 +27,7 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:19:5 | LL | String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for struct `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` @@ -34,7 +36,7 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:25:5 | LL | String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for struct `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` @@ -43,41 +45,34 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:33:5 | LL | String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for struct `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` -error[E0283]: type annotations needed for `String` +error[E0283]: type annotations needed --> $DIR/issue-72690.rs:41:5 | LL | String::from("x".as_ref()); - | ^^^^^^^^^^^^ cannot infer type for struct `String` -LL | let _ = String::from("x"); - | - consider giving this pattern a type + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` -error[E0283]: type annotations needed for `String` +error[E0283]: type annotations needed --> $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 `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` -error[E0283]: type annotations needed for `String` +error[E0283]: type annotations needed --> $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 `String` + | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` = note: required by `from` diff --git a/src/test/ui/traits/issue-77982.rs b/src/test/ui/traits/issue-77982.rs new file mode 100644 index 0000000000000..03d4fe23cc5bc --- /dev/null +++ b/src/test/ui/traits/issue-77982.rs @@ -0,0 +1,40 @@ +use std::collections::HashMap; + +fn what() { + let descr = String::new(); + let mut opts = HashMap::::new(); + let opt = String::new(); + + opts.get(opt.as_ref()); //~ ERROR type annotations needed +} + +fn main() { + let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + //~^ ERROR type annotations needed +} + +trait Foo<'a, T: ?Sized> { + fn foo(&self) -> Box { + todo!() + } +} + +trait Bar<'a, T: ?Sized> { + fn bar(&self) -> Box { + todo!() + } +} + +impl Foo<'static, u32> for () {} +impl<'a> Foo<'a, i16> for () {} + +impl<'a> Bar<'static, u32> for &'a () {} +impl<'a> Bar<'a, i16> for &'a () {} + +fn foo() { + let _ = ().foo(); //~ ERROR type annotations needed +} + +fn bar() { + let _ = (&()).bar(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr new file mode 100644 index 0000000000000..d788f1871ffac --- /dev/null +++ b/src/test/ui/traits/issue-77982.stderr @@ -0,0 +1,44 @@ +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:8:10 + | +LL | opts.get(opt.as_ref()); + | ^^^ ------------ this method call resolves to `&T` + | | + | cannot infer type for type parameter `Q` declared on the associated function `get` + | + = note: cannot satisfy `String: Borrow<_>` + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:12:44 + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + | ^^^^^^^^^ ----------- this method call resolves to `T` + | | + | cannot infer type for type parameter `T` declared on the trait `From` + | + = note: cannot satisfy `u32: From<_>` + = note: required by `from` + +error[E0283]: type annotations needed for `Box` + --> $DIR/issue-77982.rs:35:16 + | +LL | let _ = ().foo(); + | - ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` + | | + | consider giving this pattern the explicit type `Box`, where the type parameter `T` is specified + | + = note: cannot satisfy `(): Foo<'_, _>` + +error[E0283]: type annotations needed for `Box` + --> $DIR/issue-77982.rs:39:19 + | +LL | let _ = (&()).bar(); + | - ^^^ cannot infer type for type parameter `T` declared on the trait `Bar` + | | + | consider giving this pattern the explicit type `Box`, where the type parameter `T` is specified + | + = note: cannot satisfy `&(): Bar<'_, _>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0283`. From c146e8c54fa0b99defd1ba77ad4d6505c491f4f3 Mon Sep 17 00:00:00 2001 From: SNCPlay42 Date: Mon, 19 Oct 2020 17:58:44 +0100 Subject: [PATCH 2/2] revert workaround #73027 --- .../src/infer/error_reporting/need_type_info.rs | 17 ++--------------- ...nfer-vars-supply-ty-with-bound-region.stderr | 4 ++-- src/test/ui/issues/issue-23046.rs | 4 ++-- src/test/ui/issues/issue-23046.stderr | 13 ++++--------- 4 files changed, 10 insertions(+), 28 deletions(-) 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 2f3089f1a92c1..21023a06bb2d9 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 @@ -91,17 +91,6 @@ 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)) { - // 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: - // - // ``` - // 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); } @@ -113,10 +102,8 @@ 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)) { - if self.target_span.contains(param.pat.span) { - self.found_arg_pattern = Some(&*param.pat); - self.found_node_ty = Some(ty); - } + 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 0c6d11cd3211d..2005bd4dd5ca7 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:5 + --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 | LL | with_closure(|x: u32, y| {}); - | ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure` + | ^ consider giving this closure parameter a type 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 75be4a11efd22..a68369616d8b6 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| { - let_(add(x,x), |y| { //~ ERROR type annotations needed + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { 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 77555fce7c460..12b2eb48e7eaa 100644 --- a/src/test/ui/issues/issue-23046.stderr +++ b/src/test/ui/issues/issue-23046.stderr @@ -1,13 +1,8 @@ -error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>` - --> $DIR/issue-23046.rs:18:9 +error[E0282]: type annotations needed for `Expr<'_, VAR>` + --> $DIR/issue-23046.rs:17:15 | -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 })})}; - | ^^^^^^^^^^^^^^^^ ^ +LL | let ex = |x| { + | ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified error: aborting due to previous error