Use type-safe wrapper for TypeFlags

This commit is contained in:
Niko Matsakis 2014-10-24 10:20:02 -04:00
parent de06faf889
commit 4a8d712345
2 changed files with 59 additions and 46 deletions

View file

@ -287,7 +287,7 @@ want to be able to cache results even when all the types in the trait
reference are not fully known. In that case, it may happen that the
trait selection process is also influencing type variables, so we have
to be able to not only cache the *result* of the selection process,
but *reply* its effects on the type variables.
but *replay* its effects on the type variables.
## An example

View file

@ -589,14 +589,19 @@ pub struct ctxt<'tcx> {
// through the type during type construction, so that we can quickly
// check whether the type has various kinds of types in it without
// recursing over the type itself.
const HAS_PARAMS: uint = 1;
const HAS_SELF: uint = 2;
const HAS_TY_INFER: uint = 4;
const HAS_RE_INFER: uint = 8;
const HAS_REGIONS: uint = 16;
const HAS_TY_ERR: uint = 32;
const HAS_TY_BOT: uint = 64;
const NEEDS_SUBST: uint = HAS_PARAMS | HAS_SELF | HAS_REGIONS;
bitflags! {
flags TypeFlags: u32 {
const NO_TYPE_FLAGS = 0b0,
const HAS_PARAMS = 0b1,
const HAS_SELF = 0b10,
const HAS_TY_INFER = 0b100,
const HAS_RE_INFER = 0b1000,
const HAS_REGIONS = 0b10000,
const HAS_TY_ERR = 0b100000,
const HAS_TY_BOT = 0b1000000,
const NEEDS_SUBST = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
}
}
pub type t_box = &'static t_box_;
@ -604,7 +609,13 @@ pub type t_box = &'static t_box_;
pub struct t_box_ {
pub sty: sty,
pub id: uint,
pub flags: uint,
pub flags: TypeFlags,
}
impl fmt::Show for TypeFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bits)
}
}
// To reduce refcounting cost, we're representing types as unsafe pointers
@ -631,8 +642,8 @@ pub fn get(t: t) -> t_box {
}
}
fn tbox_has_flag(tb: t_box, flag: uint) -> bool {
(tb.flags & flag) != 0u
fn tbox_has_flag(tb: t_box, flag: TypeFlags) -> bool {
tb.flags.intersects(flag)
}
pub fn type_has_params(t: t) -> bool {
tbox_has_flag(get(t), HAS_PARAMS)
@ -887,7 +898,7 @@ mod primitives {
pub static $name: t_box_ = t_box_ {
sty: $sty,
id: $id,
flags: 0,
flags: super::NO_TYPE_FLAGS,
};
)
)
@ -1578,32 +1589,32 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
_ => ()
}
let mut flags = 0u;
fn rflags(r: Region) -> uint {
let mut flags = NO_TYPE_FLAGS;
fn rflags(r: Region) -> TypeFlags {
HAS_REGIONS | {
match r {
ty::ReInfer(_) => HAS_RE_INFER,
_ => 0u
_ => NO_TYPE_FLAGS,
}
}
}
fn sflags(substs: &Substs) -> uint {
let mut f = 0u;
fn sflags(substs: &Substs) -> TypeFlags {
let mut f = NO_TYPE_FLAGS;
let mut i = substs.types.iter();
for tt in i {
f |= get(*tt).flags;
f = f | get(*tt).flags;
}
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref regions) => {
for r in regions.iter() {
f |= rflags(*r)
f = f | rflags(*r)
}
}
}
return f;
}
fn flags_for_bounds(bounds: &ExistentialBounds) -> uint {
fn flags_for_bounds(bounds: &ExistentialBounds) -> TypeFlags {
rflags(bounds.region_bound)
}
match &st {
@ -1616,53 +1627,53 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
// But doing so caused sporadic memory corruption, and
// neither I (tjc) nor nmatsakis could figure out why,
// so we're doing it this way.
&ty_bot => flags |= HAS_TY_BOT,
&ty_err => flags |= HAS_TY_ERR,
&ty_bot => flags = flags | HAS_TY_BOT,
&ty_err => flags = flags | HAS_TY_ERR,
&ty_param(ref p) => {
if p.space == subst::SelfSpace {
flags |= HAS_SELF;
flags = flags | HAS_SELF;
} else {
flags |= HAS_PARAMS;
flags = flags | HAS_PARAMS;
}
}
&ty_unboxed_closure(_, ref region) => flags |= rflags(*region),
&ty_infer(_) => flags |= HAS_TY_INFER,
&ty_unboxed_closure(_, ref region) => flags = flags | rflags(*region),
&ty_infer(_) => flags = flags | HAS_TY_INFER,
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
flags = flags | sflags(substs);
}
&ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
flags |= sflags(substs);
flags |= flags_for_bounds(bounds);
flags = flags | sflags(substs);
flags = flags | flags_for_bounds(bounds);
}
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
flags |= get(tt).flags
flags = flags | get(tt).flags
}
&ty_ptr(ref m) => {
flags |= get(m.ty).flags;
flags = flags | get(m.ty).flags;
}
&ty_rptr(r, ref m) => {
flags |= rflags(r);
flags |= get(m.ty).flags;
flags = flags | rflags(r);
flags = flags | get(m.ty).flags;
}
&ty_tup(ref ts) => for tt in ts.iter() { flags |= get(*tt).flags; },
&ty_tup(ref ts) => for tt in ts.iter() { flags = flags | get(*tt).flags; },
&ty_bare_fn(ref f) => {
for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
flags |= get(f.sig.output).flags;
for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
flags = flags | get(f.sig.output).flags;
// T -> _|_ is *not* _|_ !
flags &= !HAS_TY_BOT;
flags = flags - HAS_TY_BOT;
}
&ty_closure(ref f) => {
match f.store {
RegionTraitStore(r, _) => {
flags |= rflags(r);
flags = flags | rflags(r);
}
_ => {}
}
for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
flags |= get(f.sig.output).flags;
for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
flags = flags | get(f.sig.output).flags;
// T -> _|_ is *not* _|_ !
flags &= !HAS_TY_BOT;
flags |= flags_for_bounds(&f.bounds);
flags = flags - HAS_TY_BOT;
flags = flags | flags_for_bounds(&f.bounds);
}
}
@ -1977,14 +1988,16 @@ impl ItemSubsts {
// Type utilities
pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
pub fn type_is_nil(ty: t) -> bool {
get(ty).sty == ty_nil
}
pub fn type_is_bot(ty: t) -> bool {
(get(ty).flags & HAS_TY_BOT) != 0
get(ty).flags.intersects(HAS_TY_BOT)
}
pub fn type_is_error(ty: t) -> bool {
(get(ty).flags & HAS_TY_ERR) != 0
get(ty).flags.intersects(HAS_TY_ERR)
}
pub fn type_needs_subst(ty: t) -> bool {