about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSNCPlay42 <SNCPlay42@gmail.com>2020-10-19 17:42:57 +0100
committerSNCPlay42 <SNCPlay42@gmail.com>2020-10-19 21:11:40 +0100
commit71ca239f8019755eb67a255fbf73450bae8ad4c2 (patch)
tree401b3ec2705aff130d52000b043e4812cbc11e85
parentc38ddb8040edce1b05bc09a0e8439472e9f67623 (diff)
downloadrust-71ca239f8019755eb67a255fbf73450bae8ad4c2.tar.gz
rust-71ca239f8019755eb67a255fbf73450bae8ad4c2.zip
don't assume trait ambiguity happens in `Self`
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs30
-rw-r--r--src/test/ui/issues/issue-72690.stderr33
-rw-r--r--src/test/ui/traits/issue-77982.rs40
-rw-r--r--src/test/ui/traits/issue-77982.stderr44
4 files changed, 113 insertions, 34 deletions
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 @@ 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 "<generic
@@ -1495,21 +1505,11 @@ impl<'a, 'tcx> 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 feb1316357e..3443cca5f32 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 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::<String, ()>::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<T> {
+        todo!()
+    }
+}
+
+trait Bar<'a, T: ?Sized> {
+    fn bar(&self) -> Box<T> {
+        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<T>`
+  --> $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<T>`, where the type parameter `T` is specified
+   |
+   = note: cannot satisfy `(): Foo<'_, _>`
+
+error[E0283]: type annotations needed for `Box<T>`
+  --> $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<T>`, 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`.