@@ -67,6 +67,7 @@ pub enum CandidateSimilarity {
6767pub struct ImplCandidate < ' tcx > {
6868 pub trait_ref : ty:: TraitRef < ' tcx > ,
6969 pub similarity : CandidateSimilarity ,
70+ impl_def_id : DefId ,
7071}
7172
7273enum GetSafeTransmuteErrorAndReason {
@@ -1328,6 +1329,7 @@ trait InferCtxtPrivExt<'tcx> {
13281329 body_def_id : LocalDefId ,
13291330 err : & mut Diagnostic ,
13301331 other : bool ,
1332+ param_env : ty:: ParamEnv < ' tcx > ,
13311333 ) -> bool ;
13321334
13331335 fn report_similar_impl_candidates_for_root_obligation (
@@ -1916,8 +1918,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19161918
19171919 let imp = self . tcx . impl_trait_ref ( def_id) . unwrap ( ) . skip_binder ( ) ;
19181920
1919- self . fuzzy_match_tys ( trait_pred. skip_binder ( ) . self_ty ( ) , imp. self_ty ( ) , false )
1920- . map ( |similarity| ImplCandidate { trait_ref : imp, similarity } )
1921+ self . fuzzy_match_tys ( trait_pred. skip_binder ( ) . self_ty ( ) , imp. self_ty ( ) , false ) . map (
1922+ |similarity| ImplCandidate { trait_ref : imp, similarity, impl_def_id : def_id } ,
1923+ )
19211924 } )
19221925 . collect ( ) ;
19231926 if candidates. iter ( ) . any ( |c| matches ! ( c. similarity, CandidateSimilarity :: Exact { .. } ) ) {
@@ -1936,7 +1939,71 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19361939 body_def_id : LocalDefId ,
19371940 err : & mut Diagnostic ,
19381941 other : bool ,
1942+ param_env : ty:: ParamEnv < ' tcx > ,
19391943 ) -> bool {
1944+ if let [ single] = & impl_candidates {
1945+ if self . probe ( |_| {
1946+ let ocx = ObligationCtxt :: new ( self ) ;
1947+ let obligation_trait_ref = self . instantiate_binder_with_placeholders ( trait_ref) ;
1948+ let impl_args = self . fresh_args_for_item ( DUMMY_SP , single. impl_def_id ) ;
1949+ let impl_trait_ref = ocx. normalize (
1950+ & ObligationCause :: dummy ( ) ,
1951+ param_env,
1952+ ty:: EarlyBinder :: bind ( single. trait_ref ) . instantiate ( self . tcx , impl_args) ,
1953+ ) ;
1954+
1955+ ocx. register_obligations (
1956+ self . tcx
1957+ . predicates_of ( single. impl_def_id )
1958+ . instantiate ( self . tcx , impl_args)
1959+ . into_iter ( )
1960+ . map ( |( clause, _) | {
1961+ Obligation :: new ( self . tcx , ObligationCause :: dummy ( ) , param_env, clause)
1962+ } ) ,
1963+ ) ;
1964+ if !ocx. select_where_possible ( ) . is_empty ( ) {
1965+ return false ;
1966+ }
1967+
1968+ let mut terrs = vec ! [ ] ;
1969+ for ( obligation_arg, impl_arg) in
1970+ std:: iter:: zip ( obligation_trait_ref. args , impl_trait_ref. args )
1971+ {
1972+ if let Err ( terr) =
1973+ ocx. eq ( & ObligationCause :: dummy ( ) , param_env, obligation_arg, impl_arg)
1974+ {
1975+ terrs. push ( terr) ;
1976+ }
1977+ if !ocx. select_where_possible ( ) . is_empty ( ) {
1978+ return false ;
1979+ }
1980+ }
1981+
1982+ // Literally nothing unified, just give up.
1983+ if terrs. len ( ) == impl_trait_ref. args . len ( ) {
1984+ return false ;
1985+ }
1986+
1987+ let cand =
1988+ self . resolve_vars_if_possible ( impl_trait_ref) . fold_with ( & mut BottomUpFolder {
1989+ tcx : self . tcx ,
1990+ ty_op : |ty| ty,
1991+ lt_op : |lt| lt,
1992+ ct_op : |ct| ct. eval ( self . tcx , ty:: ParamEnv :: empty ( ) ) ,
1993+ } ) ;
1994+ err. highlighted_help ( vec ! [
1995+ ( format!( "the trait `{}` " , cand. print_only_trait_path( ) ) , Style :: NoStyle ) ,
1996+ ( "is" . to_string( ) , Style :: Highlight ) ,
1997+ ( " implemented for `" . to_string( ) , Style :: NoStyle ) ,
1998+ ( cand. self_ty( ) . to_string( ) , Style :: Highlight ) ,
1999+ ( "`" . to_string( ) , Style :: NoStyle ) ,
2000+ ] ) ;
2001+ true
2002+ } ) {
2003+ return true ;
2004+ }
2005+ }
2006+
19402007 let other = if other { "other " } else { "" } ;
19412008 let report = |candidates : Vec < TraitRef < ' tcx > > , err : & mut Diagnostic | {
19422009 if candidates. is_empty ( ) {
@@ -2060,9 +2127,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
20602127 } )
20612128 . collect ( ) ;
20622129 impl_candidates. sort_by_key ( |cand| ( cand. similarity , cand. trait_ref ) ) ;
2130+ let mut impl_candidates: Vec < _ > =
2131+ impl_candidates. into_iter ( ) . map ( |cand| cand. trait_ref ) . collect ( ) ;
20632132 impl_candidates. dedup ( ) ;
20642133
2065- report ( impl_candidates. into_iter ( ) . map ( |cand| cand . trait_ref ) . collect ( ) , err)
2134+ report ( impl_candidates, err)
20662135 }
20672136
20682137 fn report_similar_impl_candidates_for_root_obligation (
@@ -2106,6 +2175,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
21062175 body_def_id,
21072176 err,
21082177 true ,
2178+ obligation. param_env ,
21092179 ) ;
21102180 }
21112181 }
@@ -2314,6 +2384,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23142384 obligation. cause . body_id ,
23152385 & mut err,
23162386 false ,
2387+ obligation. param_env ,
23172388 ) ;
23182389 }
23192390 }
@@ -3040,6 +3111,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30403111 body_def_id,
30413112 err,
30423113 true ,
3114+ obligation. param_env ,
30433115 ) {
30443116 self . report_similar_impl_candidates_for_root_obligation ( & obligation, * trait_predicate, body_def_id, err) ;
30453117 }
0 commit comments