diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 00403ff044c4..f73eca5bf612 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> { if let Term::Ty(ty) = self { Some(*ty) } else { None } } + pub fn ct(&self) -> Option> { 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 00b4d0857ac2..3201ea1e2715 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 421c86ee51a5..e324c1e799f9 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 02dce4f7a97e..41afaec86b6e 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: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual: True, - | ^^^^ cannot infer type for struct `IsLessOrEqual` + | ^^^^ | = note: cannot satisfy `IsLessOrEqual: True` -error[E0283]: type annotations needed +error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual: True` --> $DIR/issue-72787.rs:21:26 | LL | IsLessOrEqual: True, - | ^^^^ cannot infer type for struct `IsLessOrEqual` + | ^^^^ | = note: cannot satisfy `IsLessOrEqual: 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 77ad57f0640f..c651bf1c8de9 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; impl S where IsLessOrEqual: True, -//[min]~^ Error type annotations needed [E0283] -//[min]~| Error type annotations needed [E0283] +//[min]~^ Error type annotations needed +//[min]~| Error type annotations needed IsLessOrEqual: 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 30cb7a1df807..8d6b81c24b68 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 == ::S` +error[E0284]: type annotations needed --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); - | ^^^^^^^^^^^^ cannot satisfy `<_ as StreamHasher>::S == ::S` + | ^^^^^^^^^^^^ + | + = note: cannot satisfy `<_ as StreamHasher>::S == ::S` +help: try using a fully qualified path to specify the expected types + | +LL | >::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 dfabde9abc97..4e010a13653e 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 fa59da852f90..8f3b2ac73199 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 9c71ecffa268..193de1a35cf1 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 `>::Array == [u8; 3]` +error[E0284]: type annotations needed --> $DIR/issue-69683.rs:30:10 | LL | 0u16.foo(b); - | ^^^ cannot satisfy `>::Array == [u8; 3]` + | ^^^ + | + = note: cannot satisfy `>::Array == [u8; 3]` +help: try using a fully qualified path to specify the expected types + | +LL | >::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 1c216e649829..6ddb7657301c 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 `>::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 `>::Output == u64` + | - ^^^^ + | | + | type must be known at this point + | + = note: cannot satisfy `>::Output == u64` +help: try using a fully qualified path to specify the expected types + | +LL | d = d % >::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 1b97f8d818a4..5832c4d173c1 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 2eeab801e3d9..6631fe987e27 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 16e874ee21e6..fb387a9c9096 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 33b12ef09ec2..fa280135beb2 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 6d1e490bcf33..75feb5698eb6 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`