@@ -756,16 +756,6 @@ pub struct ctxt<'tcx> {
756
756
/// Caches the representation hints for struct definitions.
757
757
pub repr_hint_cache : RefCell < DefIdMap < Rc < Vec < attr:: ReprAttr > > > > ,
758
758
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
-
769
759
/// Maps Expr NodeId's to their constant qualification.
770
760
pub const_qualif_map : RefCell < NodeMap < check_const:: ConstQualif > > ,
771
761
@@ -827,6 +817,23 @@ bitflags! {
827
817
const NEEDS_SUBST = TypeFlags :: HAS_PARAMS . bits |
828
818
TypeFlags :: HAS_SELF . bits |
829
819
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 ,
830
837
}
831
838
}
832
839
@@ -859,8 +866,8 @@ macro_rules! sty_debug_print {
859
866
ty:: ty_err => /* unimportant */ continue ,
860
867
$( ty:: $variant( ..) => & mut $variant, ) *
861
868
} ;
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 ) ;
864
871
865
872
variant. total += 1 ;
866
873
total. total += 1 ;
@@ -908,7 +915,7 @@ impl<'tcx> ctxt<'tcx> {
908
915
#[ derive( Debug ) ]
909
916
pub struct TyS < ' tcx > {
910
917
pub sty : sty < ' tcx > ,
911
- pub flags : TypeFlags ,
918
+ pub flags : Cell < TypeFlags > ,
912
919
913
920
// the maximal depth of any bound regions appearing in this type.
914
921
region_depth : u32 ,
@@ -964,23 +971,23 @@ impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
964
971
}
965
972
966
973
pub fn type_has_params ( ty : Ty ) -> bool {
967
- ty. flags . intersects ( TypeFlags :: HAS_PARAMS )
974
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PARAMS )
968
975
}
969
976
pub fn type_has_self ( ty : Ty ) -> bool {
970
- ty. flags . intersects ( TypeFlags :: HAS_SELF )
977
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_SELF )
971
978
}
972
979
pub 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 )
974
981
}
975
982
pub 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 )
977
984
}
978
985
pub fn type_has_projection ( ty : Ty ) -> bool {
979
- ty. flags . intersects ( TypeFlags :: HAS_PROJECTION )
986
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_PROJECTION )
980
987
}
981
988
982
989
pub 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 )
984
991
}
985
992
986
993
/// 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,
2770
2777
stability : RefCell :: new ( stability) ,
2771
2778
selection_cache : traits:: SelectionCache :: new ( ) ,
2772
2779
repr_hint_cache : RefCell :: new ( DefIdMap ( ) ) ,
2773
- type_impls_copy_cache : RefCell :: new ( HashMap :: new ( ) ) ,
2774
- type_impls_sized_cache : RefCell :: new ( HashMap :: new ( ) ) ,
2775
2780
const_qualif_map : RefCell :: new ( NodeMap ( ) ) ,
2776
2781
custom_coerce_unsized_kinds : RefCell :: new ( DefIdMap ( ) ) ,
2777
2782
cast_kinds : RefCell :: new ( NodeMap ( ) ) ,
@@ -2871,7 +2876,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
2871
2876
2872
2877
let ty = match ( ) {
2873
2878
( ) => type_arena. alloc ( TyS { sty : st,
2874
- flags : flags. flags ,
2879
+ flags : Cell :: new ( flags. flags ) ,
2875
2880
region_depth : flags. depth , } ) ,
2876
2881
} ;
2877
2882
@@ -2902,7 +2907,7 @@ impl FlagComputation {
2902
2907
}
2903
2908
2904
2909
fn add_flags ( & mut self , flags : TypeFlags ) {
2905
- self . flags = self . flags | flags;
2910
+ self . flags = self . flags | ( flags & TypeFlags :: NOMINAL_FLAGS ) ;
2906
2911
}
2907
2912
2908
2913
fn add_depth ( & mut self , depth : u32 ) {
@@ -3008,7 +3013,7 @@ impl FlagComputation {
3008
3013
}
3009
3014
3010
3015
fn add_ty ( & mut self , ty : Ty ) {
3011
- self . add_flags ( ty. flags ) ;
3016
+ self . add_flags ( ty. flags . get ( ) ) ;
3012
3017
self . add_depth ( ty. region_depth ) ;
3013
3018
}
3014
3019
@@ -3389,11 +3394,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
3389
3394
}
3390
3395
3391
3396
pub fn type_is_error ( ty : Ty ) -> bool {
3392
- ty. flags . intersects ( TypeFlags :: HAS_TY_ERR )
3397
+ ty. flags . get ( ) . intersects ( TypeFlags :: HAS_TY_ERR )
3393
3398
}
3394
3399
3395
3400
pub fn type_needs_subst ( ty : Ty ) -> bool {
3396
- ty. flags . intersects ( TypeFlags :: NEEDS_SUBST )
3401
+ ty. flags . get ( ) . intersects ( TypeFlags :: NEEDS_SUBST )
3397
3402
}
3398
3403
3399
3404
pub 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 {
3911
3916
}
3912
3917
}
3913
3918
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 > ,
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
- }
3926
+ let pe;
3927
+ let param_env = match param_env {
3928
+ Some ( e) => e,
3929
+ None => {
3930
+ pe = empty_parameter_environment ( tcx) ;
3931
+ & pe
3933
3932
}
3934
- }
3935
-
3936
- let infcx = infer:: new_infer_ctxt ( param_env. tcx ) ;
3933
+ } ;
3934
+ let infcx = infer:: new_infer_ctxt ( tcx) ;
3937
3935
3938
3936
let is_impld = traits:: type_known_to_meet_builtin_bound ( & infcx, param_env, ty, bound, span) ;
3939
3937
3940
3938
debug ! ( "type_impls_bound({}, {:?}) = {:?}" ,
3941
- ty. repr( param_env . tcx) ,
3939
+ ty. repr( tcx) ,
3942
3940
bound,
3943
3941
is_impld) ;
3944
3942
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
3943
is_impld
3951
3944
}
3952
3945
@@ -3955,17 +3948,85 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3955
3948
ty : Ty < ' tcx > )
3956
3949
-> bool
3957
3950
{
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
3960
3986
}
3961
3987
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 > ,
3963
3991
span : Span ,
3964
3992
ty : Ty < ' tcx > )
3965
3993
-> bool
3966
3994
{
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
3969
4030
}
3970
4031
3971
4032
pub fn is_ffi_safe < ' tcx > ( cx : & ctxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
0 commit comments