@@ -2104,6 +2104,98 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
21042104                        ) ; 
21052105                    } 
21062106                } 
2107+ 
2108+                 if  let  ( Some ( body_id) ,  Some ( ty:: subst:: GenericArgKind :: Type ( _) ) )  =
2109+                     ( body_id,  subst. map ( |subst| subst. unpack ( ) ) ) 
2110+                 { 
2111+                     struct  FindExprBySpan < ' hir >  { 
2112+                         span :  Span , 
2113+                         result :  Option < & ' hir  hir:: Expr < ' hir > > , 
2114+                     } 
2115+ 
2116+                     impl < ' v >  hir:: intravisit:: Visitor < ' v >  for  FindExprBySpan < ' v >  { 
2117+                         fn  visit_expr ( & mut  self ,  ex :  & ' v  hir:: Expr < ' v > )  { 
2118+                             if  self . span  == ex. span  { 
2119+                                 self . result  = Some ( ex) ; 
2120+                             }  else  { 
2121+                                 hir:: intravisit:: walk_expr ( self ,  ex) ; 
2122+                             } 
2123+                         } 
2124+                     } 
2125+ 
2126+                     let  mut  expr_finder = FindExprBySpan  {  span,  result :  None  } ; 
2127+ 
2128+                     expr_finder. visit_expr ( & self . tcx . hir ( ) . body ( body_id) . value ) ; 
2129+ 
2130+                     if  let  Some ( hir:: Expr  { 
2131+                         kind :  hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None ,  path) ) ,  .. } 
2132+                     )  = expr_finder. result 
2133+                         && let  [ 
2134+                             .., 
2135+                             trait_path_segment @ hir:: PathSegment  { 
2136+                                 res :  Some ( rustc_hir:: def:: Res :: Def ( rustc_hir:: def:: DefKind :: Trait ,  trait_id) ) , 
2137+                                 ..
2138+                             } , 
2139+                             hir:: PathSegment  { 
2140+                                 ident :  assoc_item_name, 
2141+                                 res :  Some ( rustc_hir:: def:: Res :: Def ( _,  item_id) ) , 
2142+                                 ..
2143+                             } 
2144+                         ]  = path. segments 
2145+                         && data. trait_ref . def_id  == * trait_id
2146+                         && self . tcx . trait_of_item ( item_id)  == Some ( * trait_id) 
2147+                         && !self . is_tainted_by_errors ( ) 
2148+                     { 
2149+                         let  ( verb,  noun)  = match  self . tcx . associated_item ( item_id) . kind  { 
2150+                             ty:: AssocKind :: Const  => ( "refer to the" ,  "constant" ) , 
2151+                             ty:: AssocKind :: Fn  => ( "call" ,  "function" ) , 
2152+                             ty:: AssocKind :: Type  => ( "refer to the" ,  "type" ) ,  // this is already covered by E0223, but this single match arm doesn't hurt here 
2153+                         } ; 
2154+ 
2155+                         // Replace the more general E0283 with a more specific error 
2156+                         err. cancel ( ) ; 
2157+                         err = self . tcx . sess . struct_span_err_with_code ( 
2158+                             span, 
2159+                             & format ! ( 
2160+                                 "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type" , 
2161+                              ) , 
2162+                             rustc_errors:: error_code!( E0790 ) , 
2163+                         ) ; 
2164+ 
2165+                         if  let  Some ( local_def_id)  = data. trait_ref . def_id . as_local ( ) 
2166+                             && let  Some ( hir:: Node :: Item ( hir:: Item  {  ident :  trait_name,  kind :  hir:: ItemKind :: Trait ( _,  _,  _,  _,  trait_item_refs) ,  .. } ) )  = self . tcx . hir ( ) . find_by_def_id ( local_def_id) 
2167+                             && let  Some ( method_ref)  = trait_item_refs. iter ( ) . find ( |item_ref| item_ref. ident  == * assoc_item_name)  { 
2168+                             err. span_label ( method_ref. span ,  format ! ( "`{}::{}` defined here" ,  trait_name,  assoc_item_name) ) ; 
2169+                         } 
2170+ 
2171+                         err. span_label ( span,  format ! ( "cannot {verb} associated {noun} of trait" ) ) ; 
2172+ 
2173+                         let  trait_impls = self . tcx . trait_impls_of ( data. trait_ref . def_id ) ; 
2174+ 
2175+                         if  trait_impls. blanket_impls ( ) . is_empty ( ) 
2176+                             && let  Some ( ( impl_ty,  _) )  = trait_impls. non_blanket_impls ( ) . iter ( ) . next ( ) 
2177+                             && let  Some ( impl_def_id)  = impl_ty. def ( )  { 
2178+                             let  message = if  trait_impls. non_blanket_impls ( ) . len ( )  == 1  { 
2179+                                 "use the fully-qualified path to the only available implementation" . to_string ( ) 
2180+                             }  else  { 
2181+                                 format ! ( 
2182+                                     "use a fully-qualified path to a specific available implementation ({} found)" , 
2183+                                     trait_impls. non_blanket_impls( ) . len( ) 
2184+                                 ) 
2185+                             } ; 
2186+ 
2187+                             err. multipart_suggestion ( 
2188+                                 message, 
2189+                                 vec ! [ 
2190+                                     ( trait_path_segment. ident. span. shrink_to_lo( ) ,  format!( "<{} as " ,  self . tcx. def_path( impl_def_id) . to_string_no_crate_verbose( ) ) ) , 
2191+                                     ( trait_path_segment. ident. span. shrink_to_hi( ) ,  format!( ">" ) ) 
2192+                                 ] , 
2193+                                 Applicability :: MaybeIncorrect 
2194+                             ) ; 
2195+                         } 
2196+                     } 
2197+                 } ; 
2198+ 
21072199                err
21082200            } 
21092201
0 commit comments