@@ -19,7 +19,7 @@ use rustc::traits::select;
19
19
use rustc:: ty:: error:: { ExpectedFound , TypeError , UnconstrainedNumeric } ;
20
20
use rustc:: ty:: fold:: { TypeFoldable , TypeFolder } ;
21
21
use rustc:: ty:: relate:: RelateResult ;
22
- use rustc:: ty:: subst:: { GenericArg , InternalSubsts , SubstsRef } ;
22
+ use rustc:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , SubstsRef } ;
23
23
pub use rustc:: ty:: IntVarValue ;
24
24
use rustc:: ty:: { self , GenericParamDefKind , InferConst , Ty , TyCtxt } ;
25
25
use rustc:: ty:: { ConstVid , FloatVid , IntVid , TyVid } ;
@@ -501,6 +501,7 @@ impl NLLRegionVariableOrigin {
501
501
}
502
502
}
503
503
504
+ // FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`.
504
505
#[ derive( Copy , Clone , Debug ) ]
505
506
pub enum FixupError < ' tcx > {
506
507
UnresolvedIntTy ( IntVid ) ,
@@ -1347,8 +1348,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1347
1348
where
1348
1349
T : TypeFoldable < ' tcx > ,
1349
1350
{
1350
- let mut r = ShallowResolver :: new ( self ) ;
1351
- value. fold_with ( & mut r)
1351
+ value. fold_with ( & mut ShallowResolver { infcx : self } )
1352
1352
}
1353
1353
1354
1354
pub fn root_var ( & self , var : ty:: TyVid ) -> ty:: TyVid {
@@ -1551,22 +1551,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1551
1551
// variables, thus we don't need to substitute back the original values.
1552
1552
self . tcx . const_eval_resolve ( param_env, def_id, substs, promoted, span)
1553
1553
}
1554
- }
1555
-
1556
- pub struct ShallowResolver < ' a , ' tcx > {
1557
- infcx : & ' a InferCtxt < ' a , ' tcx > ,
1558
- }
1559
-
1560
- impl < ' a , ' tcx > ShallowResolver < ' a , ' tcx > {
1561
- #[ inline( always) ]
1562
- pub fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > ) -> Self {
1563
- ShallowResolver { infcx }
1564
- }
1565
1554
1566
1555
/// If `typ` is a type variable of some kind, resolve it one level
1567
1556
/// (but do not resolve types found in the result). If `typ` is
1568
1557
/// not a type variable, just return it unmodified.
1569
- pub fn shallow_resolve ( & mut self , typ : Ty < ' tcx > ) -> Ty < ' tcx > {
1558
+ // FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
1559
+ fn shallow_resolve_ty ( & self , typ : Ty < ' tcx > ) -> Ty < ' tcx > {
1570
1560
match typ. kind {
1571
1561
ty:: Infer ( ty:: TyVar ( v) ) => {
1572
1562
// Not entirely obvious: if `typ` is a type variable,
@@ -1580,69 +1570,133 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
1580
1570
// depth.
1581
1571
//
1582
1572
// Note: if these two lines are combined into one we get
1583
- // dynamic borrow errors on `self.infcx. inner`.
1584
- let known = self . infcx . inner . borrow_mut ( ) . type_variables . probe ( v) . known ( ) ;
1585
- known. map ( |t| self . fold_ty ( t) ) . unwrap_or ( typ)
1573
+ // dynamic borrow errors on `self.inner`.
1574
+ let known = self . inner . borrow_mut ( ) . type_variables . probe ( v) . known ( ) ;
1575
+ known. map ( |t| self . shallow_resolve_ty ( t) ) . unwrap_or ( typ)
1586
1576
}
1587
1577
1588
1578
ty:: Infer ( ty:: IntVar ( v) ) => self
1589
- . infcx
1590
1579
. inner
1591
1580
. borrow_mut ( )
1592
1581
. int_unification_table
1593
1582
. probe_value ( v)
1594
- . map ( |v| v. to_type ( self . infcx . tcx ) )
1583
+ . map ( |v| v. to_type ( self . tcx ) )
1595
1584
. unwrap_or ( typ) ,
1596
1585
1597
1586
ty:: Infer ( ty:: FloatVar ( v) ) => self
1598
- . infcx
1599
1587
. inner
1600
1588
. borrow_mut ( )
1601
1589
. float_unification_table
1602
1590
. probe_value ( v)
1603
- . map ( |v| v. to_type ( self . infcx . tcx ) )
1591
+ . map ( |v| v. to_type ( self . tcx ) )
1604
1592
. unwrap_or ( typ) ,
1605
1593
1606
1594
_ => typ,
1607
1595
}
1608
1596
}
1609
1597
1610
- // `resolver.shallow_resolve_changed(ty)` is equivalent to
1611
- // `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
1612
- // inlined, despite being large, because it has only two call sites that
1613
- // are extremely hot.
1598
+ /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
1599
+ /// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
1600
+ /// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
1601
+ ///
1602
+ /// However, `ty_or_const_infer_var_changed` is more efficient. It's always
1603
+ /// inlined, despite being large, because it has only two call sites that
1604
+ /// are extremely hot (both in `traits::fulfill`'s checking of `stalled_on`
1605
+ /// inference variables), and it handles both `Ty` and `ty::Const` without
1606
+ /// having to resort to storing full `GenericArg`s in `stalled_on`.
1614
1607
#[ inline( always) ]
1615
- pub fn shallow_resolve_changed ( & self , infer : ty :: InferTy ) -> bool {
1616
- match infer {
1617
- ty :: TyVar ( v) => {
1608
+ pub fn ty_or_const_infer_var_changed ( & self , infer_var : TyOrConstInferVar < ' tcx > ) -> bool {
1609
+ match infer_var {
1610
+ TyOrConstInferVar :: Ty ( v) => {
1618
1611
use self :: type_variable:: TypeVariableValue ;
1619
1612
1620
- // If `inlined_probe` returns a `Known` value its `kind` never
1621
- // matches `infer `.
1622
- match self . infcx . inner . borrow_mut ( ) . type_variables . inlined_probe ( v) {
1613
+ // If `inlined_probe` returns a `Known` value, it never equals
1614
+ // `ty::Infer(ty::TyVar(v)) `.
1615
+ match self . inner . borrow_mut ( ) . type_variables . inlined_probe ( v) {
1623
1616
TypeVariableValue :: Unknown { .. } => false ,
1624
1617
TypeVariableValue :: Known { .. } => true ,
1625
1618
}
1626
1619
}
1627
1620
1628
- ty :: IntVar ( v) => {
1629
- // If inlined_probe_value returns a value it's always a
1621
+ TyOrConstInferVar :: TyInt ( v) => {
1622
+ // If ` inlined_probe_value` returns a value it's always a
1630
1623
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
1631
1624
// `ty::Infer(_)`.
1632
- self . infcx . inner . borrow_mut ( ) . int_unification_table . inlined_probe_value ( v) . is_some ( )
1625
+ self . inner . borrow_mut ( ) . int_unification_table . inlined_probe_value ( v) . is_some ( )
1633
1626
}
1634
1627
1635
- ty :: FloatVar ( v) => {
1636
- // If inlined_probe_value returns a value it's always a
1628
+ TyOrConstInferVar :: TyFloat ( v) => {
1629
+ // If `probe_value` returns a value it's always a
1637
1630
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
1638
1631
//
1639
1632
// Not `inlined_probe_value(v)` because this call site is colder.
1640
- self . infcx . inner . borrow_mut ( ) . float_unification_table . probe_value ( v) . is_some ( )
1633
+ self . inner . borrow_mut ( ) . float_unification_table . probe_value ( v) . is_some ( )
1641
1634
}
1642
1635
1643
- _ => unreachable ! ( ) ,
1636
+ TyOrConstInferVar :: Const ( v) => {
1637
+ // If `probe_value` returns a `Known` value, it never equals
1638
+ // `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
1639
+ //
1640
+ // Not `inlined_probe_value(v)` because this call site is colder.
1641
+ match self . inner . borrow_mut ( ) . const_unification_table . probe_value ( v) . val {
1642
+ ConstVariableValue :: Unknown { .. } => false ,
1643
+ ConstVariableValue :: Known { .. } => true ,
1644
+ }
1645
+ }
1646
+ }
1647
+ }
1648
+ }
1649
+
1650
+ /// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently
1651
+ /// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
1652
+ #[ derive( Copy , Clone , Debug ) ]
1653
+ pub enum TyOrConstInferVar < ' tcx > {
1654
+ /// Equivalent to `ty::Infer(ty::TyVar(_))`.
1655
+ Ty ( TyVid ) ,
1656
+ /// Equivalent to `ty::Infer(ty::IntVar(_))`.
1657
+ TyInt ( IntVid ) ,
1658
+ /// Equivalent to `ty::Infer(ty::FloatVar(_))`.
1659
+ TyFloat ( FloatVid ) ,
1660
+
1661
+ /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
1662
+ Const ( ConstVid < ' tcx > ) ,
1663
+ }
1664
+
1665
+ impl TyOrConstInferVar < ' tcx > {
1666
+ /// Tries to extract an inference variable from a type or a constant, returns `None`
1667
+ /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
1668
+ /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
1669
+ pub fn maybe_from_generic_arg ( arg : GenericArg < ' tcx > ) -> Option < Self > {
1670
+ match arg. unpack ( ) {
1671
+ GenericArgKind :: Type ( ty) => Self :: maybe_from_ty ( ty) ,
1672
+ GenericArgKind :: Const ( ct) => Self :: maybe_from_const ( ct) ,
1673
+ GenericArgKind :: Lifetime ( _) => None ,
1644
1674
}
1645
1675
}
1676
+
1677
+ /// Tries to extract an inference variable from a type, returns `None`
1678
+ /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
1679
+ pub fn maybe_from_ty ( ty : Ty < ' tcx > ) -> Option < Self > {
1680
+ match ty. kind {
1681
+ ty:: Infer ( ty:: TyVar ( v) ) => Some ( TyOrConstInferVar :: Ty ( v) ) ,
1682
+ ty:: Infer ( ty:: IntVar ( v) ) => Some ( TyOrConstInferVar :: TyInt ( v) ) ,
1683
+ ty:: Infer ( ty:: FloatVar ( v) ) => Some ( TyOrConstInferVar :: TyFloat ( v) ) ,
1684
+ _ => None ,
1685
+ }
1686
+ }
1687
+
1688
+ /// Tries to extract an inference variable from a constant, returns `None`
1689
+ /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
1690
+ pub fn maybe_from_const ( ct : & ' tcx ty:: Const < ' tcx > ) -> Option < Self > {
1691
+ match ct. val {
1692
+ ty:: ConstKind :: Infer ( InferConst :: Var ( v) ) => Some ( TyOrConstInferVar :: Const ( v) ) ,
1693
+ _ => None ,
1694
+ }
1695
+ }
1696
+ }
1697
+
1698
+ struct ShallowResolver < ' a , ' tcx > {
1699
+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
1646
1700
}
1647
1701
1648
1702
impl < ' a , ' tcx > TypeFolder < ' tcx > for ShallowResolver < ' a , ' tcx > {
@@ -1651,7 +1705,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
1651
1705
}
1652
1706
1653
1707
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1654
- self . shallow_resolve ( ty)
1708
+ self . infcx . shallow_resolve_ty ( ty)
1655
1709
}
1656
1710
1657
1711
fn fold_const ( & mut self , ct : & ' tcx ty:: Const < ' tcx > ) -> & ' tcx ty:: Const < ' tcx > {
0 commit comments