@@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap;
2424use middle:: mem_categorization as mc;
2525use middle:: mem_categorization:: McResult ;
2626use middle:: region:: CodeExtent ;
27+ use mir:: tcx:: LvalueTy ;
2728use ty:: subst;
2829use ty:: subst:: Substs ;
2930use ty:: subst:: Subst ;
@@ -35,7 +36,7 @@ use ty::fold::TypeFoldable;
3536use ty:: relate:: { Relate , RelateResult , TypeRelation } ;
3637use traits:: { self , PredicateObligations , ProjectionMode } ;
3738use rustc_data_structures:: unify:: { self , UnificationTable } ;
38- use std:: cell:: { Cell , RefCell , Ref } ;
39+ use std:: cell:: { Cell , RefCell , Ref , RefMut } ;
3940use std:: fmt;
4041use syntax:: ast;
4142use syntax:: codemap;
@@ -72,10 +73,36 @@ pub type Bound<T> = Option<T>;
7273pub type UnitResult < ' tcx > = RelateResult < ' tcx , ( ) > ; // "unify result"
7374pub type FixupResult < T > = Result < T , FixupError > ; // "fixup result"
7475
76+ /// A version of &ty::Tables which can be global or local.
77+ /// Only the local version supports borrow_mut.
78+ #[ derive( Copy , Clone ) ]
79+ pub enum InferTables < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
80+ Global ( & ' a RefCell < ty:: Tables < ' gcx > > ) ,
81+ Local ( & ' a RefCell < ty:: Tables < ' tcx > > )
82+ }
83+
84+ impl < ' a , ' gcx , ' tcx > InferTables < ' a , ' gcx , ' tcx > {
85+ pub fn borrow ( self ) -> Ref < ' a , ty:: Tables < ' tcx > > {
86+ match self {
87+ InferTables :: Global ( tables) => tables. borrow ( ) ,
88+ InferTables :: Local ( tables) => tables. borrow ( )
89+ }
90+ }
91+
92+ pub fn borrow_mut ( self ) -> RefMut < ' a , ty:: Tables < ' tcx > > {
93+ match self {
94+ InferTables :: Global ( _) => {
95+ bug ! ( "InferTables: infcx.tables.borrow_mut() outside of type-checking" ) ;
96+ }
97+ InferTables :: Local ( tables) => tables. borrow_mut ( )
98+ }
99+ }
100+ }
101+
75102pub struct InferCtxt < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
76103 pub tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
77104
78- pub tables : & ' a RefCell < ty :: Tables < ' tcx > > ,
105+ pub tables : InferTables < ' a , ' gcx , ' tcx > ,
79106
80107 // We instantiate UnificationTable with bounds<Ty> because the
81108 // types that might instantiate a general type variable have an
@@ -390,48 +417,106 @@ impl fmt::Display for FixupError {
390417 }
391418}
392419
393- impl < ' a , ' tcx > InferCtxt < ' a , ' tcx , ' tcx > {
394- pub fn enter < F , R > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
395- tables : Option < ty:: Tables < ' tcx > > ,
396- param_env : Option < ty:: ParameterEnvironment < ' tcx > > ,
397- projection_mode : ProjectionMode ,
398- f : F ) -> R
399- where F : for < ' b > FnOnce ( InferCtxt < ' b , ' tcx , ' tcx > ) -> R
420+ /// Helper type of a temporary returned by tcx.infer_ctxt(...).
421+ /// Necessary because we can't write the following bound:
422+ /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
423+ pub struct InferCtxtBuilder < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
424+ global_tcx : TyCtxt < ' a , ' gcx , ' gcx > ,
425+ arenas : ty:: CtxtArenas < ' tcx > ,
426+ tables : Option < RefCell < ty:: Tables < ' tcx > > > ,
427+ param_env : Option < ty:: ParameterEnvironment < ' gcx > > ,
428+ projection_mode : ProjectionMode ,
429+ normalize : bool
430+ }
431+
432+ impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' gcx > {
433+ pub fn infer_ctxt ( self ,
434+ tables : Option < ty:: Tables < ' tcx > > ,
435+ param_env : Option < ty:: ParameterEnvironment < ' gcx > > ,
436+ projection_mode : ProjectionMode )
437+ -> InferCtxtBuilder < ' a , ' gcx , ' tcx > {
438+ InferCtxtBuilder {
439+ global_tcx : self ,
440+ arenas : ty:: CtxtArenas :: new ( ) ,
441+ tables : tables. map ( RefCell :: new) ,
442+ param_env : param_env,
443+ projection_mode : projection_mode,
444+ normalize : false
445+ }
446+ }
447+
448+ pub fn normalizing_infer_ctxt ( self , projection_mode : ProjectionMode )
449+ -> InferCtxtBuilder < ' a , ' gcx , ' tcx > {
450+ InferCtxtBuilder {
451+ global_tcx : self ,
452+ arenas : ty:: CtxtArenas :: new ( ) ,
453+ tables : None ,
454+ param_env : None ,
455+ projection_mode : projection_mode,
456+ normalize : false
457+ }
458+ }
459+
460+ /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
461+ /// for MemCategorizationContext/ExprUseVisitor.
462+ /// If any inference functionality is used, ICEs will occur.
463+ pub fn borrowck_fake_infer_ctxt ( self , param_env : ty:: ParameterEnvironment < ' gcx > )
464+ -> InferCtxt < ' a , ' gcx , ' gcx > {
465+ InferCtxt {
466+ tcx : self ,
467+ tables : InferTables :: Global ( & self . tables ) ,
468+ type_variables : RefCell :: new ( type_variable:: TypeVariableTable :: new ( ) ) ,
469+ int_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
470+ float_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
471+ region_vars : RegionVarBindings :: new ( self ) ,
472+ parameter_environment : param_env,
473+ selection_cache : traits:: SelectionCache :: new ( ) ,
474+ evaluation_cache : traits:: EvaluationCache :: new ( ) ,
475+ reported_trait_errors : RefCell :: new ( FnvHashSet ( ) ) ,
476+ normalize : false ,
477+ projection_mode : ProjectionMode :: AnyFinal ,
478+ tainted_by_errors_flag : Cell :: new ( false ) ,
479+ err_count_on_creation : self . sess . err_count ( )
480+ }
481+ }
482+ }
483+
484+ impl < ' a , ' gcx , ' tcx > InferCtxtBuilder < ' a , ' gcx , ' tcx > {
485+ pub fn enter < F , R > ( & ' tcx mut self , f : F ) -> R
486+ where F : for < ' b > FnOnce ( InferCtxt < ' b , ' gcx , ' tcx > ) -> R
400487 {
401- let new_tables;
402- let tables = if let Some ( tables) = tables {
403- new_tables = RefCell :: new ( tables) ;
404- & new_tables
488+ let InferCtxtBuilder {
489+ global_tcx,
490+ ref arenas,
491+ ref tables,
492+ ref mut param_env,
493+ projection_mode,
494+ normalize
495+ } = * self ;
496+ let tables = if let Some ( ref tables) = * tables {
497+ InferTables :: Local ( tables)
405498 } else {
406- & tcx . tables
499+ InferTables :: Global ( & global_tcx . tables )
407500 } ;
408- f ( InferCtxt {
501+ let param_env = param_env. take ( ) . unwrap_or_else ( || {
502+ global_tcx. empty_parameter_environment ( )
503+ } ) ;
504+ global_tcx. enter_local ( arenas, |tcx| f ( InferCtxt {
409505 tcx : tcx,
410506 tables : tables,
411507 type_variables : RefCell :: new ( type_variable:: TypeVariableTable :: new ( ) ) ,
412508 int_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
413509 float_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
414510 region_vars : RegionVarBindings :: new ( tcx) ,
415- parameter_environment : param_env. unwrap_or ( tcx . empty_parameter_environment ( ) ) ,
511+ parameter_environment : param_env,
416512 selection_cache : traits:: SelectionCache :: new ( ) ,
417513 evaluation_cache : traits:: EvaluationCache :: new ( ) ,
418514 reported_trait_errors : RefCell :: new ( FnvHashSet ( ) ) ,
419- normalize : false ,
515+ normalize : normalize ,
420516 projection_mode : projection_mode,
421- tainted_by_errors_flag : Cell :: new ( false ) ,
517+ tainted_by_errors_flag : Cell :: new ( false ) ,
422518 err_count_on_creation : tcx. sess . err_count ( )
423- } )
424- }
425-
426- pub fn enter_normalizing < F , R > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
427- projection_mode : ProjectionMode ,
428- f : F ) -> R
429- where F : for < ' b > FnOnce ( InferCtxt < ' b , ' tcx , ' tcx > ) -> R
430- {
431- InferCtxt :: enter ( tcx, None , None , projection_mode, |mut infcx| {
432- infcx. normalize = true ;
433- f ( infcx)
434- } )
519+ } ) )
435520 }
436521}
437522
@@ -459,10 +544,54 @@ pub struct CombinedSnapshot {
459544 region_vars_snapshot : RegionSnapshot ,
460545}
461546
547+ /// Helper trait for shortening the lifetimes inside a
548+ /// value for post-type-checking normalization.
549+ pub trait TransNormalize < ' gcx > : TypeFoldable < ' gcx > {
550+ fn trans_normalize < ' a , ' tcx > ( & self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > ) -> Self ;
551+ }
552+
553+ macro_rules! items { ( $( $item: item) +) => ( $( $item) +) }
554+ macro_rules! impl_trans_normalize {
555+ ( $lt_gcx: tt, $( $ty: ty) ,+) => {
556+ items!( $( impl <$lt_gcx> TransNormalize <$lt_gcx> for $ty {
557+ fn trans_normalize<' a, ' tcx>( & self ,
558+ infcx: & InferCtxt <' a, $lt_gcx, ' tcx>)
559+ -> Self {
560+ infcx. normalize_projections_in( self )
561+ }
562+ } ) +) ;
563+ }
564+ }
565+
566+ impl_trans_normalize ! ( ' gcx,
567+ Ty <' gcx>,
568+ & ' gcx Substs <' gcx>,
569+ ty:: FnSig <' gcx>,
570+ ty:: FnOutput <' gcx>,
571+ & ' gcx ty:: BareFnTy <' gcx>,
572+ ty:: ClosureSubsts <' gcx>,
573+ ty:: PolyTraitRef <' gcx>
574+ ) ;
575+
576+ impl < ' gcx > TransNormalize < ' gcx > for LvalueTy < ' gcx > {
577+ fn trans_normalize < ' a , ' tcx > ( & self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > ) -> Self {
578+ match * self {
579+ LvalueTy :: Ty { ty } => LvalueTy :: Ty { ty : ty. trans_normalize ( infcx) } ,
580+ LvalueTy :: Downcast { adt_def, substs, variant_index } => {
581+ LvalueTy :: Downcast {
582+ adt_def : adt_def,
583+ substs : substs. trans_normalize ( infcx) ,
584+ variant_index : variant_index
585+ }
586+ }
587+ }
588+ }
589+ }
590+
462591// NOTE: Callable from trans only!
463592impl < ' a , ' tcx > TyCtxt < ' a , ' tcx , ' tcx > {
464593 pub fn normalize_associated_type < T > ( self , value : & T ) -> T
465- where T : TypeFoldable < ' tcx >
594+ where T : TransNormalize < ' tcx >
466595 {
467596 debug ! ( "normalize_associated_type(t={:?})" , value) ;
468597
@@ -472,15 +601,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
472601 return value;
473602 }
474603
475- InferCtxt :: enter ( self , None , None , ProjectionMode :: Any , |infcx| {
476- infcx . normalize_projections_in ( & value )
604+ self . infer_ctxt ( None , None , ProjectionMode :: Any ) . enter ( |infcx| {
605+ value . trans_normalize ( & infcx )
477606 } )
478607 }
479608}
480609
481610impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
482- fn normalize_projections_in < T > ( & self , value : & T ) -> T
483- where T : TypeFoldable < ' tcx >
611+ fn normalize_projections_in < T > ( & self , value : & T ) -> T :: Lifted
612+ where T : TypeFoldable < ' tcx > + ty :: Lift < ' gcx >
484613 {
485614 let mut selcx = traits:: SelectionContext :: new ( self ) ;
486615 let cause = traits:: ObligationCause :: dummy ( ) ;
@@ -503,16 +632,21 @@ pub fn drain_fulfillment_cx_or_panic<T>(&self,
503632 span : Span ,
504633 fulfill_cx : & mut traits:: FulfillmentContext < ' tcx > ,
505634 result : & T )
506- -> T
507- where T : TypeFoldable < ' tcx >
635+ -> T :: Lifted
636+ where T : TypeFoldable < ' tcx > + ty :: Lift < ' gcx >
508637{
509- match self . drain_fulfillment_cx ( fulfill_cx, result) {
638+ let when = "resolving bounds after type-checking" ;
639+ let v = match self . drain_fulfillment_cx ( fulfill_cx, result) {
510640 Ok ( v) => v,
511641 Err ( errors) => {
512- span_bug ! (
513- span,
514- "Encountered errors `{:?}` fulfilling during trans" ,
515- errors) ;
642+ span_bug ! ( span, "Encountered errors `{:?}` {}" , errors, when) ;
643+ }
644+ } ;
645+
646+ match self . tcx . lift_to_global ( & v) {
647+ Some ( v) => v,
648+ None => {
649+ span_bug ! ( span, "Uninferred types/regions in `{:?}` {}" , v, when) ;
516650 }
517651 }
518652}
@@ -1449,18 +1583,16 @@ pub fn drain_fulfillment_cx<T>(&self,
14491583 self . resolve_type_vars_or_error ( & ty)
14501584 }
14511585
1452- pub fn tables_are_tcx_tables ( & self ) -> bool {
1453- let tables: & RefCell < ty:: Tables > = & self . tables ;
1454- let tcx_tables: & RefCell < ty:: Tables > = & self . tcx . tables ;
1455- tables as * const _ as usize == tcx_tables as * const _ as usize
1456- }
1457-
14581586 pub fn type_moves_by_default ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
14591587 let ty = self . resolve_type_vars_if_possible ( & ty) ;
14601588 if let Some ( ty) = self . tcx . lift_to_global ( & ty) {
1461- // HACK(eddyb) Temporarily handle infer type in the global tcx.
1462- if !ty. needs_infer ( ) &&
1463- !( ty. has_closure_types ( ) && !self . tables_are_tcx_tables ( ) ) {
1589+ // Even if the type may have no inference variables, during
1590+ // type-checking closure types are in local tables only.
1591+ let local_closures = match self . tables {
1592+ InferTables :: Local ( _) => ty. has_closure_types ( ) ,
1593+ InferTables :: Global ( _) => false
1594+ } ;
1595+ if !local_closures {
14641596 return ty. moves_by_default ( self . tcx . global_tcx ( ) , self . param_env ( ) , span) ;
14651597 }
14661598 }
@@ -1527,7 +1659,7 @@ pub fn drain_fulfillment_cx<T>(&self,
15271659 // during trans, we see closure ids from other traits.
15281660 // That may require loading the closure data out of the
15291661 // cstore.
1530- Some ( ty :: Tables :: closure_kind ( & self . tables , self . tcx , def_id) )
1662+ Some ( self . tcx . closure_kind ( def_id) )
15311663 }
15321664 }
15331665
@@ -1536,12 +1668,13 @@ pub fn drain_fulfillment_cx<T>(&self,
15361668 substs : ty:: ClosureSubsts < ' tcx > )
15371669 -> ty:: ClosureTy < ' tcx >
15381670 {
1539- let closure_ty =
1540- ty :: Tables :: closure_type ( self . tables ,
1541- self . tcx ,
1542- def_id ,
1543- substs ) ;
1671+ if let InferTables :: Local ( tables ) = self . tables {
1672+ if let Some ( ty ) = tables . borrow ( ) . closure_tys . get ( & def_id ) {
1673+ return ty . subst ( self . tcx , substs . func_substs ) ;
1674+ }
1675+ }
15441676
1677+ let closure_ty = self . tcx . closure_type ( def_id, substs) ;
15451678 if self . normalize {
15461679 let closure_ty = self . tcx . erase_regions ( & closure_ty) ;
15471680
0 commit comments