Skip to content

Commit

Permalink
Use type-safe wrapper for TypeFlags
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Oct 24, 2014
1 parent de06faf commit 4a8d712
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
103 changes: 58 additions & 45 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,22 +589,33 @@ 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_;

#[deriving(Show)]
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
Expand All @@ -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)
Expand Down Expand Up @@ -887,7 +898,7 @@ mod primitives {
pub static $name: t_box_ = t_box_ {
sty: $sty,
id: $id,
flags: 0,
flags: super::NO_TYPE_FLAGS,
};
)
)
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 4a8d712

Please sign in to comment.