about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-06-25 10:42:23 -0700
committerMichael Goulet <michael@errs.io>2022-07-01 17:38:34 +0000
commit12ab6bfafddac39c401fe418b9fa5dbda5ce7ceb (patch)
tree2924b6c726857542e87942db0360b434076ca7b0
parentca0105ba4e3c846f3d3e25705a401db949c8dd40 (diff)
Don't point at Self type if we can't find an infer variable in ambiguous trait predicate
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs63
-rw-r--r--src/test/ui/coherence/coherence-overlap-trait-alias.stderr4
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-72787.rs4
-rw-r--r--src/test/ui/issues/issue-12028.stderr10
-rw-r--r--src/test/ui/issues/issue-21974.stderr4
-rw-r--r--src/test/ui/issues/issue-24424.stderr4
-rw-r--r--src/test/ui/issues/issue-69683.stderr10
-rw-r--r--src/test/ui/issues/issue-71584.stderr14
-rw-r--r--src/test/ui/lifetimes/issue-34979.stderr4
-rw-r--r--src/test/ui/marker_trait_attr/region-overlap.stderr8
-rw-r--r--src/test/ui/traits/issue-85735.rs2
-rw-r--r--src/test/ui/traits/issue-85735.stderr4
-rw-r--r--src/test/ui/type/type-check/issue-40294.stderr4
15 files changed, 94 insertions, 57 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 00403ff044c..f73eca5bf61 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -914,9 +914,17 @@ impl<'tcx> Term<'tcx> {
     pub fn ty(&self) -> Option<Ty<'tcx>> {
         if let Term::Ty(ty) = self { Some(*ty) } else { None }
     }
+
     pub fn ct(&self) -> Option<Const<'tcx>> {
         if let Term::Const(c) = self { Some(*c) } else { None }
     }
+
+    pub fn into_arg(self) -> GenericArg<'tcx> {
+        match self {
+            Term::Ty(ty) => ty.into(),
+            Term::Const(c) => c.into(),
+        }
+    }
 }
 
 /// This kind of predicate has no *direct* correspondent in the
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 00b4d0857ac..3201ea1e271 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1970,13 +1970,31 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
 
                 // 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])
+                // a more general error.
+                let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
+
+                let mut err = if let Some(subst) = subst {
+                    let impl_candidates = self
+                        .find_similar_impl_candidates(trait_ref)
+                        .into_iter()
+                        .map(|candidate| candidate.trait_ref)
+                        .collect();
+                    self.emit_inference_failure_err(
+                        body_id,
+                        span,
+                        subst,
+                        impl_candidates,
+                        ErrorCode::E0283,
+                        true,
+                    )
+                } else {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        span,
+                        E0283,
+                        "type annotations needed: cannot satisfy `{}`",
+                        predicate,
+                    )
                 };
 
                 // This is kind of a hack: it frequently happens that some earlier
@@ -1999,30 +2017,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                         self.emit_inference_failure_err(
                             body_id,
                             span,
-                            subst,
+                            trait_ref.self_ty().skip_binder().into(),
                             vec![],
                             ErrorCode::E0282,
                             false,
                         )
                         .emit();
                     }
+                    err.cancel();
                     return;
                 }
 
-                let impl_candidates = self
-                    .find_similar_impl_candidates(trait_ref)
-                    .into_iter()
-                    .map(|candidate| candidate.trait_ref)
-                    .collect();
-                let mut err = self.emit_inference_failure_err(
-                    body_id,
-                    span,
-                    subst,
-                    impl_candidates,
-                    ErrorCode::E0283,
-                    true,
-                );
-
                 let obligation = Obligation::new(
                     obligation.cause.clone(),
                     obligation.param_env,
@@ -2136,17 +2141,20 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 )
             }
             ty::PredicateKind::Projection(data) => {
-                let self_ty = data.projection_ty.self_ty();
-                let term = data.term;
                 if predicate.references_error() || self.is_tainted_by_errors() {
                     return;
                 }
-                if self_ty.needs_infer() && term.needs_infer() {
-                    // We do this for the `foo.collect()?` case to produce a suggestion.
+                let subst = data
+                    .projection_ty
+                    .substs
+                    .iter()
+                    .chain(Some(data.term.into_arg()))
+                    .find(|g| g.has_infer_types_or_consts());
+                if let Some(subst) = subst {
                     let mut err = self.emit_inference_failure_err(
                         body_id,
                         span,
-                        self_ty.into(),
+                        subst,
                         vec![],
                         ErrorCode::E0284,
                         true,
@@ -2154,6 +2162,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     err.note(&format!("cannot satisfy `{}`", predicate));
                     err
                 } else {
+                    // If we can't find a substitution, just print a generic error
                     let mut err = struct_span_err!(
                         self.tcx.sess,
                         span,
diff --git a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
index 421c86ee51a..e324c1e799f 100644
--- a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
+++ b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `u32: C`
   --> $DIR/coherence-overlap-trait-alias.rs:15:6
    |
 LL | impl C for u32 {}
-   |      ^ cannot infer type for type `u32`
+   |      ^
    |
 note: multiple `impl`s satisfying `u32: C` found
   --> $DIR/coherence-overlap-trait-alias.rs:14:1
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
index 02dce4f7a97..41afaec86b6 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
@@ -34,19 +34,19 @@ LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
    = help: const parameters may only be used as standalone arguments, i.e. `J`
    = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
   --> $DIR/issue-72787.rs:21:26
    |
 LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
+   |                          ^^^^
    |
    = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
 
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
   --> $DIR/issue-72787.rs:21:26
    |
 LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
+   |                          ^^^^
    |
    = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs
index 77ad57f0640..c651bf1c8de 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs
@@ -19,8 +19,8 @@ struct S<const I: u32, const J: u32>;
 impl<const I: u32, const J: u32> S<I, J>
 where
     IsLessOrEqual<I, 8>: True,
-//[min]~^ Error type annotations needed [E0283]
-//[min]~| Error type annotations needed [E0283]
+//[min]~^ Error type annotations needed
+//[min]~| Error type annotations needed
     IsLessOrEqual<J, 8>: True,
     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
 //[min]~^ Error generic parameters may not be used in const operations
diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr
index 30cb7a1df80..8d6b81c24b6 100644
--- a/src/test/ui/issues/issue-12028.stderr
+++ b/src/test/ui/issues/issue-12028.stderr
@@ -1,8 +1,14 @@
-error[E0284]: type annotations needed: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+error[E0284]: type annotations needed
   --> $DIR/issue-12028.rs:27:14
    |
 LL |         self.input_stream(&mut stream);
-   |              ^^^^^^^^^^^^ cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+   |              ^^^^^^^^^^^^
+   |
+   = note: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |         <u8 as StreamHash<H>>::input_stream(self, &mut stream);
+   |         ++++++++++++++++++++++++++++++++++++    ~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr
index dfabde9abc9..4e010a13653 100644
--- a/src/test/ui/issues/issue-21974.stderr
+++ b/src/test/ui/issues/issue-21974.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
   --> $DIR/issue-21974.rs:11:19
    |
 LL |     where &'a T : Foo,
-   |                   ^^^ cannot infer type for reference `&'a T`
+   |                   ^^^
    |
    = note: cannot satisfy `&'a T: Foo`
 
diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr
index fa59da852f9..8f3b2ac7319 100644
--- a/src/test/ui/issues/issue-24424.stderr
+++ b/src/test/ui/issues/issue-24424.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>`
   --> $DIR/issue-24424.rs:4:57
    |
 LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
-   |                                                         ^^^^^^^^^^^ cannot infer type for type parameter `T0`
+   |                                                         ^^^^^^^^^^^
    |
    = note: cannot satisfy `T0: Trait0<'l0>`
 
diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr
index 9c71ecffa26..193de1a35cf 100644
--- a/src/test/ui/issues/issue-69683.stderr
+++ b/src/test/ui/issues/issue-69683.stderr
@@ -1,8 +1,14 @@
-error[E0284]: type annotations needed: cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
+error[E0284]: type annotations needed
   --> $DIR/issue-69683.rs:30:10
    |
 LL |     0u16.foo(b);
-   |          ^^^ cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
+   |          ^^^
+   |
+   = note: cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     <u16 as Foo<I>>::foo(0u16, b);
+   |     +++++++++++++++++++++    ~
 
 error[E0283]: type annotations needed
   --> $DIR/issue-69683.rs:30:10
diff --git a/src/test/ui/issues/issue-71584.stderr b/src/test/ui/issues/issue-71584.stderr
index 1c216e64982..6ddb7657301 100644
--- a/src/test/ui/issues/issue-71584.stderr
+++ b/src/test/ui/issues/issue-71584.stderr
@@ -1,8 +1,16 @@
-error[E0284]: type annotations needed: cannot satisfy `<u64 as Rem<_>>::Output == u64`
-  --> $DIR/issue-71584.rs:4:11
+error[E0284]: type annotations needed
+  --> $DIR/issue-71584.rs:4:15
    |
 LL |     d = d % n.into();
-   |           ^ cannot satisfy `<u64 as Rem<_>>::Output == u64`
+   |           -   ^^^^
+   |           |
+   |           type must be known at this point
+   |
+   = note: cannot satisfy `<u64 as Rem<_>>::Output == u64`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |     d = d % <u32 as Into<T>>::into(n);
+   |             +++++++++++++++++++++++ ~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/issue-34979.stderr b/src/test/ui/lifetimes/issue-34979.stderr
index 1b97f8d818a..5832c4d173c 100644
--- a/src/test/ui/lifetimes/issue-34979.stderr
+++ b/src/test/ui/lifetimes/issue-34979.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
   --> $DIR/issue-34979.rs:6:13
    |
 LL |     &'a (): Foo,
-   |             ^^^ cannot infer type for reference `&'a ()`
+   |             ^^^
    |
    = note: cannot satisfy `&'a (): Foo`
 
diff --git a/src/test/ui/marker_trait_attr/region-overlap.stderr b/src/test/ui/marker_trait_attr/region-overlap.stderr
index 2eeab801e3d..6631fe987e2 100644
--- a/src/test/ui/marker_trait_attr/region-overlap.stderr
+++ b/src/test/ui/marker_trait_attr/region-overlap.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `(&'static (), &'a ()): A`
   --> $DIR/region-overlap.rs:5:10
    |
 LL | impl<'a> A for (&'static (), &'a ()) {}
-   |          ^ cannot infer type for tuple `(&'static (), &'a ())`
+   |          ^
    |
 note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found
   --> $DIR/region-overlap.rs:5:1
@@ -12,11 +12,11 @@ LL | impl<'a> A for (&'static (), &'a ()) {}
 LL | impl<'a> A for (&'a (), &'static ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `(&'a (), &'static ()): A`
   --> $DIR/region-overlap.rs:6:10
    |
 LL | impl<'a> A for (&'a (), &'static ()) {}
-   |          ^ cannot infer type for tuple `(&'a (), &'static ())`
+   |          ^
    |
 note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found
   --> $DIR/region-overlap.rs:5:1
diff --git a/src/test/ui/traits/issue-85735.rs b/src/test/ui/traits/issue-85735.rs
index 16e874ee21e..fb387a9c909 100644
--- a/src/test/ui/traits/issue-85735.rs
+++ b/src/test/ui/traits/issue-85735.rs
@@ -5,7 +5,7 @@ trait Foo {}
 impl<'a, 'b, T> Foo for T
 where
     T: FnMut(&'a ()),
-    //~^ ERROR: type annotations needed [E0283]
+    //~^ ERROR: type annotations needed
     T: FnMut(&'b ()),
 {
 }
diff --git a/src/test/ui/traits/issue-85735.stderr b/src/test/ui/traits/issue-85735.stderr
index 33b12ef09ec..fa280135beb 100644
--- a/src/test/ui/traits/issue-85735.stderr
+++ b/src/test/ui/traits/issue-85735.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>`
   --> $DIR/issue-85735.rs:7:8
    |
 LL |     T: FnMut(&'a ()),
-   |        ^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+   |        ^^^^^^^^^^^^^
    |
    = note: cannot satisfy `T: FnMut<(&'a (),)>`
 
diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr
index 6d1e490bcf3..75feb5698eb 100644
--- a/src/test/ui/type/type-check/issue-40294.stderr
+++ b/src/test/ui/type/type-check/issue-40294.stderr
@@ -1,8 +1,8 @@
-error[E0283]: type annotations needed
+error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
   --> $DIR/issue-40294.rs:6:19
    |
 LL |     where &'a T : Foo,
-   |                   ^^^ cannot infer type for reference `&'a T`
+   |                   ^^^
    |
    = note: cannot satisfy `&'a T: Foo`