@@ -756,16 +756,6 @@ pub struct ctxt<'tcx> {
756756 /// Caches the representation hints for struct definitions.
757757 pub repr_hint_cache : RefCell < DefIdMap < Rc < Vec < attr:: ReprAttr > > > > ,
758758
759- /// Caches whether types are known to impl Copy. Note that type
760- /// parameters are never placed into this cache, because their
761- /// results are dependent on the parameter environment.
762- pub type_impls_copy_cache : RefCell < HashMap < Ty < ' tcx > , bool > > ,
763-
764- /// Caches whether types are known to impl Sized. Note that type
765- /// parameters are never placed into this cache, because their
766- /// results are dependent on the parameter environment.
767- pub type_impls_sized_cache : RefCell < HashMap < Ty < ' tcx > , bool > > ,
768-
769759 /// Maps Expr NodeId's to their constant qualification.
770760 pub const_qualif_map : RefCell < NodeMap < check_const:: ConstQualif > > ,
771761
@@ -827,6 +817,23 @@ bitflags! {
827817 const NEEDS_SUBST = TypeFlags :: HAS_PARAMS . bits |
828818 TypeFlags :: HAS_SELF . bits |
829819 TypeFlags :: HAS_REGIONS . bits,
820+
821+ // Flags representing the nominal content of a type,
822+ // computed by FlagsComputetion
823+ const NOMINAL_FLAGS = TypeFlags :: HAS_PARAMS . bits |
824+ TypeFlags :: HAS_SELF . bits |
825+ TypeFlags :: HAS_TY_INFER . bits |
826+ TypeFlags :: HAS_RE_INFER . bits |
827+ TypeFlags :: HAS_RE_LATE_BOUND . bits |
828+ TypeFlags :: HAS_REGIONS . bits |
829+ TypeFlags :: HAS_TY_ERR . bits |
830+ TypeFlags :: HAS_PROJECTION . bits,
831+
832+ // Caches for type_is_sized, type_moves_by_default
833+ const SIZEDNESS_CACHED = 1 << 16 ,
834+ const IS_SIZED = 1 << 17 ,
835+ const MOVENESS_CACHED = 1 << 18 ,
836+ const MOVES_BY_DEFAULT = 1 << 19 ,
830837 }
831838}
832839
@@ -859,8 +866,8 @@ macro_rules! sty_debug_print {
859866 ty:: ty_err => /* unimportant */ continue ,
860867 $( ty:: $variant( ..) => & mut $variant, ) *
861868 } ;
862- let region = t. flags. intersects( ty:: TypeFlags :: HAS_RE_INFER ) ;
863- let ty = t. flags. intersects( ty:: TypeFlags :: HAS_TY_INFER ) ;
869+ let region = t. flags. get ( ) . intersects( ty:: TypeFlags :: HAS_RE_INFER ) ;
870+ let ty = t. flags. get ( ) . intersects( ty:: TypeFlags :: HAS_TY_INFER ) ;
864871
865872 variant. total += 1 ;
866873 total. total += 1 ;
@@ -908,7 +915,7 @@ impl<'tcx> ctxt<'tcx> {
908915#[ derive( Debug ) ]
909916pub struct TyS < ' tcx > {
910917 pub sty : sty < ' tcx > ,
911- pub flags : TypeFlags ,
918+ pub flags : Cell < TypeFlags > ,
912919
913920 // the maximal depth of any bound regions appearing in this type.
914921 region_depth : u32 ,
@@ -964,23 +971,23 @@ impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
964971}
965972
966973pub fn type_has_params ( ty : Ty ) -> bool {
967- ty. flags . intersects ( TypeFlags :: HAS_PARAMS )
974+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PARAMS )
968975}
969976pub fn type_has_self ( ty : Ty ) -> bool {
970- ty. flags . intersects ( TypeFlags :: HAS_SELF )
977+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_SELF )
971978}
972979pub fn type_has_ty_infer ( ty : Ty ) -> bool {
973- ty. flags . intersects ( TypeFlags :: HAS_TY_INFER )
980+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_INFER )
974981}
975982pub fn type_needs_infer ( ty : Ty ) -> bool {
976- ty. flags . intersects ( TypeFlags :: HAS_TY_INFER | TypeFlags :: HAS_RE_INFER )
983+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_INFER | TypeFlags :: HAS_RE_INFER )
977984}
978985pub fn type_has_projection ( ty : Ty ) -> bool {
979- ty. flags . intersects ( TypeFlags :: HAS_PROJECTION )
986+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PROJECTION )
980987}
981988
982989pub fn type_has_late_bound_regions ( ty : Ty ) -> bool {
983- ty. flags . intersects ( TypeFlags :: HAS_RE_LATE_BOUND )
990+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_RE_LATE_BOUND )
984991}
985992
986993/// An "escaping region" is a bound region whose binder is not part of `t`.
@@ -2770,8 +2777,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
27702777 stability : RefCell :: new ( stability) ,
27712778 selection_cache : traits:: SelectionCache :: new ( ) ,
27722779 repr_hint_cache : RefCell :: new ( DefIdMap ( ) ) ,
2773- type_impls_copy_cache : RefCell :: new ( HashMap :: new ( ) ) ,
2774- type_impls_sized_cache : RefCell :: new ( HashMap :: new ( ) ) ,
27752780 const_qualif_map : RefCell :: new ( NodeMap ( ) ) ,
27762781 custom_coerce_unsized_kinds : RefCell :: new ( DefIdMap ( ) ) ,
27772782 cast_kinds : RefCell :: new ( NodeMap ( ) ) ,
@@ -2871,7 +2876,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
28712876
28722877 let ty = match ( ) {
28732878 ( ) => type_arena. alloc ( TyS { sty : st,
2874- flags : flags. flags ,
2879+ flags : Cell :: new ( flags. flags ) ,
28752880 region_depth : flags. depth , } ) ,
28762881 } ;
28772882
@@ -2902,7 +2907,7 @@ impl FlagComputation {
29022907 }
29032908
29042909 fn add_flags ( & mut self , flags : TypeFlags ) {
2905- self . flags = self . flags | flags;
2910+ self . flags = self . flags | ( flags & TypeFlags :: NOMINAL_FLAGS ) ;
29062911 }
29072912
29082913 fn add_depth ( & mut self , depth : u32 ) {
@@ -3008,7 +3013,7 @@ impl FlagComputation {
30083013 }
30093014
30103015 fn add_ty ( & mut self , ty : Ty ) {
3011- self . add_flags ( ty. flags ) ;
3016+ self . add_flags ( ty. flags . get ( ) ) ;
30123017 self . add_depth ( ty. region_depth ) ;
30133018 }
30143019
@@ -3389,11 +3394,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
33893394}
33903395
33913396pub fn type_is_error ( ty : Ty ) -> bool {
3392- ty. flags . intersects ( TypeFlags :: HAS_TY_ERR )
3397+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_ERR )
33933398}
33943399
33953400pub fn type_needs_subst ( ty : Ty ) -> bool {
3396- ty. flags . intersects ( TypeFlags :: NEEDS_SUBST )
3401+ ty. flags . get ( ) . intersects ( TypeFlags :: NEEDS_SUBST )
33973402}
33983403
33993404pub fn trait_ref_contains_error ( tref : & ty:: TraitRef ) -> bool {
@@ -3911,42 +3916,30 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
39113916 }
39123917}
39133918
3914- fn type_impls_bound < ' a , ' tcx > ( param_env : & ParameterEnvironment < ' a , ' tcx > ,
3915- cache : & RefCell < HashMap < Ty < ' tcx > , bool > > ,
3919+ fn type_impls_bound < ' a , ' tcx > ( param_env : Option < & ParameterEnvironment < ' a , ' tcx > > ,
3920+ tcx : & ty :: ctxt < ' tcx > ,
39163921 ty : Ty < ' tcx > ,
39173922 bound : ty:: BuiltinBound ,
39183923 span : Span )
39193924 -> bool
39203925{
3921- assert ! ( !ty:: type_needs_infer( ty) ) ;
3922-
3923- if !type_has_params ( ty) && !type_has_self ( ty) {
3924- match cache. borrow ( ) . get ( & ty) {
3925- None => { }
3926- Some ( & result) => {
3927- debug ! ( "type_impls_bound({}, {:?}) = {:?} (cached)" ,
3928- ty. repr( param_env. tcx) ,
3929- bound,
3930- result) ;
3931- return result
3932- }
3926+ let pe;
3927+ let param_env = match param_env {
3928+ Some ( e) => e,
3929+ None => {
3930+ pe = empty_parameter_environment ( tcx) ;
3931+ & pe
39333932 }
3934- }
3935-
3936- let infcx = infer:: new_infer_ctxt ( param_env. tcx ) ;
3933+ } ;
3934+ let infcx = infer:: new_infer_ctxt ( tcx) ;
39373935
39383936 let is_impld = traits:: type_known_to_meet_builtin_bound ( & infcx, param_env, ty, bound, span) ;
39393937
39403938 debug ! ( "type_impls_bound({}, {:?}) = {:?}" ,
3941- ty. repr( param_env . tcx) ,
3939+ ty. repr( tcx) ,
39423940 bound,
39433941 is_impld) ;
39443942
3945- if !type_has_params ( ty) && !type_has_self ( ty) {
3946- let old_value = cache. borrow_mut ( ) . insert ( ty, is_impld) ;
3947- assert ! ( old_value. is_none( ) ) ;
3948- }
3949-
39503943 is_impld
39513944}
39523945
@@ -3955,17 +3948,85 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
39553948 ty : Ty < ' tcx > )
39563949 -> bool
39573950{
3958- let tcx = param_env. tcx ;
3959- !type_impls_bound ( param_env, & tcx. type_impls_copy_cache , ty, ty:: BoundCopy , span)
3951+ if ty. flags . get ( ) . intersects ( TypeFlags :: MOVENESS_CACHED ) {
3952+ return ty. flags . get ( ) . intersects ( TypeFlags :: MOVES_BY_DEFAULT ) ;
3953+ }
3954+
3955+ assert ! ( !ty:: type_needs_infer( ty) ) ;
3956+
3957+ // Fast-path for primitive types
3958+ let result = match ty. sty {
3959+ ty_bool | ty_char | ty_int( ..) | ty_uint( ..) | ty_float( ..) |
3960+ ty_ptr( ..) | ty_bare_fn( ..) | ty_rptr( _, mt {
3961+ mutbl : ast:: MutImmutable , ..
3962+ } ) => Some ( false ) ,
3963+
3964+ ty_str | ty_uniq( ..) | ty_rptr( _, mt {
3965+ mutbl : ast:: MutMutable , ..
3966+ } ) => Some ( true ) ,
3967+
3968+ ty_vec( ..) | ty_trait( ..) | ty_tup( ..) |
3969+ ty_closure( ..) | ty_enum( ..) | ty_struct( ..) |
3970+ ty_projection( ..) | ty_param( ..) | ty_infer( ..) | ty_err => None
3971+ } . unwrap_or_else ( || !type_impls_bound ( Some ( param_env) ,
3972+ param_env. tcx ,
3973+ ty,
3974+ ty:: BoundCopy ,
3975+ span) ) ;
3976+
3977+ if !type_has_params ( ty) && !type_has_self ( ty) {
3978+ ty. flags . set ( ty. flags . get ( ) | if result {
3979+ TypeFlags :: MOVENESS_CACHED | TypeFlags :: MOVES_BY_DEFAULT
3980+ } else {
3981+ TypeFlags :: MOVENESS_CACHED
3982+ } ) ;
3983+ }
3984+
3985+ result
39603986}
39613987
3962- pub fn type_is_sized < ' a , ' tcx > ( param_env : & ParameterEnvironment < ' a , ' tcx > ,
3988+ #[ inline]
3989+ pub fn type_is_sized < ' a , ' tcx > ( param_env : Option < & ParameterEnvironment < ' a , ' tcx > > ,
3990+ tcx : & ty:: ctxt < ' tcx > ,
39633991 span : Span ,
39643992 ty : Ty < ' tcx > )
39653993 -> bool
39663994{
3967- let tcx = param_env. tcx ;
3968- type_impls_bound ( param_env, & tcx. type_impls_sized_cache , ty, ty:: BoundSized , span)
3995+ if ty. flags . get ( ) . intersects ( TypeFlags :: SIZEDNESS_CACHED ) {
3996+ let result = ty. flags . get ( ) . intersects ( TypeFlags :: IS_SIZED ) ;
3997+ return result;
3998+ }
3999+
4000+ type_is_sized_uncached ( param_env, tcx, span, ty)
4001+ }
4002+
4003+ fn type_is_sized_uncached < ' a , ' tcx > ( param_env : Option < & ParameterEnvironment < ' a , ' tcx > > ,
4004+ tcx : & ty:: ctxt < ' tcx > ,
4005+ span : Span ,
4006+ ty : Ty < ' tcx > ) -> bool {
4007+ assert ! ( !ty:: type_needs_infer( ty) ) ;
4008+
4009+ // Fast-path for primitive types
4010+ let result = match ty. sty {
4011+ ty_bool | ty_char | ty_int( ..) | ty_uint( ..) | ty_float( ..) |
4012+ ty_uniq( ..) | ty_ptr( ..) | ty_rptr( ..) | ty_bare_fn( ..) |
4013+ ty_vec( _, Some ( ..) ) | ty_tup( ..) | ty_closure( ..) => Some ( true ) ,
4014+
4015+ ty_str | ty_trait( ..) | ty_vec( _, None ) => Some ( false ) ,
4016+
4017+ ty_enum( ..) | ty_struct( ..) | ty_projection( ..) | ty_param( ..) |
4018+ ty_infer( ..) | ty_err => None
4019+ } . unwrap_or_else ( || type_impls_bound ( param_env, tcx, ty, ty:: BoundSized , span) ) ;
4020+
4021+ if !type_has_params ( ty) && !type_has_self ( ty) {
4022+ ty. flags . set ( ty. flags . get ( ) | if result {
4023+ TypeFlags :: SIZEDNESS_CACHED | TypeFlags :: IS_SIZED
4024+ } else {
4025+ TypeFlags :: SIZEDNESS_CACHED
4026+ } ) ;
4027+ }
4028+
4029+ result
39694030}
39704031
39714032pub fn is_ffi_safe < ' tcx > ( cx : & ctxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
0 commit comments