about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2015-07-22 20:10:18 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2015-08-06 14:17:04 +0300
commit213b6d71f502a8568208cf549050a71cc24b1338 (patch)
tree16dbf1460a1b8f4f3fa9892b6ea9590e0eaf8c98
parent764310e7bb90ec14a6c6a399e703f6b455ba52d3 (diff)
downloadrust-213b6d71f502a8568208cf549050a71cc24b1338.tar.gz
rust-213b6d71f502a8568208cf549050a71cc24b1338.zip
add variant info to ADTDef, but don't actually use it
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/metadata/decoder.rs3
-rw-r--r--src/librustc/middle/ty.rs117
-rw-r--r--src/librustc_typeck/collect.rs4
4 files changed, 112 insertions, 15 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index c38345a79fd..1a15d98d531 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -32,6 +32,7 @@
 #![feature(clone_from_slice)]
 #![feature(collections)]
 #![feature(const_fn)]
+#![feature(core)]
 #![feature(duration)]
 #![feature(duration_span)]
 #![feature(dynamic_lib)]
@@ -42,6 +43,7 @@
 #![feature(iter_cmp)]
 #![feature(iter_arith)]
 #![feature(libc)]
+#![feature(nonzero)]
 #![feature(num_bits_bytes)]
 #![feature(path_ext)]
 #![feature(quote)]
@@ -65,6 +67,7 @@
 #![allow(trivial_casts)]
 
 extern crate arena;
+extern crate core;
 extern crate flate;
 extern crate fmt_macros;
 extern crate getopts;
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 7e955ad7338..9e8c5505c89 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -394,7 +394,8 @@ pub fn get_adt_def<'tcx>(cdata: Cmd,
                          item_id: ast::NodeId,
                          tcx: &ty::ctxt<'tcx>) -> &'tcx ty::ADTDef<'tcx>
 {
-    tcx.intern_adt_def(ast::DefId { krate: cdata.cnum, node: item_id })
+    tcx.intern_adt_def(ast::DefId { krate: cdata.cnum, node: item_id },
+                       ty::ADTKind::Enum)
 }
 
 pub fn get_predicates<'tcx>(cdata: Cmd,
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9b5943e7d30..a491d6e65b7 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -74,12 +74,15 @@ use std::cell::{Cell, RefCell, Ref};
 use std::cmp;
 use std::fmt;
 use std::hash::{Hash, SipHasher, Hasher};
+use std::marker::PhantomData;
 use std::mem;
 use std::ops;
 use std::rc::Rc;
 use std::vec::IntoIter;
 use collections::enum_set::{self, EnumSet, CLike};
+use core::nonzero::NonZero;
 use std::collections::{HashMap, HashSet};
+use rustc_data_structures::ivar;
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
@@ -721,7 +724,7 @@ pub struct CtxtArenas<'tcx> {
 
     // references
     trait_defs: TypedArena<TraitDef<'tcx>>,
-    adt_defs: TypedArena<ADTDef<'tcx>>,
+    adt_defs: TypedArena<ADTDef_<'tcx, 'tcx>>,
 }
 
 impl<'tcx> CtxtArenas<'tcx> {
@@ -1020,9 +1023,10 @@ impl<'tcx> ctxt<'tcx> {
         interned
     }
 
-    pub fn intern_adt_def(&self, did: DefId) -> &'tcx ADTDef<'tcx> {
-        let def = ADTDef::new(self, did);
+    pub fn intern_adt_def(&self, did: DefId, kind: ADTKind) -> &'tcx ADTDef_<'tcx, 'tcx> {
+        let def = ADTDef_::new(self, did, kind);
         let interned = self.arenas.adt_defs.alloc(def);
+        // this will need a transmute when reverse-variance is removed
         self.adt_defs.borrow_mut().insert(did, interned);
         interned
     }
@@ -1395,6 +1399,61 @@ impl<'tcx> Hash for TyS<'tcx> {
 
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
+/// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
+/// on the lifetime of the IVar. This is required because of variance
+/// problems: the IVar needs to be variant with respect to 'tcx (so
+/// it can be referred to from Ty) but can only be modified if its
+/// lifetime is exactly 'tcx.
+///
+/// Safety invariants:
+///     (A) self.0, if fulfilled, is a valid Ty<'tcx>
+///     (B) no aliases to this value with a 'tcx longer than this
+///         value's 'lt exist
+///
+/// NonZero is used rather than Unique because Unique isn't Copy.
+pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
+                                   PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
+
+impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
+    #[inline]
+    pub fn new() -> Self {
+        // Invariant (A) satisfied because the IVar is unfulfilled
+        // Invariant (B) because 'lt : 'tcx
+        TyIVar(ivar::Ivar::new(), PhantomData)
+    }
+
+    #[inline]
+    pub fn get(&self) -> Option<Ty<'tcx>> {
+        match self.0.get() {
+            None => None,
+            // valid because of invariant (A)
+            Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
+        }
+    }
+    #[inline]
+    pub fn unwrap(&self) -> Ty<'tcx> {
+        self.get().unwrap()
+    }
+
+    pub fn fulfill(&self, value: Ty<'lt>) {
+        // Invariant (A) is fulfilled, because by (B), every alias
+        // of this has a 'tcx longer than 'lt.
+        let value: *const TyS<'lt> = value;
+        // FIXME(27214): unneeded [as *const ()]
+        let value = value as *const () as *const TyS<'static>;
+        self.0.fulfill(unsafe { NonZero::new(value) })
+    }
+}
+
+impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.get() {
+            Some(val) => write!(f, "TyIVar({:?})", val),
+            None => f.write_str("TyIVar(<unfulfilled>)")
+        }
+    }
+}
+
 /// An entry in the type interner.
 pub struct InternedTy<'tcx> {
     ty: Ty<'tcx>
@@ -3210,33 +3269,55 @@ bitflags! {
         const IS_PHANTOM_DATA     = 1 << 1,
         const IS_DTORCK           = 1 << 2, // is this a dtorck type?
         const IS_DTORCK_VALID     = 1 << 3,
+        const IS_ENUM             = 1 << 4
     }
 }
 
-/// The definition of an abstract data type - a struct or enum.
-pub struct ADTDef<'tcx> {
+pub type ADTDef<'tcx> = ADTDef_<'tcx, 'static>;
+
+pub struct VariantDef<'tcx, 'lt: 'tcx> {
+    pub did: DefId,
+    pub name: Name, // struct's name if this is a struct
+    pub disr_val: Disr,
+    pub fields: Vec<FieldDef<'tcx, 'lt>>
+}
+
+pub struct FieldDef<'tcx, 'lt: 'tcx> {
+    pub did: DefId,
+    pub name: Name, // XXX if tuple-like
+    pub vis: ast::Visibility,
+    // TyIVar is used here to allow for
+    ty: TyIVar<'tcx, 'lt>
+}
+
+/// The definition of an abstract data type - a struct or enum. 'lt
+/// is here so 'tcx can be variant.
+pub struct ADTDef_<'tcx, 'lt: 'tcx> {
     pub did: DefId,
+    pub variants: Vec<VariantDef<'tcx, 'lt>>,
     flags: Cell<ADTFlags>,
-    marker: ::std::marker::PhantomData<&'tcx ()>,
 }
 
-impl<'tcx> PartialEq for ADTDef<'tcx> {
+impl<'tcx, 'lt> PartialEq for ADTDef_<'tcx, 'lt> {
     // ADTDef are always interned and this is part of TyS equality
     #[inline]
     fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
 }
 
-impl<'tcx> Eq for ADTDef<'tcx> {}
+impl<'tcx, 'lt> Eq for ADTDef_<'tcx, 'lt> {}
 
-impl<'tcx> Hash for ADTDef<'tcx> {
+impl<'tcx, 'lt> Hash for ADTDef_<'tcx, 'lt> {
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
         (self as *const ADTDef).hash(s)
     }
 }
 
-impl<'tcx> ADTDef<'tcx> {
-    fn new(tcx: &ctxt<'tcx>, did: DefId) -> Self {
+#[derive(Copy, Clone, Debug)]
+pub enum ADTKind { Struct, Enum }
+
+impl<'tcx, 'lt> ADTDef_<'tcx, 'lt> {
+    fn new(tcx: &ctxt<'tcx>, did: DefId, kind: ADTKind) -> Self {
         let mut flags = ADTFlags::NO_ADT_FLAGS;
         if tcx.has_attr(did, "fundamental") {
             flags = flags | ADTFlags::IS_FUNDAMENTAL;
@@ -3244,10 +3325,13 @@ impl<'tcx> ADTDef<'tcx> {
         if Some(did) == tcx.lang_items.phantom_data() {
             flags = flags | ADTFlags::IS_PHANTOM_DATA;
         }
+        if let ADTKind::Enum = kind {
+            flags = flags | ADTFlags::IS_ENUM;
+        }
         ADTDef {
             did: did,
+            variants: vec![],
             flags: Cell::new(flags),
-            marker: ::std::marker::PhantomData
         }
     }
 
@@ -3259,6 +3343,15 @@ impl<'tcx> ADTDef<'tcx> {
     }
 
     #[inline]
+    pub fn adt_kind(&self) -> ADTKind {
+        if self.flags.get().intersects(ADTFlags::IS_ENUM) {
+            ADTKind::Enum
+        } else {
+            ADTKind::Struct
+        }
+    }
+
+    #[inline]
     pub fn is_dtorck(&'tcx self, tcx: &ctxt<'tcx>) -> bool {
         if !self.flags.get().intersects(ADTFlags::IS_DTORCK_VALID) {
             self.calculate_dtorck(tcx)
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 0fed9343536..708825fc95a 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1473,14 +1473,14 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             // Create a new generic polytype.
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let def = tcx.intern_adt_def(local_def(it.id));
+            let def = tcx.intern_adt_def(local_def(it.id), ty::ADTKind::Enum);
             let t = tcx.mk_enum(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
         ast::ItemStruct(_, ref generics) => {
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let def = tcx.intern_adt_def(local_def(it.id));
+            let def = tcx.intern_adt_def(local_def(it.id), ty::ADTKind::Struct);
             let t = tcx.mk_struct(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }