@@ -19,7 +19,7 @@ use rustc::traits::select;
1919use rustc:: ty:: error:: { ExpectedFound , TypeError , UnconstrainedNumeric } ;
2020use rustc:: ty:: fold:: { TypeFoldable , TypeFolder } ;
2121use rustc:: ty:: relate:: RelateResult ;
22- use rustc:: ty:: subst:: { GenericArg , InternalSubsts , SubstsRef } ;
22+ use rustc:: ty:: subst:: { GenericArg , GenericArgKind , InternalSubsts , SubstsRef } ;
2323pub use rustc:: ty:: IntVarValue ;
2424use rustc:: ty:: { self , GenericParamDefKind , InferConst , Ty , TyCtxt } ;
2525use rustc:: ty:: { ConstVid , FloatVid , IntVid , TyVid } ;
@@ -501,6 +501,7 @@ impl NLLRegionVariableOrigin {
501501 }
502502}
503503
504+ // FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`.
504505#[ derive( Copy , Clone , Debug ) ]
505506pub enum FixupError < ' tcx > {
506507 UnresolvedIntTy ( IntVid ) ,
@@ -1608,14 +1609,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16081609 }
16091610 }
16101611
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
16131617 /// 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`.
16151621 #[ 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) => {
16191625 use self :: type_variable:: TypeVariableValue ;
16201626
16211627 // If `inlined_probe` returns a `Known` value, it never equals
@@ -1626,22 +1632,79 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16261632 }
16271633 }
16281634
1629- ty :: IntVar ( v) => {
1635+ TyOrConstInferVar :: TyInt ( v) => {
16301636 // If `inlined_probe_value` returns a value it's always a
16311637 // `ty::Int(_)` or `ty::UInt(_)`, which never matches a
16321638 // `ty::Infer(_)`.
16331639 self . inner . borrow_mut ( ) . int_unification_table . inlined_probe_value ( v) . is_some ( )
16341640 }
16351641
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
16381644 // `ty::Float(_)`, which never matches a `ty::Infer(_)`.
16391645 //
16401646 // Not `inlined_probe_value(v)` because this call site is colder.
16411647 self . inner . borrow_mut ( ) . float_unification_table . probe_value ( v) . is_some ( )
16421648 }
16431649
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 ,
16451708 }
16461709 }
16471710}
0 commit comments