@@ -27,11 +27,12 @@ use rustc_hir::def_id::{DefId, LocalDefId};
2727use rustc_hir:: intravisit:: { walk_generics, Visitor as _} ;
2828use rustc_hir:: { GenericArg , GenericArgs , OpaqueTyOrigin } ;
2929use rustc_infer:: infer:: { InferCtxt , InferOk , TyCtxtInferExt } ;
30- use rustc_infer:: traits:: ObligationCause ;
30+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
3131use rustc_middle:: middle:: stability:: AllowUnstable ;
3232use rustc_middle:: ty:: GenericParamDefKind ;
3333use rustc_middle:: ty:: {
34- self , Const , GenericArgKind , GenericArgsRef , IsSuggestable , Ty , TyCtxt , TypeVisitableExt ,
34+ self , Const , GenericArgKind , GenericArgsRef , IsSuggestable , ParamEnv , Predicate , Ty , TyCtxt ,
35+ TypeVisitableExt ,
3536} ;
3637use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
3738use rustc_span:: edit_distance:: find_best_match_for_name;
@@ -1607,7 +1608,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16071608 let param_env = tcx. param_env ( block. owner ) ;
16081609 let cause = ObligationCause :: misc ( span, block. owner . def_id ) ;
16091610
1610- let mut fulfillment_errors = Vec :: new ( ) ;
16111611 let mut universes = if self_ty. has_escaping_bound_vars ( ) {
16121612 vec ! [ None ; self_ty. outer_exclusive_binder( ) . as_usize( ) ]
16131613 } else {
@@ -1619,94 +1619,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16191619 & mut universes,
16201620 self_ty,
16211621 |self_ty| {
1622+ let tcx = self . tcx ( ) ;
16221623 let InferOk { value : self_ty, obligations } =
16231624 infcx. at ( & cause, param_env) . normalize ( self_ty) ;
16241625
1625- let mut applicable_candidates: Vec < _ > = candidates
1626- . iter ( )
1627- . copied ( )
1628- . filter ( |& ( impl_, _) | {
1629- infcx. probe ( |_| {
1630- let ocx = ObligationCtxt :: new ( & infcx) ;
1631- ocx. register_obligations ( obligations. clone ( ) ) ;
1632-
1633- let impl_args = infcx. fresh_args_for_item ( span, impl_) ;
1634- let impl_ty = tcx. type_of ( impl_) . instantiate ( tcx, impl_args) ;
1635- let impl_ty = ocx. normalize ( & cause, param_env, impl_ty) ;
1636-
1637- // Check that the self types can be related.
1638- if ocx
1639- . eq ( & ObligationCause :: dummy ( ) , param_env, impl_ty, self_ty)
1640- . is_err ( )
1641- {
1642- return false ;
1643- }
1644-
1645- // Check whether the impl imposes obligations we have to worry about.
1646- let impl_bounds = tcx. predicates_of ( impl_) . instantiate ( tcx, impl_args) ;
1647- let impl_bounds = ocx. normalize ( & cause, param_env, impl_bounds) ;
1648- let impl_obligations = traits:: predicates_for_generics (
1649- |_, _| cause. clone ( ) ,
1650- param_env,
1651- impl_bounds,
1652- ) ;
1653- ocx. register_obligations ( impl_obligations) ;
1626+ let ( impl_, ( assoc_item, def_scope) ) = self . select_inherent_assoc_type_candidates (
1627+ obligations,
1628+ infcx,
1629+ self_ty,
1630+ name,
1631+ span,
1632+ cause,
1633+ param_env,
1634+ candidates,
1635+ ) ?;
1636+
1637+ self . check_assoc_ty ( assoc_item, name, def_scope, block, span) ;
1638+
1639+ // FIXME(fmease): Currently creating throwaway `parent_args` to please
1640+ // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1641+ // not require the parent args logic.
1642+ let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, impl_) ;
1643+ let args =
1644+ self . create_args_for_associated_item ( span, assoc_item, segment, parent_args) ;
1645+ let args = tcx. mk_args_from_iter (
1646+ std:: iter:: once ( ty:: GenericArg :: from ( self_ty) )
1647+ . chain ( args. into_iter ( ) . skip ( parent_args. len ( ) ) ) ,
1648+ ) ;
16541649
1655- let mut errors = ocx. select_where_possible ( ) ;
1656- if !errors. is_empty ( ) {
1657- fulfillment_errors. append ( & mut errors) ;
1658- return false ;
1659- }
1650+ let ty = Ty :: new_alias ( tcx, ty:: Inherent , ty:: AliasTy :: new ( tcx, assoc_item, args) ) ;
16601651
1661- true
1662- } )
1663- } )
1664- . collect ( ) ;
1652+ Ok ( Some ( ( ty , assoc_item ) ) )
1653+ } ,
1654+ )
1655+ }
16651656
1666- if applicable_candidates. len ( ) > 1 {
1667- return Err ( self . complain_about_ambiguous_inherent_assoc_type (
1668- name,
1669- applicable_candidates
1670- . into_iter ( )
1671- . map ( |( _, ( candidate, _) ) | candidate)
1672- . collect ( ) ,
1673- span,
1674- ) ) ;
1675- }
1657+ fn select_inherent_assoc_type_candidates (
1658+ & self ,
1659+ obligations : Vec < Obligation < ' tcx , Predicate < ' tcx > > > ,
1660+ infcx : & InferCtxt < ' tcx > ,
1661+ self_ty : Ty < ' tcx > ,
1662+ name : Ident ,
1663+ span : Span ,
1664+ cause : ObligationCause < ' tcx > ,
1665+ param_env : ParamEnv < ' tcx > ,
1666+ candidates : Vec < ( DefId , ( DefId , DefId ) ) > ,
1667+ ) -> Result < ( DefId , ( DefId , DefId ) ) , ErrorGuaranteed > {
1668+ let tcx = self . tcx ( ) ;
1669+ let mut fulfillment_errors = Vec :: new ( ) ;
16761670
1677- if let Some ( ( impl_, ( assoc_item, def_scope) ) ) = applicable_candidates. pop ( ) {
1678- self . check_assoc_ty ( assoc_item, name, def_scope, block, span) ;
1671+ let applicable_candidates: Vec < _ > = candidates
1672+ . iter ( )
1673+ . copied ( )
1674+ . filter ( |& ( impl_, _) | {
1675+ infcx. probe ( |_| {
1676+ let ocx = ObligationCtxt :: new ( & infcx) ;
1677+ ocx. register_obligations ( obligations. clone ( ) ) ;
1678+
1679+ let impl_args = infcx. fresh_args_for_item ( span, impl_) ;
1680+ let impl_ty = tcx. type_of ( impl_) . instantiate ( tcx, impl_args) ;
1681+ let impl_ty = ocx. normalize ( & cause, param_env, impl_ty) ;
1682+
1683+ // Check that the self types can be related.
1684+ if ocx. eq ( & ObligationCause :: dummy ( ) , param_env, impl_ty, self_ty) . is_err ( ) {
1685+ return false ;
1686+ }
16791687
1680- // FIXME(fmease): Currently creating throwaway `parent_args` to please
1681- // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
1682- // not require the parent args logic.
1683- let parent_args = ty:: GenericArgs :: identity_for_item ( tcx, impl_) ;
1684- let args = self . create_args_for_associated_item (
1685- span,
1686- assoc_item,
1687- segment,
1688- parent_args,
1689- ) ;
1690- let args = tcx. mk_args_from_iter (
1691- std:: iter:: once ( ty:: GenericArg :: from ( self_ty) )
1692- . chain ( args. into_iter ( ) . skip ( parent_args. len ( ) ) ) ,
1688+ // Check whether the impl imposes obligations we have to worry about.
1689+ let impl_bounds = tcx. predicates_of ( impl_) . instantiate ( tcx, impl_args) ;
1690+ let impl_bounds = ocx. normalize ( & cause, param_env, impl_bounds) ;
1691+ let impl_obligations = traits:: predicates_for_generics (
1692+ |_, _| cause. clone ( ) ,
1693+ param_env,
1694+ impl_bounds,
16931695 ) ;
1696+ ocx. register_obligations ( impl_obligations) ;
16941697
1695- let ty =
1696- Ty :: new_alias ( tcx, ty:: Inherent , ty:: AliasTy :: new ( tcx, assoc_item, args) ) ;
1698+ let mut errors = ocx. select_where_possible ( ) ;
1699+ if !errors. is_empty ( ) {
1700+ fulfillment_errors. append ( & mut errors) ;
1701+ return false ;
1702+ }
16971703
1698- return Ok ( Some ( ( ty, assoc_item) ) ) ;
1699- }
1704+ true
1705+ } )
1706+ } )
1707+ . collect ( ) ;
17001708
1701- Err ( self . complain_about_inherent_assoc_type_not_found (
1702- name,
1703- self_ty,
1704- candidates,
1705- fulfillment_errors,
1706- span,
1707- ) )
1708- } ,
1709- )
1709+ match & applicable_candidates[ ..] {
1710+ & [ ] => Err ( self . complain_about_inherent_assoc_type_not_found (
1711+ name,
1712+ self_ty,
1713+ candidates,
1714+ fulfillment_errors,
1715+ span,
1716+ ) ) ,
1717+
1718+ & [ applicable_candidate] => Ok ( applicable_candidate) ,
1719+
1720+ & [ _, ..] => Err ( self . complain_about_ambiguous_inherent_assoc_type (
1721+ name,
1722+ applicable_candidates. into_iter ( ) . map ( |( _, ( candidate, _) ) | candidate) . collect ( ) ,
1723+ span,
1724+ ) ) ,
1725+ }
17101726 }
17111727
17121728 fn lookup_assoc_ty (
0 commit comments