From 88c5679c4e0ba0bd21a15eaaf8e5fafcc6bcdafd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 2 Sep 2016 11:08:16 +0300 Subject: [PATCH] rustc_metadata: remove ty{en,de}code and move to auto-derived serialization. --- src/librustc/ty/context.rs | 108 +++-- src/librustc/ty/mod.rs | 40 ++ src/librustc/ty/structural_impls.rs | 13 +- src/librustc/ty/sty.rs | 55 +-- src/librustc_const_eval/check_match.rs | 27 +- src/librustc_metadata/common.rs | 9 +- src/librustc_metadata/decoder.rs | 54 ++- src/librustc_metadata/encoder.rs | 51 ++- src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/tydecode.rs | 598 ------------------------- src/librustc_metadata/tyencode.rs | 385 ---------------- src/libserialize/collection_impls.rs | 4 +- 12 files changed, 235 insertions(+), 1113 deletions(-) delete mode 100644 src/librustc_metadata/tydecode.rs delete mode 100644 src/librustc_metadata/tyencode.rs diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index bb9e90f8919..338ea6b0dd6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -25,7 +25,7 @@ use middle::stability; use ty::subst::Substs; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; -use ty::{TyS, TypeVariants}; +use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; @@ -92,7 +92,7 @@ pub struct CtxtInterners<'tcx> { /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. type_: RefCell>>>, - type_list: RefCell]>>>, + type_list: RefCell>>>>, substs: RefCell>>>, bare_fn: RefCell>>>, region: RefCell>>, @@ -847,10 +847,11 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Region { } } -impl<'a, 'tcx> Lift<'tcx> for &'a [Ty<'a>] { - type Lifted = &'tcx [Ty<'tcx>]; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx [Ty<'tcx>]> { - if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(*self) { +impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { + type Lifted = &'tcx Slice>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) + -> Option<&'tcx Slice>> { + if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) { if *self as *const _ == list as *const _ { return Some(list); } @@ -1067,9 +1068,24 @@ impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, TyS<'tcx>> } } -impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, [Ty<'tcx>]> { +// NB: An Interned> compares and hashes as its elements. +impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice> { + fn eq(&self, other: &Interned<'tcx, Slice>) -> bool { + self.0[..] == other.0[..] + } +} + +impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice> {} + +impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice> { + fn hash(&self, s: &mut H) { + self.0[..].hash(s) + } +} + +impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice>> { fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { - self.0 + &self.0[..] } } @@ -1091,32 +1107,23 @@ impl<'tcx> Borrow for Interned<'tcx, Region> { } } -macro_rules! items { ($($item:item)+) => ($($item)+) } -macro_rules! impl_interners { - ($lt_tcx:tt, $($name:ident: $method:ident($alloc:ty, $needs_infer:expr)-> $ty:ty),+) => { - items!($(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} - - impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { - fn hash(&self, s: &mut H) { - self.0.hash(s) - } - } - +macro_rules! intern_method { + ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, + $alloc_to_key:expr, + $alloc_to_ret:expr, + $needs_infer:expr) -> $ty:ty) => { impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { - if let Some(i) = self.interners.$name.borrow().get::<$ty>(&v) { - return i.0; - } - if !self.is_global() { - if let Some(i) = self.global_interners.$name.borrow().get::<$ty>(&v) { + { + let key = ($alloc_to_key)(&v); + if let Some(i) = self.interners.$name.borrow().get(key) { return i.0; } + if !self.is_global() { + if let Some(i) = self.global_interners.$name.borrow().get(key) { + return i.0; + } + } } // HACK(eddyb) Depend on flags being accurate to @@ -1127,7 +1134,7 @@ macro_rules! impl_interners { let v = unsafe { mem::transmute(v) }; - let i = self.global_interners.arenas.$name.alloc(v); + let i = ($alloc_to_ret)(self.global_interners.arenas.$name.alloc(v)); self.global_interners.$name.borrow_mut().insert(Interned(i)); return i; } @@ -1141,11 +1148,31 @@ macro_rules! impl_interners { } } - let i = self.interners.arenas.$name.alloc(v); + let i = ($alloc_to_ret)(self.interners.arenas.$name.alloc(v)); self.interners.$name.borrow_mut().insert(Interned(i)); i } - })+); + } + } +} + +macro_rules! direct_interners { + ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => { + $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} + + impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { + fn hash(&self, s: &mut H) { + self.0.hash(s) + } + } + + intern_method!($lt_tcx, $name: $method($ty, |x| x, |x| x, $needs_infer) -> $ty);)+ } } @@ -1153,15 +1180,14 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) } -impl_interners!('tcx, - type_list: mk_type_list(Vec>, keep_local) -> [Ty<'tcx>], - substs: mk_substs(Substs<'tcx>, |substs: &Substs| { +direct_interners!('tcx, + substs: mk_substs(|substs: &Substs| { substs.params().iter().any(keep_local) }) -> Substs<'tcx>, - bare_fn: mk_bare_fn(BareFnTy<'tcx>, |fty: &BareFnTy| { + bare_fn: mk_bare_fn(|fty: &BareFnTy| { keep_local(&fty.sig) }) -> BareFnTy<'tcx>, - region: mk_region(Region, |r| { + region: mk_region(|r| { match r { &ty::ReVar(_) | &ty::ReSkolemized(..) => true, _ => false @@ -1169,6 +1195,12 @@ impl_interners!('tcx, }) -> Region ); +intern_method!('tcx, + type_list: mk_type_list(Vec>, Deref::deref, |xs: &[Ty]| -> &Slice { + unsafe { mem::transmute(xs) } + }, keep_local) -> Slice> +); + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Create an unsafe fn ty based on a safe fn ty. pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d4dd8298db3..59475b42226 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -38,6 +38,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::hash::{Hash, Hasher}; use std::iter; +use std::ops::Deref; use std::rc::Rc; use std::slice; use std::vec::IntoIter; @@ -569,6 +570,45 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} +/// A wrapper for slices with the additioanl invariant +/// that the slice is interned and no other slice with +/// the same contents can exist in the same context. +/// This means we can use pointer + length for both +/// equality comparisons and hashing. +#[derive(Debug, RustcEncodable)] +pub struct Slice([T]); + +impl PartialEq for Slice { + #[inline] + fn eq(&self, other: &Slice) -> bool { + (&self.0 as *const [T]) == (&other.0 as *const [T]) + } +} +impl Eq for Slice {} + +impl Hash for Slice { + fn hash(&self, s: &mut H) { + (self.as_ptr(), self.len()).hash(s) + } +} + +impl Deref for Slice { + type Target = [T]; + fn deref(&self) -> &[T] { + &self.0 + } +} + +impl<'a, T> IntoIterator for &'a Slice { + type Item = &'a T; + type IntoIter = <&'a [T] as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self[..].iter() + } +} + +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} + /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 6c3dabfe113..5a87ea1473d 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -14,7 +14,6 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use std::rc::Rc; use syntax::abi; -use syntax::ptr::P; use hir; @@ -437,16 +436,6 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TraitObject { @@ -464,7 +453,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx [Ty<'tcx>] { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let tys = self.iter().map(|t| t.fold_with(folder)).collect(); folder.tcx().mk_type_list(tys) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0f2ff8a689f..302cab0446c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -13,12 +13,12 @@ use hir::def_id::DefId; use middle::region; use ty::subst::Substs; -use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable}; +use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use ty::{Slice, TyS}; use util::common::ErrorReported; use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; -use std::mem; use std::ops; use syntax::abi; use syntax::ast::{self, Name}; @@ -31,7 +31,7 @@ use hir; use self::InferTy::*; use self::TypeVariants::*; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct TypeAndMut<'tcx> { pub ty: Ty<'tcx>, pub mutbl: hir::Mutability, @@ -87,7 +87,7 @@ pub enum Issue32330 { // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum TypeVariants<'tcx> { /// The primitive boolean type. Written as `bool`. TyBool, @@ -155,7 +155,7 @@ pub enum TypeVariants<'tcx> { TyNever, /// A tuple type. For example, `(i32, bool)`. - TyTuple(&'tcx [Ty<'tcx>]), + TyTuple(&'tcx Slice>), /// The projection of an associated type. For example, /// `>::N`. @@ -252,7 +252,7 @@ pub enum TypeVariants<'tcx> { /// closure C wind up influencing the decisions we ought to make for /// closure C (which would then require fixed point iteration to /// handle). Plus it fixes an ICE. :P -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function. /// These are separated out because trans wants to pass them around @@ -262,12 +262,10 @@ pub struct ClosureSubsts<'tcx> { /// The types of the upvars. The list parallels the freevars and /// `upvar_borrows` lists. These are kept distinct so that we can /// easily index into them. - pub upvar_tys: &'tcx [Ty<'tcx>] + pub upvar_tys: &'tcx Slice> } -impl<'tcx> serialize::UseSpecializedDecodable for ClosureSubsts<'tcx> {} - -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitObject<'tcx> { pub principal: PolyExistentialTraitRef<'tcx>, pub region_bound: &'tcx ty::Region, @@ -330,7 +328,7 @@ impl<'tcx> PolyTraitRef<'tcx> { /// /// The substitutions don't include the erased `Self`, only trait /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ExistentialTraitRef<'tcx> { pub def_id: DefId, pub substs: &'tcx Substs<'tcx>, @@ -423,13 +421,15 @@ pub struct ProjectionTy<'tcx> { pub item_name: Name, } -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BareFnTy<'tcx> { pub unsafety: hir::Unsafety, pub abi: abi::Abi, pub sig: PolyFnSig<'tcx>, } +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx BareFnTy<'tcx> {} + #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ClosureTy<'tcx> { pub unsafety: hir::Unsafety, @@ -467,7 +467,7 @@ impl<'tcx> PolyFnSig<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct ParamTy { pub idx: u32, pub name: Name, @@ -654,17 +654,17 @@ pub struct EarlyBoundRegion { pub name: Name, } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TyVid { pub index: u32, } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct IntVid { pub index: u32 } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct FloatVid { pub index: u32 } @@ -679,7 +679,7 @@ pub struct SkolemizedRegionVid { pub index: u32 } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -694,7 +694,7 @@ pub enum InferTy { } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExistentialProjection<'tcx> { pub trait_ref: ExistentialTraitRef<'tcx>, pub item_name: Name, @@ -739,7 +739,7 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BuiltinBounds(EnumSet); impl<'a, 'gcx, 'tcx> BuiltinBounds { @@ -782,12 +782,11 @@ impl<'a> IntoIterator for &'a BuiltinBounds { #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, Debug, Copy)] -#[repr(usize)] pub enum BuiltinBound { - Send, - Sized, - Copy, - Sync, + Send = 0, + Sized = 1, + Copy = 2, + Sync = 3, } impl CLike for BuiltinBound { @@ -795,7 +794,13 @@ impl CLike for BuiltinBound { *self as usize } fn from_usize(v: usize) -> BuiltinBound { - unsafe { mem::transmute(v) } + match v { + 0 => BuiltinBound::Send, + 1 => BuiltinBound::Sized, + 2 => BuiltinBound::Copy, + 3 => BuiltinBound::Sync, + _ => bug!("{} is not a valid BuiltinBound", v) + } } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index dda72ce57b4..8af06286189 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -26,8 +26,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization::{cmt}; use rustc::hir::pat_util::*; use rustc::traits::Reveal; -use rustc::ty::*; -use rustc::ty; +use rustc::ty::{self, Ty, TyCtxt}; use std::cmp::Ordering; use std::fmt; use std::iter::{FromIterator, IntoIterator, repeat}; @@ -110,7 +109,7 @@ impl<'a, 'tcx> FromIterator>)>> for Matrix<'a, 'tc //NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv pub struct MatchCheckCtxt<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub param_env: ParameterEnvironment<'tcx>, + pub param_env: ty::ParameterEnvironment<'tcx>, } #[derive(Clone, Debug, PartialEq)] @@ -248,7 +247,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) if edef.is_enum() { if let Def::Local(..) = cx.tcx.expect_def(p.id) { if edef.variants.iter().any(|variant| { - variant.name == name.node && variant.kind == VariantKind::Unit + variant.name == name.node && variant.kind == ty::VariantKind::Unit }) { let ty_path = cx.tcx.item_path_str(edef.did); let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, @@ -579,7 +578,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, ty::TyAdt(adt, _) => { let v = ctor.variant_for_adt(adt); match v.kind { - VariantKind::Struct => { + ty::VariantKind::Struct => { let field_pats: hir::HirVec<_> = v.fields.iter() .zip(pats) .filter(|&(_, ref pat)| pat.node != PatKind::Wild) @@ -594,10 +593,10 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, let has_more_fields = field_pats.len() < pats_len; PatKind::Struct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields) } - VariantKind::Tuple => { + ty::VariantKind::Tuple => { PatKind::TupleStruct(def_to_path(cx.tcx, v.did), pats.collect(), None) } - VariantKind::Unit => { + ty::VariantKind::Unit => { PatKind::Path(None, def_to_path(cx.tcx, v.did)) } } @@ -639,7 +638,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, impl Constructor { fn variant_for_adt<'tcx, 'container, 'a>(&self, adt: &'a ty::AdtDefData<'tcx, 'container>) - -> &'a VariantDefData<'tcx, 'container> { + -> &'a ty::VariantDefData<'tcx, 'container> { match self { &Variant(vid) => adt.variant_with_id(vid), _ => adt.struct_variant() @@ -878,7 +877,7 @@ fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>, let pat_ty = cx.tcx.pat_ty(pat); (pat, Some(match pat.node { PatKind::Binding(hir::BindByRef(..), ..) => { - pat_ty.builtin_deref(false, NoPreference).unwrap().ty + pat_ty.builtin_deref(false, ty::NoPreference).unwrap().ty } _ => pat_ty })) @@ -1068,7 +1067,7 @@ fn check_fn(cx: &mut MatchCheckCtxt, fn_id: NodeId) { match kind { FnKind::Closure(_) => {} - _ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id), + _ => cx.param_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_id), } intravisit::walk_fn(cx, kind, decl, body, sp, fn_id); @@ -1187,17 +1186,17 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { _: NodeId, span: Span, _: cmt, - _: &'tcx Region, - kind: BorrowKind, + _: &'tcx ty::Region, + kind:ty:: BorrowKind, _: LoanCause) { match kind { - MutBorrow => { + ty::MutBorrow => { struct_span_err!(self.cx.tcx.sess, span, E0301, "cannot mutably borrow in a pattern guard") .span_label(span, &format!("borrowed mutably in pattern guard")) .emit(); } - ImmBorrow | UniqueImmBorrow => {} + ty::ImmBorrow | ty::UniqueImmBorrow => {} } } fn decl_without_init(&mut self, _: NodeId, _: Span) {} diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 3b63ee6b5fa..123ed11a7a5 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -10,9 +10,7 @@ #![allow(non_camel_case_types, non_upper_case_globals)] -pub const tag_opaque: usize = 0x00; - -// GAP 0x01...0x19 +// GAP 0x00...0x19 pub const tag_items: usize = 0x100; // top-level only @@ -214,3 +212,8 @@ pub const tag_macro_derive_registrar: usize = 0x115; // NB: increment this if you change the format of metadata such that // rustc_version can't be found. pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2]; + +/// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize` +/// and is offset by this value so it never matches a real variant. +/// This offset is also chosen so that the first byte is never < 0x80. +pub const TYPE_SHORTHAND_OFFSET: usize = 0x80; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d3c04874a08..0118cacad18 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -20,7 +20,6 @@ use common::*; use def_key; use encoder::def_to_u64; use index; -use tydecode::TyDecoder; use rustc::hir::def_id::CRATE_DEF_INDEX; use rustc::hir::svh::Svh; @@ -45,13 +44,14 @@ use rustc_const_math::ConstInt; use rustc::mir::repr::Mir; use std::io; +use std::mem; use std::rc::Rc; use std::str; use std::u32; use rbml::reader; use rbml; -use rustc_serialize::{Decodable, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use rustc_serialize as serialize; use syntax::attr; use syntax::parse::token; @@ -233,35 +233,53 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - let pos = self.opaque.position(); - let doc = rbml::Doc::at(self.opaque.data, pos); - self.opaque.advance(doc.end - pos); - Ok(TyDecoder::with_doc(self.tcx(), self.cdata().cnum, doc, - &mut |d| translate_def_id(self.cdata(), d)) - .parse_ty()) + let tcx = self.tcx(); + + // Handle shorthands first, if we have an usize > 0x80. + if self.opaque.data[self.opaque.position()] & 0x80 != 0 { + let pos = self.read_usize()?; + assert!(pos >= TYPE_SHORTHAND_OFFSET); + let key = ty::CReaderCacheKey { + cnum: self.cdata().cnum, + pos: pos - TYPE_SHORTHAND_OFFSET + }; + if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() { + return Ok(ty); + } + + let new = opaque::Decoder::new(self.opaque.data, key.pos); + let old = mem::replace(&mut self.opaque, new); + let ty = Ty::decode(self)?; + self.opaque = old; + tcx.rcache.borrow_mut().insert(key, ty); + return Ok(ty); + } + + Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?)) } } impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> { - let substs = Substs::decode(self)?; - Ok(self.tcx().mk_substs(substs)) + Ok(self.tcx().mk_substs(Decodable::decode(self)?)) } } impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::Region, Self::Error> { - let r = ty::Region::decode(self)?; - Ok(self.tcx().mk_region(r)) + Ok(self.tcx().mk_region(Decodable::decode(self)?)) } } -impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(ty::ClosureSubsts { - func_substs: Decodable::decode(self)?, - upvar_tys: self.tcx().mk_type_list(Decodable::decode(self)?) - }) +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice>, Self::Error> { + Ok(self.tcx().mk_type_list(Decodable::decode(self)?)) + } +} + +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::BareFnTy<'tcx>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::BareFnTy<'tcx>, Self::Error> { + Ok(self.tcx().mk_bare_fn(Decodable::decode(self)?)) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index dcc3d13631e..e414275f8b4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -18,7 +18,6 @@ use common::*; use cstore; use decoder; use def_key; -use tyencode; use index::{self, IndexData}; use middle::cstore::{InlinedItemRef, LinkMeta}; @@ -34,8 +33,10 @@ use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro}; use rustc::util::nodemap::{FnvHashMap, NodeSet}; -use rustc_serialize::{Encodable, SpecializedEncoder, opaque}; +use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use rustc_serialize as serialize; +use std::cell::RefCell; +use std::intrinsics; use std::io::prelude::*; use std::io::Cursor; use std::ops::{Deref, DerefMut}; @@ -55,14 +56,14 @@ use rustc::hir::map::DefKey; use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef}; pub struct EncodeContext<'a, 'tcx: 'a> { - pub rbml_w: rbml::writer::Encoder<'a>, + rbml_w: rbml::writer::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub reexports: &'a def::ExportMap, - pub link_meta: &'a LinkMeta, - pub cstore: &'a cstore::CStore, - pub type_abbrevs: &'a tyencode::abbrev_map<'tcx>, - pub reachable: &'a NodeSet, - pub mir_map: &'a MirMap<'tcx>, + reexports: &'a def::ExportMap, + link_meta: &'a LinkMeta, + cstore: &'a cstore::CStore, + type_shorthands: RefCell, usize>>, + reachable: &'a NodeSet, + mir_map: &'a MirMap<'tcx>, } impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> { @@ -116,12 +117,32 @@ impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { - let cx = self.ty_str_ctxt(); + let existing_shorthand = self.type_shorthands.borrow().get(ty).cloned(); + if let Some(shorthand) = existing_shorthand { + return self.emit_usize(shorthand); + } - self.start_tag(tag_opaque)?; - tyencode::enc_ty(&mut self.rbml_w.opaque.cursor, &cx, ty); - self.mark_stable_position(); - self.end_tag() + let start = self.mark_stable_position(); + ty.sty.encode(self)?; + let len = self.mark_stable_position() - start; + + // The shorthand encoding uses the same usize as the + // discriminant, with an offset so they can't conflict. + let discriminant = unsafe { intrinsics::discriminant_value(&ty.sty) }; + assert!(discriminant < TYPE_SHORTHAND_OFFSET as u64); + let shorthand = start + TYPE_SHORTHAND_OFFSET; + + // Get the number of bits that leb128 could fit + // in the same space as the fully encoded type. + let leb128_bits = len * 7; + + // Check that the shorthand is a not longer than the + // full encoding itself, i.e. it's an obvious win. + if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) { + self.type_shorthands.borrow_mut().insert(*ty, shorthand); + } + + Ok(()) } } @@ -1742,7 +1763,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: cstore, reachable: reachable, mir_map: mir_map, - type_abbrevs: &Default::default(), + type_shorthands: Default::default(), }); // RBML compacts the encoded bytes whenever appropriate, diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 7205a88618f..e5f7aab38c3 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -17,9 +17,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(not(stage0), deny(warnings))] +#![feature(core_intrinsics)] #![feature(box_patterns)] #![feature(dotdot_in_tuple_patterns)] -#![feature(enumset)] #![feature(question_mark)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -63,8 +63,6 @@ pub mod diagnostics; pub mod astencode; pub mod common; pub mod def_key; -pub mod tyencode; -pub mod tydecode; pub mod encoder; mod index_builder; pub mod decoder; diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs deleted file mode 100644 index ccc4894fcdd..00000000000 --- a/src/librustc_metadata/tydecode.rs +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// Type decoding - -// tjc note: Would be great to have a `match check` macro equivalent -// for some of these - -#![allow(non_camel_case_types)] - -use rustc::hir; - -use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; -use middle::region; -use rustc::ty::subst::{Kind, Substs}; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; - -use rbml; -use rustc_serialize::leb128; -use std::str; -use syntax::abi; -use syntax::ast; -use syntax::parse::token; - -// Compact string representation for Ty values. API TyStr & -// parse_from_str. Extra parameters are for converting to/from def_ids in the -// data buffer. Whatever format you choose should not contain pipe characters. - -pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId; - -pub struct TyDecoder<'a, 'tcx: 'a> { - data: &'a [u8], - krate: CrateNum, - pos: usize, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - conv_def_id: DefIdConvert<'a>, -} - -impl<'a,'tcx> TyDecoder<'a,'tcx> { - pub fn with_doc(tcx: TyCtxt<'a, 'tcx, 'tcx>, - crate_num: CrateNum, - doc: rbml::Doc<'a>, - conv: DefIdConvert<'a>) - -> TyDecoder<'a,'tcx> { - TyDecoder::new(doc.data, crate_num, doc.start, tcx, conv) - } - - pub fn new(data: &'a [u8], - crate_num: CrateNum, - pos: usize, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - conv: DefIdConvert<'a>) - -> TyDecoder<'a, 'tcx> { - TyDecoder { - data: data, - krate: crate_num, - pos: pos, - tcx: tcx, - conv_def_id: conv, - } - } - - pub fn position(&self) -> usize { - self.pos - } - - fn peek(&self) -> char { - self.data[self.pos] as char - } - - fn next(&mut self) -> char { - let ch = self.data[self.pos] as char; - self.pos = self.pos + 1; - return ch; - } - - fn next_byte(&mut self) -> u8 { - let b = self.data[self.pos]; - self.pos = self.pos + 1; - return b; - } - - fn scan(&mut self, mut is_last: F) -> &'a [u8] - where F: FnMut(char) -> bool, - { - let start_pos = self.pos; - debug!("scan: '{}' (start)", self.data[self.pos] as char); - while !is_last(self.data[self.pos] as char) { - self.pos += 1; - debug!("scan: '{}'", self.data[self.pos] as char); - } - let end_pos = self.pos; - self.pos += 1; - return &self.data[start_pos..end_pos]; - } - - fn parse_vuint(&mut self) -> usize { - let (value, bytes_read) = leb128::read_unsigned_leb128(self.data, - self.pos); - self.pos += bytes_read; - value as usize - } - - fn parse_size(&mut self) -> Option { - assert_eq!(self.next(), '/'); - - if self.peek() == '|' { - assert_eq!(self.next(), '|'); - None - } else { - let n = self.parse_uint(); - assert_eq!(self.next(), '|'); - Some(n) - } - } - - fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { - let mut params = vec![]; - assert_eq!(self.next(), '['); - while self.peek() != ']' { - let k = match self.next() { - 'r' => Kind::from(self.parse_region()), - 't' => Kind::from(self.parse_ty()), - _ => bug!() - }; - params.push(k); - } - assert_eq!(self.next(), ']'); - - Substs::new(self.tcx, params) - } - - fn parse_bound_region(&mut self) -> ty::BoundRegion { - match self.next() { - 'a' => { - let id = self.parse_u32(); - assert_eq!(self.next(), '|'); - ty::BrAnon(id) - } - '[' => { - let def = self.parse_def(); - let name = token::intern(&self.parse_str('|')); - let issue32330 = match self.next() { - 'n' => { - assert_eq!(self.next(), ']'); - ty::Issue32330::WontChange - } - 'y' => { - ty::Issue32330::WillChange { - fn_def_id: self.parse_def(), - region_name: token::intern(&self.parse_str(']')), - } - } - c => panic!("expected n or y not {}", c) - }; - ty::BrNamed(def, name, issue32330) - } - 'f' => { - let id = self.parse_u32(); - assert_eq!(self.next(), '|'); - ty::BrFresh(id) - } - 'e' => ty::BrEnv, - _ => bug!("parse_bound_region: bad input") - } - } - - fn parse_region(&mut self) -> &'tcx ty::Region { - self.tcx.mk_region(match self.next() { - 'b' => { - assert_eq!(self.next(), '['); - let id = ty::DebruijnIndex::new(self.parse_u32()); - assert_eq!(self.next(), '|'); - let br = self.parse_bound_region(); - assert_eq!(self.next(), ']'); - ty::ReLateBound(id, br) - } - 'B' => { - assert_eq!(self.next(), '['); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let name = token::intern(&self.parse_str(']')); - ty::ReEarlyBound(ty::EarlyBoundRegion { - index: index, - name: name - }) - } - 'f' => { - assert_eq!(self.next(), '['); - let scope = self.parse_scope(); - assert_eq!(self.next(), '|'); - let br = self.parse_bound_region(); - assert_eq!(self.next(), ']'); - ty::ReFree(ty::FreeRegion { scope: scope, - bound_region: br}) - } - 's' => { - let scope = self.parse_scope(); - assert_eq!(self.next(), '|'); - ty::ReScope(scope) - } - 't' => ty::ReStatic, - 'e' => ty::ReEmpty, - 'E' => ty::ReErased, - _ => bug!("parse_region: bad input") - }) - } - - fn parse_scope(&mut self) -> region::CodeExtent { - self.tcx.region_maps.bogus_code_extent(match self.next() { - // This creates scopes with the wrong NodeId. This isn't - // actually a problem because scopes only exist *within* - // functions, and functions aren't loaded until trans which - // doesn't care about regions. - // - // May still be worth fixing though. - 'C' => { - assert_eq!(self.next(), '['); - let fn_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let body_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), ']'); - region::CodeExtentData::CallSiteScope { - fn_id: fn_id, body_id: body_id - } - } - // This creates scopes with the wrong NodeId. (See note above.) - 'P' => { - assert_eq!(self.next(), '['); - let fn_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let body_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), ']'); - region::CodeExtentData::ParameterScope { - fn_id: fn_id, body_id: body_id - } - } - 'M' => { - let node_id = ast::NodeId::new(self.parse_uint()); - region::CodeExtentData::Misc(node_id) - } - 'D' => { - let node_id = ast::NodeId::new(self.parse_uint()); - region::CodeExtentData::DestructionScope(node_id) - } - 'B' => { - assert_eq!(self.next(), '['); - let node_id = ast::NodeId::new(self.parse_uint()); - assert_eq!(self.next(), '|'); - let first_stmt_index = self.parse_u32(); - assert_eq!(self.next(), ']'); - let block_remainder = region::BlockRemainder { - block: node_id, first_statement_index: first_stmt_index, - }; - region::CodeExtentData::Remainder(block_remainder) - } - _ => bug!("parse_scope: bad input") - }) - } - - fn parse_str(&mut self, term: char) -> String { - let mut result = String::new(); - while self.peek() != term { - unsafe { - result.as_mut_vec().extend_from_slice(&[self.next_byte()]) - } - } - self.next(); - result - } - - fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { - ty::TraitRef { - def_id: self.parse_def(), - substs: self.parse_substs() - } - } - - fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { - ty::ExistentialTraitRef { - def_id: self.parse_def(), - substs: self.parse_substs() - } - } - - pub fn parse_ty(&mut self) -> Ty<'tcx> { - let tcx = self.tcx; - match self.next() { - 'b' => return tcx.types.bool, - '!' => return tcx.types.never, - 'i' => { /* eat the s of is */ self.next(); return tcx.types.isize }, - 'u' => { /* eat the s of us */ self.next(); return tcx.types.usize }, - 'M' => { - match self.next() { - 'b' => return tcx.types.u8, - 'w' => return tcx.types.u16, - 'l' => return tcx.types.u32, - 'd' => return tcx.types.u64, - 'B' => return tcx.types.i8, - 'W' => return tcx.types.i16, - 'L' => return tcx.types.i32, - 'D' => return tcx.types.i64, - 'f' => return tcx.types.f32, - 'F' => return tcx.types.f64, - _ => bug!("parse_ty: bad numeric type") - } - } - 'c' => return tcx.types.char, - 'x' => { - assert_eq!(self.next(), '['); - let trait_ref = ty::Binder(self.parse_existential_trait_ref()); - let builtin_bounds = self.parse_builtin_bounds(); - let region_bound = self.parse_region(); - let mut projection_bounds = Vec::new(); - - loop { - match self.next() { - 'P' => { - let bound = self.parse_existential_projection(); - projection_bounds.push(ty::Binder(bound)); - } - '.' => { break; } - c => { - bug!("parse_bounds: bad bounds ('{}')", c) - } - } - } - assert_eq!(self.next(), ']'); - return tcx.mk_trait(ty::TraitObject { - principal: trait_ref, - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: projection_bounds - }); - } - 'p' => { - assert_eq!(self.next(), '['); - let index = self.parse_u32(); - assert_eq!(self.next(), '|'); - let name = token::intern(&self.parse_str(']')); - return tcx.mk_param(index, name); - } - '~' => return tcx.mk_box(self.parse_ty()), - '*' => return tcx.mk_ptr(self.parse_mt()), - '&' => { - return tcx.mk_ref(self.parse_region(), self.parse_mt()); - } - 'V' => { - let t = self.parse_ty(); - return match self.parse_size() { - Some(n) => tcx.mk_array(t, n), - None => tcx.mk_slice(t) - }; - } - 'v' => { - return tcx.mk_str(); - } - 'T' => { - assert_eq!(self.next(), '['); - let mut params = Vec::new(); - while self.peek() != ']' { params.push(self.parse_ty()); } - self.pos = self.pos + 1; - return tcx.mk_tup(params); - } - 'F' => { - let def_id = self.parse_def(); - let substs = self.parse_substs(); - return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty()); - } - 'G' => { - return tcx.mk_fn_ptr(self.parse_bare_fn_ty()); - } - '#' => { - // This is a hacky little caching scheme. The idea is that if we encode - // the same type twice, the second (and third, and fourth...) time we will - // just write `#123`, where `123` is the offset in the metadata of the - // first appearance. Now when we are *decoding*, if we see a `#123`, we - // can first check a cache (`tcx.rcache`) for that offset. If we find something, - // we return it (modulo closure types, see below). But if not, then we - // jump to offset 123 and read the type from there. - - let pos = self.parse_vuint(); - let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos }; - if let Some(tt) = tcx.rcache.borrow().get(&key).cloned() { - // If there is a closure buried in the type some where, then we - // need to re-convert any def ids (see case 'k', below). That means - // we can't reuse the cached version. - if !tt.has_closure_types() { - return tt; - } - } - - let mut substate = TyDecoder::new(self.data, - self.krate, - pos, - self.tcx, - self.conv_def_id); - let tt = substate.parse_ty(); - tcx.rcache.borrow_mut().insert(key, tt); - return tt; - } - '\"' => { - let _ = self.parse_def(); - let inner = self.parse_ty(); - inner - } - 'a' => { - assert_eq!(self.next(), '['); - let did = self.parse_def(); - let substs = self.parse_substs(); - assert_eq!(self.next(), ']'); - let def = self.tcx.lookup_adt_def(did); - return self.tcx.mk_adt(def, substs); - } - 'k' => { - assert_eq!(self.next(), '['); - let did = self.parse_def(); - let substs = self.parse_substs(); - let mut tys = vec![]; - while self.peek() != '.' { - tys.push(self.parse_ty()); - } - assert_eq!(self.next(), '.'); - assert_eq!(self.next(), ']'); - return self.tcx.mk_closure(did, substs, tys); - } - 'P' => { - assert_eq!(self.next(), '['); - let trait_ref = self.parse_trait_ref(); - let name = token::intern(&self.parse_str(']')); - return tcx.mk_projection(trait_ref, name); - } - 'A' => { - assert_eq!(self.next(), '['); - let def_id = self.parse_def(); - let substs = self.parse_substs(); - assert_eq!(self.next(), ']'); - return self.tcx.mk_anon(def_id, substs); - } - 'e' => { - return tcx.types.err; - } - c => { bug!("unexpected char in type string: {}", c);} - } - } - - fn parse_mutability(&mut self) -> hir::Mutability { - match self.peek() { - 'm' => { self.next(); hir::MutMutable } - _ => { hir::MutImmutable } - } - } - - fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> { - let m = self.parse_mutability(); - ty::TypeAndMut { ty: self.parse_ty(), mutbl: m } - } - - fn parse_def(&mut self) -> DefId { - let def_id = parse_defid(self.scan(|c| c == '|')); - return (self.conv_def_id)(def_id); - } - - fn parse_uint(&mut self) -> usize { - let mut n = 0; - loop { - let cur = self.peek(); - if cur < '0' || cur > '9' { return n; } - self.pos = self.pos + 1; - n *= 10; - n += (cur as usize) - ('0' as usize); - }; - } - - fn parse_u32(&mut self) -> u32 { - let n = self.parse_uint(); - let m = n as u32; - assert_eq!(m as usize, n); - m - } - - fn parse_abi_set(&mut self) -> abi::Abi { - assert_eq!(self.next(), '['); - let bytes = self.scan(|c| c == ']'); - let abi_str = str::from_utf8(bytes).unwrap(); - abi::lookup(&abi_str[..]).expect(abi_str) - } - - fn parse_bare_fn_ty(&mut self) -> &'tcx ty::BareFnTy<'tcx> { - let unsafety = parse_unsafety(self.next()); - let abi = self.parse_abi_set(); - let sig = self.parse_sig(); - self.tcx.mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: sig - }) - } - - fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> { - assert_eq!(self.next(), '['); - let mut inputs = Vec::new(); - while self.peek() != ']' { - inputs.push(self.parse_ty()); - } - self.pos += 1; // eat the ']' - let variadic = match self.next() { - 'V' => true, - 'N' => false, - r => bug!("bad variadic: {}", r), - }; - let output = self.parse_ty(); - ty::Binder(ty::FnSig {inputs: inputs, - output: output, - variadic: variadic}) - } - - fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> { - ty::ExistentialProjection { - trait_ref: self.parse_existential_trait_ref(), - item_name: token::intern(&self.parse_str('|')), - ty: self.parse_ty(), - } - } - - fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds { - let mut builtin_bounds = ty::BuiltinBounds::empty(); - loop { - match self.next() { - 'S' => { - builtin_bounds.insert(ty::BoundSend); - } - 'Z' => { - builtin_bounds.insert(ty::BoundSized); - } - 'P' => { - builtin_bounds.insert(ty::BoundCopy); - } - 'T' => { - builtin_bounds.insert(ty::BoundSync); - } - '.' => { - return builtin_bounds; - } - c => { - bug!("parse_bounds: bad builtin bounds ('{}')", c) - } - } - } - } -} - -// Rust metadata parsing -fn parse_defid(buf: &[u8]) -> DefId { - let mut colon_idx = 0; - let len = buf.len(); - while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; } - if colon_idx == len { - error!("didn't find ':' when parsing def id"); - bug!(); - } - - let crate_part = &buf[0..colon_idx]; - let def_part = &buf[colon_idx + 1..len]; - - let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| { - s.parse::().ok() - }) { - Some(cn) => CrateNum::new(cn), - None => bug!("internal error: parse_defid: crate number expected, found {:?}", - crate_part) - }; - let def_num = match str::from_utf8(def_part).ok().and_then(|s| { - s.parse::().ok() - }) { - Some(dn) => dn, - None => bug!("internal error: parse_defid: id expected, found {:?}", - def_part) - }; - let index = DefIndex::new(def_num); - DefId { krate: crate_num, index: index } -} - -fn parse_unsafety(c: char) -> hir::Unsafety { - match c { - 'u' => hir::Unsafety::Unsafe, - 'n' => hir::Unsafety::Normal, - _ => bug!("parse_unsafety: bad unsafety {}", c) - } -} diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs deleted file mode 100644 index 54b4dc93342..00000000000 --- a/src/librustc_metadata/tyencode.rs +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Type encoding - -#![allow(unused_must_use)] // as with encoding, everything is a no-fail MemWriter -#![allow(non_camel_case_types)] - -use std::cell::RefCell; -use std::io::Cursor; -use std::io::prelude::*; - -use rustc::hir::def_id::DefId; -use middle::region; -use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::util::nodemap::FnvHashMap; - -use rustc::hir; - -use syntax::abi::Abi; -use syntax::ast; - -use rustc_serialize::leb128; -use encoder; - -pub struct ctxt<'a, 'tcx: 'a> { - // Def -> str Callback: - pub ds: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String, - // The type context. - pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub abbrevs: &'a abbrev_map<'tcx> -} - -impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> { - pub fn ty_str_ctxt(&self) -> ctxt<'a, 'tcx> { - ctxt { - ds: encoder::def_to_string, - tcx: self.tcx, - abbrevs: self.type_abbrevs - } - } -} - -// Compact string representation for Ty values. API TyStr & parse_from_str. -// Extra parameters are for converting to/from def_ids in the string rep. -// Whatever format you choose should not contain pipe characters. -pub struct ty_abbrev { - s: Vec -} - -pub type abbrev_map<'tcx> = RefCell, ty_abbrev>>; - -pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { - if let Some(a) = cx.abbrevs.borrow_mut().get(&t) { - w.write_all(&a.s); - return; - } - - let pos = w.position(); - - match t.sty { - ty::TyBool => { write!(w, "b"); } - ty::TyChar => { write!(w, "c"); } - ty::TyNever => { write!(w, "!"); } - ty::TyInt(t) => { - match t { - ast::IntTy::Is => write!(w, "is"), - ast::IntTy::I8 => write!(w, "MB"), - ast::IntTy::I16 => write!(w, "MW"), - ast::IntTy::I32 => write!(w, "ML"), - ast::IntTy::I64 => write!(w, "MD") - }; - } - ty::TyUint(t) => { - match t { - ast::UintTy::Us => write!(w, "us"), - ast::UintTy::U8 => write!(w, "Mb"), - ast::UintTy::U16 => write!(w, "Mw"), - ast::UintTy::U32 => write!(w, "Ml"), - ast::UintTy::U64 => write!(w, "Md") - }; - } - ty::TyFloat(t) => { - match t { - ast::FloatTy::F32 => write!(w, "Mf"), - ast::FloatTy::F64 => write!(w, "MF"), - }; - } - ty::TyTrait(ref obj) => { - write!(w, "x["); - enc_existential_trait_ref(w, cx, obj.principal.0); - enc_builtin_bounds(w, cx, &obj.builtin_bounds); - - enc_region(w, cx, obj.region_bound); - - for tp in &obj.projection_bounds { - write!(w, "P"); - enc_existential_projection(w, cx, &tp.0); - } - - write!(w, "."); - write!(w, "]"); - } - ty::TyTuple(ts) => { - write!(w, "T["); - for t in ts { enc_ty(w, cx, *t); } - write!(w, "]"); - } - ty::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); } - ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); } - ty::TyRef(r, mt) => { - write!(w, "&"); - enc_region(w, cx, r); - enc_mt(w, cx, mt); - } - ty::TyArray(t, sz) => { - write!(w, "V"); - enc_ty(w, cx, t); - write!(w, "/{}|", sz); - } - ty::TySlice(t) => { - write!(w, "V"); - enc_ty(w, cx, t); - write!(w, "/|"); - } - ty::TyStr => { - write!(w, "v"); - } - ty::TyFnDef(def_id, substs, f) => { - write!(w, "F"); - write!(w, "{}|", (cx.ds)(cx.tcx, def_id)); - enc_substs(w, cx, substs); - enc_bare_fn_ty(w, cx, f); - } - ty::TyFnPtr(f) => { - write!(w, "G"); - enc_bare_fn_ty(w, cx, f); - } - ty::TyInfer(_) => { - bug!("cannot encode inference variable types"); - } - ty::TyParam(p) => { - write!(w, "p[{}|{}]", p.idx, p.name); - } - ty::TyAdt(def, substs) => { - write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did)); - enc_substs(w, cx, substs); - write!(w, "]"); - } - ty::TyClosure(def, substs) => { - write!(w, "k[{}|", (cx.ds)(cx.tcx, def)); - enc_substs(w, cx, substs.func_substs); - for ty in substs.upvar_tys { - enc_ty(w, cx, ty); - } - write!(w, "."); - write!(w, "]"); - } - ty::TyProjection(ref data) => { - write!(w, "P["); - enc_trait_ref(w, cx, data.trait_ref); - write!(w, "{}]", data.item_name); - } - ty::TyAnon(def_id, substs) => { - write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id)); - enc_substs(w, cx, substs); - write!(w, "]"); - } - ty::TyError => { - write!(w, "e"); - } - } - - let end = w.position(); - let len = end - pos; - - let mut abbrev = Cursor::new(Vec::with_capacity(16)); - abbrev.write_all(b"#"); - { - let start_position = abbrev.position() as usize; - let meta_start = 8 + ::common::metadata_encoding_version.len() as u64; - let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(), - start_position, - pos - meta_start); - abbrev.set_position((start_position + bytes_written) as u64); - } - - cx.abbrevs.borrow_mut().insert(t, ty_abbrev { - s: if abbrev.position() < len { - abbrev.get_ref()[..abbrev.position() as usize].to_owned() - } else { - // if the abbreviation is longer than the real type, - // don't use #-notation. However, insert it here so - // other won't have to `mark_stable_position` - w.get_ref()[pos as usize .. end as usize].to_owned() - } - }); -} - -fn enc_mutability(w: &mut Cursor>, mt: hir::Mutability) { - match mt { - hir::MutImmutable => (), - hir::MutMutable => { - write!(w, "m"); - } - }; -} - -fn enc_mt<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - mt: ty::TypeAndMut<'tcx>) { - enc_mutability(w, mt.mutbl); - enc_ty(w, cx, mt.ty); -} - -fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &Substs<'tcx>) { - write!(w, "["); - for &k in substs.params() { - if let Some(ty) = k.as_type() { - write!(w, "t"); - enc_ty(w, cx, ty); - } else if let Some(r) = k.as_region() { - write!(w, "r"); - enc_region(w, cx, r); - } else { - bug!() - } - } - write!(w, "]"); -} - -fn enc_region(w: &mut Cursor>, cx: &ctxt, r: &ty::Region) { - match *r { - ty::ReLateBound(id, br) => { - write!(w, "b[{}|", id.depth); - enc_bound_region(w, cx, br); - write!(w, "]"); - } - ty::ReEarlyBound(ref data) => { - write!(w, "B[{}|{}]", - data.index, - data.name); - } - ty::ReFree(ref fr) => { - write!(w, "f["); - enc_scope(w, cx, fr.scope); - write!(w, "|"); - enc_bound_region(w, cx, fr.bound_region); - write!(w, "]"); - } - ty::ReScope(scope) => { - write!(w, "s"); - enc_scope(w, cx, scope); - write!(w, "|"); - } - ty::ReStatic => { - write!(w, "t"); - } - ty::ReEmpty => { - write!(w, "e"); - } - ty::ReErased => { - write!(w, "E"); - } - ty::ReVar(_) | ty::ReSkolemized(..) => { - // these should not crop up after typeck - bug!("cannot encode region variables"); - } - } -} - -fn enc_scope(w: &mut Cursor>, cx: &ctxt, scope: region::CodeExtent) { - match cx.tcx.region_maps.code_extent_data(scope) { - region::CodeExtentData::CallSiteScope { - fn_id, body_id } => write!(w, "C[{}|{}]", fn_id, body_id), - region::CodeExtentData::ParameterScope { - fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id), - region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id), - region::CodeExtentData::Remainder(region::BlockRemainder { - block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i), - region::CodeExtentData::DestructionScope(node_id) => write!(w, "D{}", node_id), - }; -} - -fn enc_bound_region(w: &mut Cursor>, cx: &ctxt, br: ty::BoundRegion) { - match br { - ty::BrAnon(idx) => { - write!(w, "a{}|", idx); - } - ty::BrNamed(d, name, issue32330) => { - write!(w, "[{}|{}|", - (cx.ds)(cx.tcx, d), - name); - - match issue32330 { - ty::Issue32330::WontChange => - write!(w, "n]"), - ty::Issue32330::WillChange { fn_def_id, region_name } => - write!(w, "y{}|{}]", (cx.ds)(cx.tcx, fn_def_id), region_name), - }; - } - ty::BrFresh(id) => { - write!(w, "f{}|", id); - } - ty::BrEnv => { - write!(w, "e|"); - } - } -} - -fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - s: ty::TraitRef<'tcx>) { - write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); - enc_substs(w, cx, s.substs); -} - -fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - s: ty::ExistentialTraitRef<'tcx>) { - write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); - enc_substs(w, cx, s.substs); -} - -fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { - match p { - hir::Unsafety::Normal => write!(w, "n"), - hir::Unsafety::Unsafe => write!(w, "u"), - }; -} - -fn enc_abi(w: &mut Cursor>, abi: Abi) { - write!(w, "["); - write!(w, "{}", abi.name()); - write!(w, "]"); -} - -fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - ft: &ty::BareFnTy<'tcx>) { - enc_unsafety(w, ft.unsafety); - enc_abi(w, ft.abi); - enc_fn_sig(w, cx, &ft.sig); -} - -fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - fsig: &ty::PolyFnSig<'tcx>) { - write!(w, "["); - for ty in &fsig.0.inputs { - enc_ty(w, cx, *ty); - } - write!(w, "]"); - if fsig.0.variadic { - write!(w, "V"); - } else { - write!(w, "N"); - } - enc_ty(w, cx, fsig.0.output); -} - -fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { - for bound in bs { - match bound { - ty::BoundSend => write!(w, "S"), - ty::BoundSized => write!(w, "Z"), - ty::BoundCopy => write!(w, "P"), - ty::BoundSync => write!(w, "T"), - }; - } - - write!(w, "."); -} - -fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - data: &ty::ExistentialProjection<'tcx>) { - enc_existential_trait_ref(w, cx, data.trait_ref); - write!(w, "{}|", data.item_name); - enc_ty(w, cx, data.ty); -} diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 7b5092e8848..ba9bf2b86a6 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -134,7 +134,7 @@ impl< fn encode(&self, s: &mut S) -> Result<(), S::Error> { let mut bits = 0; for item in self { - bits |= item.to_usize(); + bits |= 1 << item.to_usize(); } s.emit_usize(bits) } @@ -148,7 +148,7 @@ impl< let mut set = EnumSet::new(); for bit in 0..(mem::size_of::()*8) { if bits & (1 << bit) != 0 { - set.insert(CLike::from_usize(1 << bit)); + set.insert(CLike::from_usize(bit)); } } Ok(set)