From 92ae0c6c255e826632f37e7b90d669d0cd4bb2ea Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 28 Sep 2014 18:31:04 +0300 Subject: [PATCH] rustc: middle: ty: replace unsafe pointers with references in Ty. --- src/librustc/middle/ty.rs | 129 +++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 73 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8a1bbe017f2..5c356e80c70 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -61,6 +61,7 @@ use util::ppaux::{Repr, UserString}; use util::common::{indenter, memoized}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::{FnvHashMap, FnvHashSet}; +use std::borrow::BorrowFrom; use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt::{mod, Show}; @@ -252,32 +253,6 @@ pub struct creader_cache_key { pub len: uint } -pub struct intern_key { - sty: *const sty, -} - -// NB: Do not replace this with #[deriving(PartialEq)]. The automatically-derived -// implementation will not recurse through sty and you will get stack -// exhaustion. -impl cmp::PartialEq for intern_key { - fn eq(&self, other: &intern_key) -> bool { - unsafe { - *self.sty == *other.sty - } - } - fn ne(&self, other: &intern_key) -> bool { - !self.eq(other) - } -} - -impl Eq for intern_key {} - -impl Hash for intern_key { - fn hash(&self, s: &mut W) { - unsafe { (*self.sty).hash(s) } - } -} - pub enum ast_ty_to_ty_cache_entry { atttce_unresolved, /* not resolved yet */ atttce_resolved(Ty) /* resolved to a type, irrespective of region */ @@ -456,11 +431,13 @@ pub struct TransmuteRestriction { /// later on. pub struct ctxt<'tcx> { /// The arena that types are allocated from. - type_arena: &'tcx TypedArena, + type_arena: &'tcx TypedArena, /// Specifically use a speedy hash algorithm for this hash map, it's used /// quite often. - interner: RefCell>, + // TODO(eddyb) use a FnvHashSet> when equivalent keys can + // queried from a HashSet. + interner: RefCell, Ty<'tcx>>>, pub sess: Session, pub def_map: resolve::DefMap, @@ -621,10 +598,8 @@ bitflags! { } } -pub type t_box = &'static t_box_; - #[deriving(Show)] -pub struct t_box_ { +pub struct TyS { pub sty: sty, pub flags: TypeFlags, @@ -638,32 +613,52 @@ impl fmt::Show for TypeFlags { } } -// To reduce refcounting cost, we're representing types as unsafe pointers -// throughout the compiler. These are simply casted t_box values. Use ty::get -// to cast them back to a box. (Without the cast, compiler performance suffers -// ~15%.) This does mean that a Ty value relies on the ctxt to keep its box -// alive, and using ty::get is unsafe when the ctxt is no longer alive. -enum t_opaque {} +impl PartialEq for TyS { + fn eq(&self, other: &TyS) -> bool { + (self as *const _) == (other as *const _) + } +} +impl Eq for TyS {} -#[allow(raw_pointer_deriving)] -#[deriving(Clone, PartialEq, Eq, Hash)] -pub struct Ty { inner: *const t_opaque } - -impl fmt::Show for Ty { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", get(*self)) +impl Hash for TyS { + fn hash(&self, s: &mut S) { + (self as *const _).hash(s) } } -pub fn get(ty: Ty) -> t_box { - unsafe { - let t2: t_box = mem::transmute(ty); - t2 +pub type Ty<'tcx> = &'tcx TyS; + +/// An entry in the type interner. +struct InternedTy<'tcx> { + ty: Ty<'tcx> +} + +// NB: An InternedTy compares and hashes as a sty. +impl<'tcx> PartialEq for InternedTy<'tcx> { + fn eq(&self, other: &InternedTy<'tcx>) -> bool { + self.ty.sty == other.ty.sty + } +} +impl<'tcx> Eq for InternedTy<'tcx> {} + +impl<'tcx, S: Writer> Hash for InternedTy<'tcx> { + fn hash(&self, s: &mut S) { + self.ty.sty.hash(s) } } -fn tbox_has_flag(tb: t_box, flag: TypeFlags) -> bool { - tb.flags.intersects(flag) +impl<'tcx> BorrowFrom> for sty<'tcx> { + fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> { + &ty.ty.sty + } +} + +pub fn get(ty: Ty) -> Ty { + ty +} + +fn tbox_has_flag(ty: Ty, flag: TypeFlags) -> bool { + ty.flags.intersects(flag) } pub fn type_has_params(ty: Ty) -> bool { tbox_has_flag(get(ty), HAS_PARAMS) @@ -1024,13 +1019,13 @@ pub enum BoundRegion { } mod primitives { - use super::t_box_; + use super::TyS; use syntax::ast; macro_rules! def_prim_ty( ($name:ident, $sty:expr) => ( - pub static $name: t_box_ = t_box_ { + pub static $name: TyS = TyS { sty: $sty, flags: super::NO_TYPE_FLAGS, region_depth: 0, @@ -1053,7 +1048,7 @@ mod primitives { def_prim_ty!(TY_F32, super::ty_float(ast::TyF32)) def_prim_ty!(TY_F64, super::ty_float(ast::TyF64)) - pub static TY_ERR: t_box_ = t_box_ { + pub static TY_ERR: TyS = TyS { sty: super::ty_err, flags: super::HAS_TY_ERR, region_depth: 0, @@ -1701,7 +1696,7 @@ impl UnboxedClosureKind { } pub fn mk_ctxt<'tcx>(s: Session, - type_arena: &'tcx TypedArena, + type_arena: &'tcx TypedArena, dm: resolve::DefMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, @@ -1785,32 +1780,22 @@ pub fn mk_t(cx: &ctxt, st: sty) -> Ty { _ => {} }; - let key = intern_key { sty: &st }; - - match cx.interner.borrow().get(&key) { - Some(ty) => unsafe { return mem::transmute(&ty.sty); }, + match cx.interner.borrow().get(&st) { + Some(ty) => return ty, _ => () } let flags = FlagComputation::for_sty(&st); - let ty = cx.type_arena.alloc(t_box_ { + let ty = cx.type_arena.alloc(TyS { sty: st, flags: flags.flags, region_depth: flags.depth, }); - let sty_ptr = &ty.sty as *const sty; + cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty); - let key = intern_key { - sty: sty_ptr, - }; - - cx.interner.borrow_mut().insert(key, ty); - - unsafe { - mem::transmute::<*const sty, Ty>(sty_ptr) - } + Ty { inner: ty } } struct FlagComputation { @@ -1996,10 +1981,8 @@ impl FlagComputation { } #[inline] -pub fn mk_prim_t(primitive: &'static t_box_) -> Ty { - unsafe { - mem::transmute::<&'static t_box_, Ty>(primitive) - } +pub fn mk_prim_t(primitive: &'static TyS) -> Ty { + Ty { inner: primitive } } #[inline]