@@ -1970,13 +1970,31 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
19701970
19711971 // Pick the first substitution that still contains inference variables as the one
19721972 // we're going to emit an error for. If there are none (see above), fall back to
1973- // the substitution for `Self`.
1974- let subst = {
1975- let substs = data. trait_ref . substs ;
1976- substs
1977- . iter ( )
1978- . find ( |s| s. has_infer_types_or_consts ( ) )
1979- . unwrap_or_else ( || substs[ 0 ] )
1973+ // a more general error.
1974+ let subst = data. trait_ref . substs . iter ( ) . find ( |s| s. has_infer_types_or_consts ( ) ) ;
1975+
1976+ let mut err = if let Some ( subst) = subst {
1977+ let impl_candidates = self
1978+ . find_similar_impl_candidates ( trait_ref)
1979+ . into_iter ( )
1980+ . map ( |candidate| candidate. trait_ref )
1981+ . collect ( ) ;
1982+ self . emit_inference_failure_err (
1983+ body_id,
1984+ span,
1985+ subst,
1986+ impl_candidates,
1987+ ErrorCode :: E0283 ,
1988+ true ,
1989+ )
1990+ } else {
1991+ struct_span_err ! (
1992+ self . tcx. sess,
1993+ span,
1994+ E0283 ,
1995+ "type annotations needed: cannot satisfy `{}`" ,
1996+ predicate,
1997+ )
19801998 } ;
19811999
19822000 // 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> {
19992017 self . emit_inference_failure_err (
20002018 body_id,
20012019 span,
2002- subst ,
2020+ trait_ref . self_ty ( ) . skip_binder ( ) . into ( ) ,
20032021 vec ! [ ] ,
20042022 ErrorCode :: E0282 ,
20052023 false ,
20062024 )
20072025 . emit ( ) ;
20082026 }
2027+ err. cancel ( ) ;
20092028 return ;
20102029 }
20112030
2012- let impl_candidates = self
2013- . find_similar_impl_candidates ( trait_ref)
2014- . into_iter ( )
2015- . map ( |candidate| candidate. trait_ref )
2016- . collect ( ) ;
2017- let mut err = self . emit_inference_failure_err (
2018- body_id,
2019- span,
2020- subst,
2021- impl_candidates,
2022- ErrorCode :: E0283 ,
2023- true ,
2024- ) ;
2025-
20262031 let obligation = Obligation :: new (
20272032 obligation. cause . clone ( ) ,
20282033 obligation. param_env ,
@@ -2136,24 +2141,28 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
21362141 )
21372142 }
21382143 ty:: PredicateKind :: Projection ( data) => {
2139- let self_ty = data. projection_ty . self_ty ( ) ;
2140- let term = data. term ;
21412144 if predicate. references_error ( ) || self . is_tainted_by_errors ( ) {
21422145 return ;
21432146 }
2144- if self_ty. needs_infer ( ) && term. needs_infer ( ) {
2145- // We do this for the `foo.collect()?` case to produce a suggestion.
2147+ let subst = data
2148+ . projection_ty
2149+ . substs
2150+ . iter ( )
2151+ . chain ( Some ( data. term . into_arg ( ) ) )
2152+ . find ( |g| g. has_infer_types_or_consts ( ) ) ;
2153+ if let Some ( subst) = subst {
21462154 let mut err = self . emit_inference_failure_err (
21472155 body_id,
21482156 span,
2149- self_ty . into ( ) ,
2157+ subst ,
21502158 vec ! [ ] ,
21512159 ErrorCode :: E0284 ,
21522160 true ,
21532161 ) ;
21542162 err. note ( & format ! ( "cannot satisfy `{}`" , predicate) ) ;
21552163 err
21562164 } else {
2165+ // If we can't find a substitution, just print a generic error
21572166 let mut err = struct_span_err ! (
21582167 self . tcx. sess,
21592168 span,
0 commit comments