@@ -67,6 +67,7 @@ pub enum CandidateSimilarity {
67
67
pub struct ImplCandidate < ' tcx > {
68
68
pub trait_ref : ty:: TraitRef < ' tcx > ,
69
69
pub similarity : CandidateSimilarity ,
70
+ impl_def_id : DefId ,
70
71
}
71
72
72
73
enum GetSafeTransmuteErrorAndReason {
@@ -1331,6 +1332,7 @@ trait InferCtxtPrivExt<'tcx> {
1331
1332
body_def_id : LocalDefId ,
1332
1333
err : & mut Diagnostic ,
1333
1334
other : bool ,
1335
+ param_env : ty:: ParamEnv < ' tcx > ,
1334
1336
) -> bool ;
1335
1337
1336
1338
fn report_similar_impl_candidates_for_root_obligation (
@@ -1918,8 +1920,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1918
1920
1919
1921
let imp = self . tcx . impl_trait_ref ( def_id) . unwrap ( ) . skip_binder ( ) ;
1920
1922
1921
- self . fuzzy_match_tys ( trait_pred. skip_binder ( ) . self_ty ( ) , imp. self_ty ( ) , false )
1922
- . map ( |similarity| ImplCandidate { trait_ref : imp, similarity } )
1923
+ self . fuzzy_match_tys ( trait_pred. skip_binder ( ) . self_ty ( ) , imp. self_ty ( ) , false ) . map (
1924
+ |similarity| ImplCandidate { trait_ref : imp, similarity, impl_def_id : def_id } ,
1925
+ )
1923
1926
} )
1924
1927
. collect ( ) ;
1925
1928
if candidates. iter ( ) . any ( |c| matches ! ( c. similarity, CandidateSimilarity :: Exact { .. } ) ) {
@@ -1938,7 +1941,71 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1938
1941
body_def_id : LocalDefId ,
1939
1942
err : & mut Diagnostic ,
1940
1943
other : bool ,
1944
+ param_env : ty:: ParamEnv < ' tcx > ,
1941
1945
) -> bool {
1946
+ if let [ single] = & impl_candidates {
1947
+ if self . probe ( |_| {
1948
+ let ocx = ObligationCtxt :: new ( self ) ;
1949
+ let obligation_trait_ref = self . instantiate_binder_with_placeholders ( trait_ref) ;
1950
+ let impl_args = self . fresh_args_for_item ( DUMMY_SP , single. impl_def_id ) ;
1951
+ let impl_trait_ref = ocx. normalize (
1952
+ & ObligationCause :: dummy ( ) ,
1953
+ param_env,
1954
+ ty:: EarlyBinder :: bind ( single. trait_ref ) . instantiate ( self . tcx , impl_args) ,
1955
+ ) ;
1956
+
1957
+ ocx. register_obligations (
1958
+ self . tcx
1959
+ . predicates_of ( single. impl_def_id )
1960
+ . instantiate ( self . tcx , impl_args)
1961
+ . into_iter ( )
1962
+ . map ( |( clause, _) | {
1963
+ Obligation :: new ( self . tcx , ObligationCause :: dummy ( ) , param_env, clause)
1964
+ } ) ,
1965
+ ) ;
1966
+ if !ocx. select_where_possible ( ) . is_empty ( ) {
1967
+ return false ;
1968
+ }
1969
+
1970
+ let mut terrs = vec ! [ ] ;
1971
+ for ( obligation_arg, impl_arg) in
1972
+ std:: iter:: zip ( obligation_trait_ref. args , impl_trait_ref. args )
1973
+ {
1974
+ if let Err ( terr) =
1975
+ ocx. eq ( & ObligationCause :: dummy ( ) , param_env, obligation_arg, impl_arg)
1976
+ {
1977
+ terrs. push ( terr) ;
1978
+ }
1979
+ if !ocx. select_where_possible ( ) . is_empty ( ) {
1980
+ return false ;
1981
+ }
1982
+ }
1983
+
1984
+ // Literally nothing unified, just give up.
1985
+ if terrs. len ( ) == impl_trait_ref. args . len ( ) {
1986
+ return false ;
1987
+ }
1988
+
1989
+ let cand =
1990
+ self . resolve_vars_if_possible ( impl_trait_ref) . fold_with ( & mut BottomUpFolder {
1991
+ tcx : self . tcx ,
1992
+ ty_op : |ty| ty,
1993
+ lt_op : |lt| lt,
1994
+ ct_op : |ct| ct. normalize ( self . tcx , ty:: ParamEnv :: empty ( ) ) ,
1995
+ } ) ;
1996
+ err. highlighted_help ( vec ! [
1997
+ ( format!( "the trait `{}` " , cand. print_only_trait_path( ) ) , Style :: NoStyle ) ,
1998
+ ( "is" . to_string( ) , Style :: Highlight ) ,
1999
+ ( " implemented for `" . to_string( ) , Style :: NoStyle ) ,
2000
+ ( cand. self_ty( ) . to_string( ) , Style :: Highlight ) ,
2001
+ ( "`" . to_string( ) , Style :: NoStyle ) ,
2002
+ ] ) ;
2003
+ true
2004
+ } ) {
2005
+ return true ;
2006
+ }
2007
+ }
2008
+
1942
2009
let other = if other { "other " } else { "" } ;
1943
2010
let report = |candidates : Vec < TraitRef < ' tcx > > , err : & mut Diagnostic | {
1944
2011
if candidates. is_empty ( ) {
@@ -2062,9 +2129,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2062
2129
} )
2063
2130
. collect ( ) ;
2064
2131
impl_candidates. sort_by_key ( |cand| ( cand. similarity , cand. trait_ref ) ) ;
2132
+ let mut impl_candidates: Vec < _ > =
2133
+ impl_candidates. into_iter ( ) . map ( |cand| cand. trait_ref ) . collect ( ) ;
2065
2134
impl_candidates. dedup ( ) ;
2066
2135
2067
- report ( impl_candidates. into_iter ( ) . map ( |cand| cand . trait_ref ) . collect ( ) , err)
2136
+ report ( impl_candidates, err)
2068
2137
}
2069
2138
2070
2139
fn report_similar_impl_candidates_for_root_obligation (
@@ -2108,6 +2177,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2108
2177
body_def_id,
2109
2178
err,
2110
2179
true ,
2180
+ obligation. param_env ,
2111
2181
) ;
2112
2182
}
2113
2183
}
@@ -2316,6 +2386,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
2316
2386
obligation. cause . body_id ,
2317
2387
& mut err,
2318
2388
false ,
2389
+ obligation. param_env ,
2319
2390
) ;
2320
2391
}
2321
2392
}
@@ -3051,6 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3051
3122
body_def_id,
3052
3123
err,
3053
3124
true ,
3125
+ obligation. param_env ,
3054
3126
) {
3055
3127
self . report_similar_impl_candidates_for_root_obligation (
3056
3128
& obligation,
0 commit comments