@@ -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 ) ,
@@ -1608,14 +1609,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1608
1609
}
1609
1610
}
1610
1611
1611
- /// `infer_ty_changed(infer_ty)` is equivalent to `shallow_resolve(ty) != ty`
1612
- /// (where `ty.kind = ty::Infer(infer_ty)`), but more efficient. It's always
1612
+ /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
1613
+ /// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
1614
+ /// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
1615
+ ///
1616
+ /// However, `ty_or_const_infer_var_changed` is more efficient. It's always
1613
1617
/// inlined, despite being large, because it has only two call sites that
1614
- /// are extremely hot.
1618
+ /// are extremely hot (both in `traits::fulfill`'s checking of `stalled_on`
1619
+ /// inference variables), and it handles both `Ty` and `ty::Const` without
1620
+ /// having to resort to storing full `GenericArg`s in `stalled_on`.
1615
1621
#[ inline( always) ]
1616
- pub fn infer_ty_changed ( & self , infer_ty : ty :: InferTy ) -> bool {
1617
- match infer_ty {
1618
- ty :: TyVar ( v) => {
1622
+ pub fn ty_or_const_infer_var_changed ( & self , infer_var : TyOrConstInferVar < ' tcx > ) -> bool {
1623
+ match infer_var {
1624
+ TyOrConstInferVar :: Ty ( v) => {
1619
1625
use self :: type_variable:: TypeVariableValue ;
1620
1626
1621
1627
// If `inlined_probe` returns a `Known` value, it never equals
@@ -1626,22 +1632,79 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1626
1632
}
1627
1633
}
1628
1634
1629
- ty :: IntVar ( v) => {
1635
+ TyOrConstInferVar :: TyInt ( v) => {
1630
1636
// If `inlined_probe_value` returns a value it's always a
1631
1637
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
1632
1638
// `ty::Infer(_)`.
1633
1639
self . inner . borrow_mut ( ) . int_unification_table . inlined_probe_value ( v) . is_some ( )
1634
1640
}
1635
1641
1636
- ty :: FloatVar ( v) => {
1637
- // If `inlined_probe_value ` returns a value it's always a
1642
+ TyOrConstInferVar :: TyFloat ( v) => {
1643
+ // If `probe_value ` returns a value it's always a
1638
1644
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
1639
1645
//
1640
1646
// Not `inlined_probe_value(v)` because this call site is colder.
1641
1647
self . inner . borrow_mut ( ) . float_unification_table . probe_value ( v) . is_some ( )
1642
1648
}
1643
1649
1644
- _ => unreachable ! ( ) ,
1650
+ TyOrConstInferVar :: Const ( v) => {
1651
+ // If `probe_value` returns a `Known` value, it never equals
1652
+ // `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
1653
+ //
1654
+ // Not `inlined_probe_value(v)` because this call site is colder.
1655
+ match self . inner . borrow_mut ( ) . const_unification_table . probe_value ( v) . val {
1656
+ ConstVariableValue :: Unknown { .. } => false ,
1657
+ ConstVariableValue :: Known { .. } => true ,
1658
+ }
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+
1664
+ /// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently
1665
+ /// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
1666
+ #[ derive( Copy , Clone , Debug ) ]
1667
+ pub enum TyOrConstInferVar < ' tcx > {
1668
+ /// Equivalent to `ty::Infer(ty::TyVar(_))`.
1669
+ Ty ( TyVid ) ,
1670
+ /// Equivalent to `ty::Infer(ty::IntVar(_))`.
1671
+ TyInt ( IntVid ) ,
1672
+ /// Equivalent to `ty::Infer(ty::FloatVar(_))`.
1673
+ TyFloat ( FloatVid ) ,
1674
+
1675
+ /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
1676
+ Const ( ConstVid < ' tcx > ) ,
1677
+ }
1678
+
1679
+ impl TyOrConstInferVar < ' tcx > {
1680
+ /// Tries to extract an inference variable from a type or a constant, returns `None`
1681
+ /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
1682
+ /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
1683
+ pub fn maybe_from_generic_arg ( arg : GenericArg < ' tcx > ) -> Option < Self > {
1684
+ match arg. unpack ( ) {
1685
+ GenericArgKind :: Type ( ty) => Self :: maybe_from_ty ( ty) ,
1686
+ GenericArgKind :: Const ( ct) => Self :: maybe_from_const ( ct) ,
1687
+ GenericArgKind :: Lifetime ( _) => None ,
1688
+ }
1689
+ }
1690
+
1691
+ /// Tries to extract an inference variable from a type, returns `None`
1692
+ /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
1693
+ pub fn maybe_from_ty ( ty : Ty < ' tcx > ) -> Option < Self > {
1694
+ match ty. kind {
1695
+ ty:: Infer ( ty:: TyVar ( v) ) => Some ( TyOrConstInferVar :: Ty ( v) ) ,
1696
+ ty:: Infer ( ty:: IntVar ( v) ) => Some ( TyOrConstInferVar :: TyInt ( v) ) ,
1697
+ ty:: Infer ( ty:: FloatVar ( v) ) => Some ( TyOrConstInferVar :: TyFloat ( v) ) ,
1698
+ _ => None ,
1699
+ }
1700
+ }
1701
+
1702
+ /// Tries to extract an inference variable from a constant, returns `None`
1703
+ /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
1704
+ pub fn maybe_from_const ( ct : & ' tcx ty:: Const < ' tcx > ) -> Option < Self > {
1705
+ match ct. val {
1706
+ ty:: ConstKind :: Infer ( InferConst :: Var ( v) ) => Some ( TyOrConstInferVar :: Const ( v) ) ,
1707
+ _ => None ,
1645
1708
}
1646
1709
}
1647
1710
}
0 commit comments