@@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap;
24
24
use middle:: mem_categorization as mc;
25
25
use middle:: mem_categorization:: McResult ;
26
26
use middle:: region:: CodeExtent ;
27
+ use mir:: tcx:: LvalueTy ;
27
28
use ty:: subst;
28
29
use ty:: subst:: Substs ;
29
30
use ty:: subst:: Subst ;
@@ -35,7 +36,7 @@ use ty::fold::TypeFoldable;
35
36
use ty:: relate:: { Relate , RelateResult , TypeRelation } ;
36
37
use traits:: { self , PredicateObligations , ProjectionMode } ;
37
38
use rustc_data_structures:: unify:: { self , UnificationTable } ;
38
- use std:: cell:: { Cell , RefCell , Ref } ;
39
+ use std:: cell:: { Cell , RefCell , Ref , RefMut } ;
39
40
use std:: fmt;
40
41
use syntax:: ast;
41
42
use syntax:: codemap;
@@ -72,10 +73,36 @@ pub type Bound<T> = Option<T>;
72
73
pub type UnitResult < ' tcx > = RelateResult < ' tcx , ( ) > ; // "unify result"
73
74
pub type FixupResult < T > = Result < T , FixupError > ; // "fixup result"
74
75
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
+
75
102
pub struct InferCtxt < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
76
103
pub tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
77
104
78
- pub tables : & ' a RefCell < ty :: Tables < ' tcx > > ,
105
+ pub tables : InferTables < ' a , ' gcx , ' tcx > ,
79
106
80
107
// We instantiate UnificationTable with bounds<Ty> because the
81
108
// types that might instantiate a general type variable have an
@@ -390,48 +417,106 @@ impl fmt::Display for FixupError {
390
417
}
391
418
}
392
419
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
400
487
{
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)
405
498
} else {
406
- & tcx . tables
499
+ InferTables :: Global ( & global_tcx . tables )
407
500
} ;
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 {
409
505
tcx : tcx,
410
506
tables : tables,
411
507
type_variables : RefCell :: new ( type_variable:: TypeVariableTable :: new ( ) ) ,
412
508
int_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
413
509
float_unification_table : RefCell :: new ( UnificationTable :: new ( ) ) ,
414
510
region_vars : RegionVarBindings :: new ( tcx) ,
415
- parameter_environment : param_env. unwrap_or ( tcx . empty_parameter_environment ( ) ) ,
511
+ parameter_environment : param_env,
416
512
selection_cache : traits:: SelectionCache :: new ( ) ,
417
513
evaluation_cache : traits:: EvaluationCache :: new ( ) ,
418
514
reported_trait_errors : RefCell :: new ( FnvHashSet ( ) ) ,
419
- normalize : false ,
515
+ normalize : normalize ,
420
516
projection_mode : projection_mode,
421
- tainted_by_errors_flag : Cell :: new ( false ) ,
517
+ tainted_by_errors_flag : Cell :: new ( false ) ,
422
518
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
+ } ) )
435
520
}
436
521
}
437
522
@@ -459,10 +544,54 @@ pub struct CombinedSnapshot {
459
544
region_vars_snapshot : RegionSnapshot ,
460
545
}
461
546
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
+
462
591
// NOTE: Callable from trans only!
463
592
impl < ' a , ' tcx > TyCtxt < ' a , ' tcx , ' tcx > {
464
593
pub fn normalize_associated_type < T > ( self , value : & T ) -> T
465
- where T : TypeFoldable < ' tcx >
594
+ where T : TransNormalize < ' tcx >
466
595
{
467
596
debug ! ( "normalize_associated_type(t={:?})" , value) ;
468
597
@@ -472,15 +601,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
472
601
return value;
473
602
}
474
603
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 )
477
606
} )
478
607
}
479
608
}
480
609
481
610
impl < ' 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 >
484
613
{
485
614
let mut selcx = traits:: SelectionContext :: new ( self ) ;
486
615
let cause = traits:: ObligationCause :: dummy ( ) ;
@@ -503,16 +632,21 @@ pub fn drain_fulfillment_cx_or_panic<T>(&self,
503
632
span : Span ,
504
633
fulfill_cx : & mut traits:: FulfillmentContext < ' tcx > ,
505
634
result : & T )
506
- -> T
507
- where T : TypeFoldable < ' tcx >
635
+ -> T :: Lifted
636
+ where T : TypeFoldable < ' tcx > + ty :: Lift < ' gcx >
508
637
{
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) {
510
640
Ok ( v) => v,
511
641
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) ;
516
650
}
517
651
}
518
652
}
@@ -1449,18 +1583,16 @@ pub fn drain_fulfillment_cx<T>(&self,
1449
1583
self . resolve_type_vars_or_error ( & ty)
1450
1584
}
1451
1585
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
-
1458
1586
pub fn type_moves_by_default ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
1459
1587
let ty = self . resolve_type_vars_if_possible ( & ty) ;
1460
1588
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 {
1464
1596
return ty. moves_by_default ( self . tcx . global_tcx ( ) , self . param_env ( ) , span) ;
1465
1597
}
1466
1598
}
@@ -1527,7 +1659,7 @@ pub fn drain_fulfillment_cx<T>(&self,
1527
1659
// during trans, we see closure ids from other traits.
1528
1660
// That may require loading the closure data out of the
1529
1661
// cstore.
1530
- Some ( ty :: Tables :: closure_kind ( & self . tables , self . tcx , def_id) )
1662
+ Some ( self . tcx . closure_kind ( def_id) )
1531
1663
}
1532
1664
}
1533
1665
@@ -1536,12 +1668,13 @@ pub fn drain_fulfillment_cx<T>(&self,
1536
1668
substs : ty:: ClosureSubsts < ' tcx > )
1537
1669
-> ty:: ClosureTy < ' tcx >
1538
1670
{
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
+ }
1544
1676
1677
+ let closure_ty = self . tcx . closure_type ( def_id, substs) ;
1545
1678
if self . normalize {
1546
1679
let closure_ty = self . tcx . erase_regions ( & closure_ty) ;
1547
1680
0 commit comments