@@ -33,13 +33,13 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
3333use  rustc_hir:: def_id:: { DefId ,  LocalDefId } ; 
3434use  rustc_hir:: { self  as  hir,  AnonConst ,  GenericArg ,  GenericArgs ,  HirId } ; 
3535use  rustc_infer:: infer:: { InferCtxt ,  TyCtxtInferExt } ; 
36- use  rustc_infer :: traits :: ObligationCause ; 
36+ use  rustc_macros :: { TypeFoldable ,   TypeVisitable } ; 
3737use  rustc_middle:: middle:: stability:: AllowUnstable ; 
3838use  rustc_middle:: mir:: interpret:: LitToConstInput ; 
3939use  rustc_middle:: ty:: print:: PrintPolyTraitRefExt  as  _; 
4040use  rustc_middle:: ty:: { 
41-     self ,  AssocTag ,  Const ,  GenericArgKind ,  GenericArgsRef ,  GenericParamDefKind ,  ParamEnv ,   Ty , 
42-     TyCtxt ,   TypeVisitableExt ,  TypingMode ,  Upcast ,  fold_regions, 
41+     self ,  AssocTag ,  Const ,  GenericArgKind ,  GenericArgsRef ,  GenericParamDefKind ,  Ty ,   TyCtxt , 
42+     TypeVisitableExt ,  TypingMode ,  Upcast ,  fold_regions, 
4343} ; 
4444use  rustc_middle:: { bug,  span_bug} ; 
4545use  rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ; 
@@ -48,7 +48,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
4848use  rustc_span:: { DUMMY_SP ,  Ident ,  Span ,  Symbol ,  kw,  sym} ; 
4949use  rustc_trait_selection:: infer:: InferCtxtExt ; 
5050use  rustc_trait_selection:: traits:: wf:: object_region_bounds; 
51- use  rustc_trait_selection:: traits:: { self ,  ObligationCtxt } ; 
51+ use  rustc_trait_selection:: traits:: { self ,  FulfillmentError } ; 
5252use  tracing:: { debug,  instrument} ; 
5353
5454use  self :: errors:: assoc_tag_str; 
@@ -101,6 +101,13 @@ pub enum RegionInferReason<'a> {
101101    OutlivesBound , 
102102} 
103103
104+ #[ derive( Copy ,  Clone ,  TypeFoldable ,  TypeVisitable ,  Debug ) ]  
105+ pub  struct  InherentAssocCandidate  { 
106+     pub  impl_ :  DefId , 
107+     pub  assoc_item :  DefId , 
108+     pub  scope :  DefId , 
109+ } 
110+ 
104111/// A context which can lower type-system entities from the [HIR][hir] to 
105112/// the [`rustc_middle::ty`] representation. 
106113/// 
@@ -150,6 +157,13 @@ pub trait HirTyLowerer<'tcx> {
150157        assoc_ident :  Ident , 
151158    )  -> ty:: EarlyBinder < ' tcx ,  & ' tcx  [ ( ty:: Clause < ' tcx > ,  Span ) ] > ; 
152159
160+     fn  select_inherent_assoc_candidates ( 
161+         & self , 
162+         span :  Span , 
163+         self_ty :  Ty < ' tcx > , 
164+         candidates :  & Vec < InherentAssocCandidate > , 
165+     )  -> ( Vec < InherentAssocCandidate > ,  Vec < FulfillmentError < ' tcx > > ) ; 
166+ 
153167    /// Lower an associated type/const (from a trait) to a projection. 
154168     /// 
155169     /// This method has to be defined by the concrete lowering context because 
@@ -1513,48 +1527,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
15131527            . filter_map ( |& impl_| { 
15141528                let  ( item,  scope)  =
15151529                    self . probe_assoc_item_unchecked ( name,  assoc_tag,  block,  impl_) ?; 
1516-                 Some ( ( impl_,  ( item. def_id ,  scope) ) ) 
1530+                 Some ( InherentAssocCandidate   {   impl_,  assoc_item :   item. def_id ,  scope  } ) 
15171531            } ) 
15181532            . collect ( ) ; 
15191533
1520-         if  candidates. is_empty ( )  { 
1521-             return  Ok ( None ) ; 
1522-         } 
1523- 
1524-         // 
1525-         // Select applicable inherent associated type candidates modulo regions. 
1526-         // 
1527- 
1528-         // In contexts that have no inference context, just make a new one. 
1529-         // We do need a local variable to store it, though. 
1530-         let  infcx = match  self . infcx ( )  { 
1531-             Some ( infcx)  => infcx, 
1532-             None  => { 
1533-                 assert ! ( !self_ty. has_infer( ) ) ; 
1534-                 & tcx. infer_ctxt ( ) . ignoring_regions ( ) . build ( TypingMode :: non_body_analysis ( ) ) 
1535-             } 
1536-         } ; 
1534+         let  ( applicable_candidates,  fulfillment_errors)  =
1535+             self . select_inherent_assoc_candidates ( span,  self_ty,  & candidates) ; 
15371536
1538-         // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors 
1539-         // when inside of an ADT (#108491) or where clause. 
1540-         let  param_env = tcx. param_env ( block. owner ) ; 
1537+         let  InherentAssocCandidate  {  impl_,  assoc_item,  scope :  def_scope }  =
1538+             match  & applicable_candidates[ ..]  { 
1539+                 & [ ]  => Err ( self . complain_about_inherent_assoc_not_found ( 
1540+                     name, 
1541+                     self_ty, 
1542+                     candidates, 
1543+                     fulfillment_errors, 
1544+                     span, 
1545+                     assoc_tag, 
1546+                 ) ) , 
15411547
1542-         let  mut  universes = if  self_ty. has_escaping_bound_vars ( )  { 
1543-             vec ! [ None ;  self_ty. outer_exclusive_binder( ) . as_usize( ) ] 
1544-         }  else  { 
1545-             vec ! [ ] 
1546-         } ; 
1548+                 & [ applicable_candidate]  => Ok ( applicable_candidate) , 
15471549
1548-         let  ( impl_,  ( assoc_item,  def_scope) )  = crate :: traits:: with_replaced_escaping_bound_vars ( 
1549-             infcx, 
1550-             & mut  universes, 
1551-             self_ty, 
1552-             |self_ty| { 
1553-                 self . select_inherent_assoc_candidates ( 
1554-                     infcx,  name,  span,  self_ty,  param_env,  candidates,  assoc_tag, 
1555-                 ) 
1556-             } , 
1557-         ) ?; 
1550+                 & [ _,  ..]  => Err ( self . complain_about_ambiguous_inherent_assoc ( 
1551+                     name, 
1552+                     candidates. into_iter ( ) . map ( |cand| cand. assoc_item ) . collect ( ) , 
1553+                     span, 
1554+                 ) ) , 
1555+             } ?; 
15581556
15591557        self . check_assoc_item ( assoc_item,  name,  def_scope,  block,  span) ; 
15601558
@@ -1571,78 +1569,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
15711569        Ok ( Some ( ( assoc_item,  args) ) ) 
15721570    } 
15731571
1574-     fn  select_inherent_assoc_candidates ( 
1575-         & self , 
1576-         infcx :  & InferCtxt < ' tcx > , 
1577-         name :  Ident , 
1578-         span :  Span , 
1579-         self_ty :  Ty < ' tcx > , 
1580-         param_env :  ParamEnv < ' tcx > , 
1581-         candidates :  Vec < ( DefId ,  ( DefId ,  DefId ) ) > , 
1582-         assoc_tag :  ty:: AssocTag , 
1583-     )  -> Result < ( DefId ,  ( DefId ,  DefId ) ) ,  ErrorGuaranteed >  { 
1584-         let  tcx = self . tcx ( ) ; 
1585-         let  mut  fulfillment_errors = Vec :: new ( ) ; 
1586- 
1587-         let  applicable_candidates:  Vec < _ >  = candidates
1588-             . iter ( ) 
1589-             . copied ( ) 
1590-             . filter ( |& ( impl_,  _) | { 
1591-                 infcx. probe ( |_| { 
1592-                     let  ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ; 
1593-                     let  self_ty = ocx. normalize ( & ObligationCause :: dummy ( ) ,  param_env,  self_ty) ; 
1594- 
1595-                     let  impl_args = infcx. fresh_args_for_item ( span,  impl_) ; 
1596-                     let  impl_ty = tcx. type_of ( impl_) . instantiate ( tcx,  impl_args) ; 
1597-                     let  impl_ty = ocx. normalize ( & ObligationCause :: dummy ( ) ,  param_env,  impl_ty) ; 
1598- 
1599-                     // Check that the self types can be related. 
1600-                     if  ocx. eq ( & ObligationCause :: dummy ( ) ,  param_env,  impl_ty,  self_ty) . is_err ( )  { 
1601-                         return  false ; 
1602-                     } 
1603- 
1604-                     // Check whether the impl imposes obligations we have to worry about. 
1605-                     let  impl_bounds = tcx. predicates_of ( impl_) . instantiate ( tcx,  impl_args) ; 
1606-                     let  impl_bounds =
1607-                         ocx. normalize ( & ObligationCause :: dummy ( ) ,  param_env,  impl_bounds) ; 
1608-                     let  impl_obligations = traits:: predicates_for_generics ( 
1609-                         |_,  _| ObligationCause :: dummy ( ) , 
1610-                         param_env, 
1611-                         impl_bounds, 
1612-                     ) ; 
1613-                     ocx. register_obligations ( impl_obligations) ; 
1614- 
1615-                     let  mut  errors = ocx. select_where_possible ( ) ; 
1616-                     if  !errors. is_empty ( )  { 
1617-                         fulfillment_errors. append ( & mut  errors) ; 
1618-                         return  false ; 
1619-                     } 
1620- 
1621-                     true 
1622-                 } ) 
1623-             } ) 
1624-             . collect ( ) ; 
1625- 
1626-         match  & applicable_candidates[ ..]  { 
1627-             & [ ]  => Err ( self . complain_about_inherent_assoc_not_found ( 
1628-                 name, 
1629-                 self_ty, 
1630-                 candidates, 
1631-                 fulfillment_errors, 
1632-                 span, 
1633-                 assoc_tag, 
1634-             ) ) , 
1635- 
1636-             & [ applicable_candidate]  => Ok ( applicable_candidate) , 
1637- 
1638-             & [ _,  ..]  => Err ( self . complain_about_ambiguous_inherent_assoc ( 
1639-                 name, 
1640-                 applicable_candidates. into_iter ( ) . map ( |( _,  ( candidate,  _) ) | candidate) . collect ( ) , 
1641-                 span, 
1642-             ) ) , 
1643-         } 
1644-     } 
1645- 
16461572    /// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1]. 
16471573     /// 
16481574     /// [^1]: I.e., accessible in the provided scope wrt. visibility and stability. 
0 commit comments