@@ -827,6 +827,12 @@ bitflags! {
827
827
const NEEDS_SUBST = TypeFlags :: HAS_PARAMS . bits |
828
828
TypeFlags :: HAS_SELF . bits |
829
829
TypeFlags :: HAS_REGIONS . bits,
830
+
831
+ // Caches for type_is_sized, type_moves_by_default
832
+ const SIZEDNESS_CACHED = 1 << 16 ,
833
+ const IS_SIZED = 1 << 17 ,
834
+ const MOVENESS_CACHED = 1 << 18 ,
835
+ const MOVES_BY_DEFAULT = 1 << 19 ,
830
836
}
831
837
}
832
838
@@ -859,8 +865,8 @@ macro_rules! sty_debug_print {
859
865
ty:: ty_err => /* unimportant */ continue ,
860
866
$( ty:: $variant( ..) => & mut $variant, ) *
861
867
} ;
862
- let region = t. flags. intersects( ty:: TypeFlags :: HAS_RE_INFER ) ;
863
- let ty = t. flags. intersects( ty:: TypeFlags :: HAS_TY_INFER ) ;
868
+ let region = t. flags. get ( ) . intersects( ty:: TypeFlags :: HAS_RE_INFER ) ;
869
+ let ty = t. flags. get ( ) . intersects( ty:: TypeFlags :: HAS_TY_INFER ) ;
864
870
865
871
variant. total += 1 ;
866
872
total. total += 1 ;
@@ -908,7 +914,7 @@ impl<'tcx> ctxt<'tcx> {
908
914
#[ derive( Debug ) ]
909
915
pub struct TyS < ' tcx > {
910
916
pub sty : sty < ' tcx > ,
911
- pub flags : TypeFlags ,
917
+ pub flags : Cell < TypeFlags > ,
912
918
913
919
// the maximal depth of any bound regions appearing in this type.
914
920
region_depth : u32 ,
@@ -964,23 +970,23 @@ impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
964
970
}
965
971
966
972
pub fn type_has_params ( ty : Ty ) -> bool {
967
- ty. flags . intersects ( TypeFlags :: HAS_PARAMS )
973
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PARAMS )
968
974
}
969
975
pub fn type_has_self ( ty : Ty ) -> bool {
970
- ty. flags . intersects ( TypeFlags :: HAS_SELF )
976
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_SELF )
971
977
}
972
978
pub fn type_has_ty_infer ( ty : Ty ) -> bool {
973
- ty. flags . intersects ( TypeFlags :: HAS_TY_INFER )
979
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_INFER )
974
980
}
975
981
pub fn type_needs_infer ( ty : Ty ) -> bool {
976
- ty. flags . intersects ( TypeFlags :: HAS_TY_INFER | TypeFlags :: HAS_RE_INFER )
982
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_INFER | TypeFlags :: HAS_RE_INFER )
977
983
}
978
984
pub fn type_has_projection ( ty : Ty ) -> bool {
979
- ty. flags . intersects ( TypeFlags :: HAS_PROJECTION )
985
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PROJECTION )
980
986
}
981
987
982
988
pub fn type_has_late_bound_regions ( ty : Ty ) -> bool {
983
- ty. flags . intersects ( TypeFlags :: HAS_RE_LATE_BOUND )
989
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_RE_LATE_BOUND )
984
990
}
985
991
986
992
/// An "escaping region" is a bound region whose binder is not part of `t`.
@@ -2871,7 +2877,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
2871
2877
2872
2878
let ty = match ( ) {
2873
2879
( ) => type_arena. alloc ( TyS { sty : st,
2874
- flags : flags. flags ,
2880
+ flags : Cell :: new ( flags. flags ) ,
2875
2881
region_depth : flags. depth , } ) ,
2876
2882
} ;
2877
2883
@@ -3008,7 +3014,7 @@ impl FlagComputation {
3008
3014
}
3009
3015
3010
3016
fn add_ty ( & mut self , ty : Ty ) {
3011
- self . add_flags ( ty. flags ) ;
3017
+ self . add_flags ( ty. flags . get ( ) ) ;
3012
3018
self . add_depth ( ty. region_depth ) ;
3013
3019
}
3014
3020
@@ -3389,11 +3395,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
3389
3395
}
3390
3396
3391
3397
pub fn type_is_error ( ty : Ty ) -> bool {
3392
- ty. flags . intersects ( TypeFlags :: HAS_TY_ERR )
3398
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_ERR )
3393
3399
}
3394
3400
3395
3401
pub fn type_needs_subst ( ty : Ty ) -> bool {
3396
- ty. flags . intersects ( TypeFlags :: NEEDS_SUBST )
3402
+ ty. flags . get ( ) . intersects ( TypeFlags :: NEEDS_SUBST )
3397
3403
}
3398
3404
3399
3405
pub fn trait_ref_contains_error ( tref : & ty:: TraitRef ) -> bool {
@@ -3912,27 +3918,11 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
3912
3918
}
3913
3919
3914
3920
fn type_impls_bound < ' a , ' tcx > ( param_env : & ParameterEnvironment < ' a , ' tcx > ,
3915
- cache : & RefCell < HashMap < Ty < ' tcx > , bool > > ,
3916
3921
ty : Ty < ' tcx > ,
3917
3922
bound : ty:: BuiltinBound ,
3918
3923
span : Span )
3919
3924
-> bool
3920
3925
{
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
- }
3933
- }
3934
- }
3935
-
3936
3926
let infcx = infer:: new_infer_ctxt ( param_env. tcx ) ;
3937
3927
3938
3928
let is_impld = traits:: type_known_to_meet_builtin_bound ( & infcx, param_env, ty, bound, span) ;
@@ -3942,11 +3932,6 @@ fn type_impls_bound<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3942
3932
bound,
3943
3933
is_impld) ;
3944
3934
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
-
3950
3935
is_impld
3951
3936
}
3952
3937
@@ -3955,17 +3940,78 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3955
3940
ty : Ty < ' tcx > )
3956
3941
-> bool
3957
3942
{
3958
- let tcx = param_env. tcx ;
3959
- !type_impls_bound ( param_env, & tcx. type_impls_copy_cache , ty, ty:: BoundCopy , span)
3943
+ if ty. flags . get ( ) . intersects ( TypeFlags :: MOVENESS_CACHED ) {
3944
+ return ty. flags . get ( ) . intersects ( TypeFlags :: MOVES_BY_DEFAULT ) ;
3945
+ }
3946
+
3947
+ assert ! ( !ty:: type_needs_infer( ty) ) ;
3948
+
3949
+ // Fast-path for primitive types
3950
+ let result = match ty. sty {
3951
+ ty_bool | ty_char | ty_int( ..) | ty_uint( ..) | ty_float( ..) |
3952
+ ty_ptr( ..) | ty_bare_fn( ..) | ty_rptr( _, mt {
3953
+ mutbl : ast:: MutImmutable , ..
3954
+ } ) => Some ( false ) ,
3955
+
3956
+ ty_str | ty_uniq( ..) | ty_rptr( _, mt {
3957
+ mutbl : ast:: MutMutable , ..
3958
+ } ) => Some ( true ) ,
3959
+
3960
+ ty_vec( ..) | ty_trait( ..) | ty_tup( ..) |
3961
+ ty_closure( ..) | ty_enum( ..) | ty_struct( ..) |
3962
+ ty_projection( ..) | ty_param( ..) | ty_infer( ..) | ty_err => None
3963
+ } . unwrap_or ( !type_impls_bound ( param_env, ty, ty:: BoundCopy , span) ) ;
3964
+
3965
+ if !type_has_params ( ty) && !type_has_self ( ty) {
3966
+ ty. flags . set ( ty. flags . get ( ) | if result {
3967
+ TypeFlags :: MOVENESS_CACHED | TypeFlags :: MOVES_BY_DEFAULT
3968
+ } else {
3969
+ TypeFlags :: MOVENESS_CACHED
3970
+ } ) ;
3971
+ }
3972
+
3973
+ result
3960
3974
}
3961
3975
3962
3976
pub fn type_is_sized < ' a , ' tcx > ( param_env : & ParameterEnvironment < ' a , ' tcx > ,
3963
3977
span : Span ,
3964
3978
ty : Ty < ' tcx > )
3965
3979
-> bool
3966
3980
{
3967
- let tcx = param_env. tcx ;
3968
- type_impls_bound ( param_env, & tcx. type_impls_sized_cache , ty, ty:: BoundSized , span)
3981
+ if ty. flags . get ( ) . intersects ( TypeFlags :: SIZEDNESS_CACHED ) {
3982
+ let result = ty. flags . get ( ) . intersects ( TypeFlags :: IS_SIZED ) ;
3983
+ debug ! ( "type_is_sized({}) = {} (cached)" , ty. repr( param_env. tcx) ,
3984
+ result) ;
3985
+ return result;
3986
+ }
3987
+
3988
+ assert ! ( !ty:: type_needs_infer( ty) ) ;
3989
+
3990
+ // Fast-path for primitive types
3991
+ let result = match ty. sty {
3992
+ ty_bool | ty_char | ty_int( ..) | ty_uint( ..) | ty_float( ..) |
3993
+ ty_uniq( ..) | ty_ptr( ..) | ty_rptr( ..) | ty_bare_fn( ..) |
3994
+ ty_vec( _, Some ( ..) ) | ty_tup( ..) | ty_closure( ..) => {
3995
+ Some ( true )
3996
+ }
3997
+
3998
+ ty_str | ty_trait( ..) | ty_vec( _, None ) => Some ( false ) ,
3999
+
4000
+ ty_enum( ..) | ty_struct( ..) | ty_projection( ..) | ty_param( ..) |
4001
+ ty_infer( ..) | ty_err => None
4002
+ } . unwrap_or ( type_impls_bound ( param_env, ty, ty:: BoundSized , span) ) ;
4003
+
4004
+ if !type_has_params ( ty) && !type_has_self ( ty) {
4005
+ ty. flags . set ( ty. flags . get ( ) | if result {
4006
+ TypeFlags :: SIZEDNESS_CACHED | TypeFlags :: IS_SIZED
4007
+ } else {
4008
+ TypeFlags :: SIZEDNESS_CACHED
4009
+ } ) ;
4010
+ }
4011
+
4012
+ debug ! ( "type_is_sized({}) = {}" , ty. repr( param_env. tcx) ,
4013
+ result) ;
4014
+ result
3969
4015
}
3970
4016
3971
4017
pub fn is_ffi_safe < ' tcx > ( cx : & ctxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
0 commit comments