@@ -27,11 +27,12 @@ use rustc_hir::def_id::{DefId, LocalDefId};
27
27
use rustc_hir:: intravisit:: { walk_generics, Visitor as _} ;
28
28
use rustc_hir:: { GenericArg , GenericArgs , OpaqueTyOrigin } ;
29
29
use rustc_infer:: infer:: { InferCtxt , InferOk , TyCtxtInferExt } ;
30
- use rustc_infer:: traits:: ObligationCause ;
30
+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
31
31
use rustc_middle:: middle:: stability:: AllowUnstable ;
32
32
use rustc_middle:: ty:: GenericParamDefKind ;
33
33
use rustc_middle:: ty:: {
34
- self , Const , GenericArgKind , GenericArgsRef , IsSuggestable , Ty , TyCtxt , TypeVisitableExt ,
34
+ self , Const , GenericArgKind , GenericArgsRef , IsSuggestable , ParamEnv , Predicate , Ty , TyCtxt ,
35
+ TypeVisitableExt ,
35
36
} ;
36
37
use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
37
38
use rustc_span:: edit_distance:: find_best_match_for_name;
@@ -1607,7 +1608,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1607
1608
let param_env = tcx. param_env ( block. owner ) ;
1608
1609
let cause = ObligationCause :: misc ( span, block. owner . def_id ) ;
1609
1610
1610
- let mut fulfillment_errors = Vec :: new ( ) ;
1611
1611
let mut universes = if self_ty. has_escaping_bound_vars ( ) {
1612
1612
vec ! [ None ; self_ty. outer_exclusive_binder( ) . as_usize( ) ]
1613
1613
} else {
@@ -1619,94 +1619,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1619
1619
& mut universes,
1620
1620
self_ty,
1621
1621
|self_ty| {
1622
+ let tcx = self . tcx ( ) ;
1622
1623
let InferOk { value : self_ty, obligations } =
1623
1624
infcx. at ( & cause, param_env) . normalize ( self_ty) ;
1624
1625
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
+ infcx,
1628
+ name,
1629
+ span,
1630
+ self_ty,
1631
+ cause,
1632
+ param_env,
1633
+ obligations,
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
+ ) ;
1654
1649
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) ) ;
1660
1651
1661
- true
1662
- } )
1663
- } )
1664
- . collect ( ) ;
1652
+ Ok ( Some ( ( ty , assoc_item ) ) )
1653
+ } ,
1654
+ )
1655
+ }
1665
1656
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
+ infcx : & InferCtxt < ' tcx > ,
1660
+ name : Ident ,
1661
+ span : Span ,
1662
+ self_ty : Ty < ' tcx > ,
1663
+ cause : ObligationCause < ' tcx > ,
1664
+ param_env : ParamEnv < ' tcx > ,
1665
+ obligations : Vec < Obligation < ' tcx , Predicate < ' 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 ( ) ;
1676
1670
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
+ }
1679
1687
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,
1693
1695
) ;
1696
+ ocx. register_obligations ( impl_obligations) ;
1694
1697
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
+ }
1697
1703
1698
- return Ok ( Some ( ( ty, assoc_item) ) ) ;
1699
- }
1704
+ true
1705
+ } )
1706
+ } )
1707
+ . collect ( ) ;
1700
1708
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
+ }
1710
1726
}
1711
1727
1712
1728
fn lookup_assoc_ty (
0 commit comments