@@ -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 ) ,
@@ -1347,8 +1348,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13471348 where
13481349 T : TypeFoldable < ' tcx > ,
13491350 {
1350- let mut r = ShallowResolver :: new ( self ) ;
1351- value. fold_with ( & mut r)
1351+ value. fold_with ( & mut ShallowResolver { infcx : self } )
13521352 }
13531353
13541354 pub fn root_var ( & self , var : ty:: TyVid ) -> ty:: TyVid {
@@ -1551,22 +1551,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15511551 // variables, thus we don't need to substitute back the original values.
15521552 self . tcx . const_eval_resolve ( param_env, def_id, substs, promoted, span)
15531553 }
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- }
15651554
15661555 /// If `typ` is a type variable of some kind, resolve it one level
15671556 /// (but do not resolve types found in the result). If `typ` is
15681557 /// 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 > {
15701560 match typ. kind {
15711561 ty:: Infer ( ty:: TyVar ( v) ) => {
15721562 // Not entirely obvious: if `typ` is a type variable,
@@ -1580,69 +1570,133 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
15801570 // depth.
15811571 //
15821572 // 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)
15861576 }
15871577
15881578 ty:: Infer ( ty:: IntVar ( v) ) => self
1589- . infcx
15901579 . inner
15911580 . borrow_mut ( )
15921581 . int_unification_table
15931582 . probe_value ( v)
1594- . map ( |v| v. to_type ( self . infcx . tcx ) )
1583+ . map ( |v| v. to_type ( self . tcx ) )
15951584 . unwrap_or ( typ) ,
15961585
15971586 ty:: Infer ( ty:: FloatVar ( v) ) => self
1598- . infcx
15991587 . inner
16001588 . borrow_mut ( )
16011589 . float_unification_table
16021590 . probe_value ( v)
1603- . map ( |v| v. to_type ( self . infcx . tcx ) )
1591+ . map ( |v| v. to_type ( self . tcx ) )
16041592 . unwrap_or ( typ) ,
16051593
16061594 _ => typ,
16071595 }
16081596 }
16091597
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`.
16141607 #[ 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) => {
16181611 use self :: type_variable:: TypeVariableValue ;
16191612
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) {
16231616 TypeVariableValue :: Unknown { .. } => false ,
16241617 TypeVariableValue :: Known { .. } => true ,
16251618 }
16261619 }
16271620
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
16301623 // `ty::Int(_)` or `ty::UInt(_)`, which never matches a
16311624 // `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 ( )
16331626 }
16341627
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
16371630 // `ty::Float(_)`, which never matches a `ty::Infer(_)`.
16381631 //
16391632 // 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 ( )
16411634 }
16421635
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 ,
16441674 }
16451675 }
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 > ,
16461700}
16471701
16481702impl < ' a , ' tcx > TypeFolder < ' tcx > for ShallowResolver < ' a , ' tcx > {
@@ -1651,7 +1705,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
16511705 }
16521706
16531707 fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1654- self . shallow_resolve ( ty)
1708+ self . infcx . shallow_resolve_ty ( ty)
16551709 }
16561710
16571711 fn fold_const ( & mut self , ct : & ' tcx ty:: Const < ' tcx > ) -> & ' tcx ty:: Const < ' tcx > {
0 commit comments