Skip to content

Commit b21e03c

Browse files
author
Ariel Ben-Yehuda
committed
bug
1 parent 52e530a commit b21e03c

File tree

1 file changed

+84
-38
lines changed

1 file changed

+84
-38
lines changed

src/librustc/middle/ty.rs

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,12 @@ bitflags! {
827827
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
828828
TypeFlags::HAS_SELF.bits |
829829
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,
830836
}
831837
}
832838

@@ -859,8 +865,8 @@ macro_rules! sty_debug_print {
859865
ty::ty_err => /* unimportant */ continue,
860866
$(ty::$variant(..) => &mut $variant,)*
861867
};
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);
864870

865871
variant.total += 1;
866872
total.total += 1;
@@ -908,7 +914,7 @@ impl<'tcx> ctxt<'tcx> {
908914
#[derive(Debug)]
909915
pub struct TyS<'tcx> {
910916
pub sty: sty<'tcx>,
911-
pub flags: TypeFlags,
917+
pub flags: Cell<TypeFlags>,
912918

913919
// the maximal depth of any bound regions appearing in this type.
914920
region_depth: u32,
@@ -964,23 +970,23 @@ impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
964970
}
965971

966972
pub fn type_has_params(ty: Ty) -> bool {
967-
ty.flags.intersects(TypeFlags::HAS_PARAMS)
973+
ty.flags.get().intersects(TypeFlags::HAS_PARAMS)
968974
}
969975
pub fn type_has_self(ty: Ty) -> bool {
970-
ty.flags.intersects(TypeFlags::HAS_SELF)
976+
ty.flags.get().intersects(TypeFlags::HAS_SELF)
971977
}
972978
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)
974980
}
975981
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)
977983
}
978984
pub fn type_has_projection(ty: Ty) -> bool {
979-
ty.flags.intersects(TypeFlags::HAS_PROJECTION)
985+
ty.flags.get().intersects(TypeFlags::HAS_PROJECTION)
980986
}
981987

982988
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)
984990
}
985991

986992
/// 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>>,
28712877

28722878
let ty = match () {
28732879
() => type_arena.alloc(TyS { sty: st,
2874-
flags: flags.flags,
2880+
flags: Cell::new(flags.flags),
28752881
region_depth: flags.depth, }),
28762882
};
28772883

@@ -3008,7 +3014,7 @@ impl FlagComputation {
30083014
}
30093015

30103016
fn add_ty(&mut self, ty: Ty) {
3011-
self.add_flags(ty.flags);
3017+
self.add_flags(ty.flags.get());
30123018
self.add_depth(ty.region_depth);
30133019
}
30143020

@@ -3389,11 +3395,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
33893395
}
33903396

33913397
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)
33933399
}
33943400

33953401
pub fn type_needs_subst(ty: Ty) -> bool {
3396-
ty.flags.intersects(TypeFlags::NEEDS_SUBST)
3402+
ty.flags.get().intersects(TypeFlags::NEEDS_SUBST)
33973403
}
33983404

33993405
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 {
39123918
}
39133919

39143920
fn type_impls_bound<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3915-
cache: &RefCell<HashMap<Ty<'tcx>,bool>>,
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-
}
3933-
}
3934-
}
3935-
39363926
let infcx = infer::new_infer_ctxt(param_env.tcx);
39373927

39383928
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>,
39423932
bound,
39433933
is_impld);
39443934

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-
39503935
is_impld
39513936
}
39523937

@@ -3955,17 +3940,78 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
39553940
ty: Ty<'tcx>)
39563941
-> bool
39573942
{
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
39603974
}
39613975

39623976
pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
39633977
span: Span,
39643978
ty: Ty<'tcx>)
39653979
-> bool
39663980
{
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
39694015
}
39704016

39714017
pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {

0 commit comments

Comments
 (0)