@@ -33,21 +33,22 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
33
33
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
34
34
use rustc_hir:: { self as hir, AnonConst , GenericArg , GenericArgs , HirId } ;
35
35
use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
36
- use rustc_infer:: traits:: { DynCompatibilityViolation , ObligationCause } ;
36
+ use rustc_infer:: traits:: DynCompatibilityViolation ;
37
+ use rustc_macros:: { TypeFoldable , TypeVisitable } ;
37
38
use rustc_middle:: middle:: stability:: AllowUnstable ;
38
39
use rustc_middle:: mir:: interpret:: LitToConstInput ;
39
40
use rustc_middle:: ty:: print:: PrintPolyTraitRefExt as _;
40
41
use rustc_middle:: ty:: {
41
- self , Const , GenericArgKind , GenericArgsRef , GenericParamDefKind , ParamEnv , Ty , TyCtxt ,
42
- TypeVisitableExt , TypingMode , Upcast , fold_regions,
42
+ self , Const , GenericArgKind , GenericArgsRef , GenericParamDefKind , Ty , TyCtxt , TypeVisitableExt ,
43
+ TypingMode , Upcast , fold_regions,
43
44
} ;
44
45
use rustc_middle:: { bug, span_bug} ;
45
46
use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
46
47
use rustc_session:: parse:: feature_err;
47
48
use rustc_span:: { DUMMY_SP , Ident , Span , kw, sym} ;
48
49
use rustc_trait_selection:: infer:: InferCtxtExt ;
49
50
use rustc_trait_selection:: traits:: wf:: object_region_bounds;
50
- use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
51
+ use rustc_trait_selection:: traits:: { self , FulfillmentError } ;
51
52
use tracing:: { debug, instrument} ;
52
53
53
54
use crate :: check:: check_abi_fn_ptr;
@@ -99,6 +100,13 @@ pub enum RegionInferReason<'a> {
99
100
OutlivesBound ,
100
101
}
101
102
103
+ #[ derive( Copy , Clone , TypeFoldable , TypeVisitable , Debug ) ]
104
+ pub struct InherentAssocCandidate {
105
+ pub impl_ : DefId ,
106
+ pub assoc_item : DefId ,
107
+ pub scope : DefId ,
108
+ }
109
+
102
110
/// A context which can lower type-system entities from the [HIR][hir] to
103
111
/// the [`rustc_middle::ty`] representation.
104
112
///
@@ -148,6 +156,13 @@ pub trait HirTyLowerer<'tcx> {
148
156
assoc_ident : Ident ,
149
157
) -> ty:: EarlyBinder < ' tcx , & ' tcx [ ( ty:: Clause < ' tcx > , Span ) ] > ;
150
158
159
+ fn select_inherent_assoc_candidates (
160
+ & self ,
161
+ span : Span ,
162
+ self_ty : Ty < ' tcx > ,
163
+ candidates : Vec < InherentAssocCandidate > ,
164
+ ) -> ( Vec < InherentAssocCandidate > , Vec < FulfillmentError < ' tcx > > ) ;
165
+
151
166
/// Lower a path to an associated item (of a trait) to a projection.
152
167
///
153
168
/// This method has to be defined by the concrete lowering context because
@@ -1445,48 +1460,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1445
1460
. filter_map ( |& impl_| {
1446
1461
let ( item, scope) =
1447
1462
self . probe_assoc_item_unchecked ( name, assoc_tag, block, impl_) ?;
1448
- Some ( ( impl_, ( item. def_id , scope) ) )
1463
+ Some ( InherentAssocCandidate { impl_, assoc_item : item. def_id , scope } )
1449
1464
} )
1450
1465
. collect ( ) ;
1451
1466
1452
- if candidates. is_empty ( ) {
1453
- return Ok ( None ) ;
1454
- }
1455
-
1456
- //
1457
- // Select applicable inherent associated type candidates modulo regions.
1458
- //
1459
-
1460
- // In contexts that have no inference context, just make a new one.
1461
- // We do need a local variable to store it, though.
1462
- let infcx = match self . infcx ( ) {
1463
- Some ( infcx) => infcx,
1464
- None => {
1465
- assert ! ( !self_ty. has_infer( ) ) ;
1466
- & tcx. infer_ctxt ( ) . ignoring_regions ( ) . build ( TypingMode :: non_body_analysis ( ) )
1467
- }
1468
- } ;
1467
+ let ( applicable_candidates, fulfillment_errors) =
1468
+ self . select_inherent_assoc_candidates ( span, self_ty, candidates. clone ( ) ) ;
1469
1469
1470
- // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
1471
- // when inside of an ADT (#108491) or where clause.
1472
- let param_env = tcx. param_env ( block. owner ) ;
1470
+ let InherentAssocCandidate { impl_, assoc_item, scope : def_scope } =
1471
+ match & applicable_candidates[ ..] {
1472
+ & [ ] => Err ( self . report_unresolved_inherent_assoc_item (
1473
+ name,
1474
+ self_ty,
1475
+ candidates,
1476
+ fulfillment_errors,
1477
+ span,
1478
+ assoc_tag,
1479
+ ) ) ,
1473
1480
1474
- let mut universes = if self_ty. has_escaping_bound_vars ( ) {
1475
- vec ! [ None ; self_ty. outer_exclusive_binder( ) . as_usize( ) ]
1476
- } else {
1477
- vec ! [ ]
1478
- } ;
1481
+ & [ applicable_candidate] => Ok ( applicable_candidate) ,
1479
1482
1480
- let ( impl_, ( assoc_item, def_scope) ) = crate :: traits:: with_replaced_escaping_bound_vars (
1481
- infcx,
1482
- & mut universes,
1483
- self_ty,
1484
- |self_ty| {
1485
- self . select_inherent_assoc_candidates (
1486
- infcx, name, span, self_ty, param_env, candidates, assoc_tag,
1487
- )
1488
- } ,
1489
- ) ?;
1483
+ & [ _, ..] => Err ( self . report_ambiguous_inherent_assoc_item (
1484
+ name,
1485
+ candidates. into_iter ( ) . map ( |cand| cand. assoc_item ) . collect ( ) ,
1486
+ span,
1487
+ ) ) ,
1488
+ } ?;
1490
1489
1491
1490
self . check_assoc_item ( assoc_item, name, def_scope, block, span) ;
1492
1491
@@ -1503,78 +1502,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1503
1502
Ok ( Some ( ( assoc_item, args) ) )
1504
1503
}
1505
1504
1506
- fn select_inherent_assoc_candidates (
1507
- & self ,
1508
- infcx : & InferCtxt < ' tcx > ,
1509
- name : Ident ,
1510
- span : Span ,
1511
- self_ty : Ty < ' tcx > ,
1512
- param_env : ParamEnv < ' tcx > ,
1513
- candidates : Vec < ( DefId , ( DefId , DefId ) ) > ,
1514
- assoc_tag : ty:: AssocTag ,
1515
- ) -> Result < ( DefId , ( DefId , DefId ) ) , ErrorGuaranteed > {
1516
- let tcx = self . tcx ( ) ;
1517
- let mut fulfillment_errors = Vec :: new ( ) ;
1518
-
1519
- let applicable_candidates: Vec < _ > = candidates
1520
- . iter ( )
1521
- . copied ( )
1522
- . filter ( |& ( impl_, _) | {
1523
- infcx. probe ( |_| {
1524
- let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
1525
- let self_ty = ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, self_ty) ;
1526
-
1527
- let impl_args = infcx. fresh_args_for_item ( span, impl_) ;
1528
- let impl_ty = tcx. type_of ( impl_) . instantiate ( tcx, impl_args) ;
1529
- let impl_ty = ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, impl_ty) ;
1530
-
1531
- // Check that the self types can be related.
1532
- if ocx. eq ( & ObligationCause :: dummy ( ) , param_env, impl_ty, self_ty) . is_err ( ) {
1533
- return false ;
1534
- }
1535
-
1536
- // Check whether the impl imposes obligations we have to worry about.
1537
- let impl_bounds = tcx. predicates_of ( impl_) . instantiate ( tcx, impl_args) ;
1538
- let impl_bounds =
1539
- ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, impl_bounds) ;
1540
- let impl_obligations = traits:: predicates_for_generics (
1541
- |_, _| ObligationCause :: dummy ( ) ,
1542
- param_env,
1543
- impl_bounds,
1544
- ) ;
1545
- ocx. register_obligations ( impl_obligations) ;
1546
-
1547
- let mut errors = ocx. select_where_possible ( ) ;
1548
- if !errors. is_empty ( ) {
1549
- fulfillment_errors. append ( & mut errors) ;
1550
- return false ;
1551
- }
1552
-
1553
- true
1554
- } )
1555
- } )
1556
- . collect ( ) ;
1557
-
1558
- match & applicable_candidates[ ..] {
1559
- & [ ] => Err ( self . report_unresolved_inherent_assoc_item (
1560
- name,
1561
- self_ty,
1562
- candidates,
1563
- fulfillment_errors,
1564
- span,
1565
- assoc_tag,
1566
- ) ) ,
1567
-
1568
- & [ applicable_candidate] => Ok ( applicable_candidate) ,
1569
-
1570
- & [ _, ..] => Err ( self . report_ambiguous_inherent_assoc_item (
1571
- name,
1572
- applicable_candidates. into_iter ( ) . map ( |( _, ( candidate, _) ) | candidate) . collect ( ) ,
1573
- span,
1574
- ) ) ,
1575
- }
1576
- }
1577
-
1578
1505
/// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1].
1579
1506
///
1580
1507
/// [^1]: I.e., accessible in the provided scope wrt. visibility and stability.
0 commit comments