From 71ca239f8019755eb67a255fbf73450bae8ad4c2 Mon Sep 17 00:00:00 2001 From: SNCPlay42 Date: Mon, 19 Oct 2020 17:42:57 +0100 Subject: [PATCH] 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 f53465266d2..f8bd3ab96e2 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 @@ fn maybe_report_ambiguity( 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 @@ fn maybe_report_ambiguity( // 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 " $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 00000000000..03d4fe23cc5 --- /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 00000000000..d788f1871ff --- /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`.