From 213b6d71f502a8568208cf549050a71cc24b1338 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 22 Jul 2015 20:10:18 +0300 Subject: [PATCH] add variant info to ADTDef, but don't actually use it --- src/librustc/lib.rs | 3 + src/librustc/metadata/decoder.rs | 3 +- src/librustc/middle/ty.rs | 117 +++++++++++++++++++++++++++---- src/librustc_typeck/collect.rs | 4 +- 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::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>, - adt_defs: TypedArena>, + adt_defs: TypedArena>, } impl<'tcx> CtxtArenas<'tcx> { @@ -1020,9 +1023,10 @@ pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'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 @@ fn hash(&self, s: &mut H) { 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>>, + PhantomData)->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> { + 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()") + } + } +} + /// An entry in the type interner. pub struct InternedTy<'tcx> { ty: Ty<'tcx> @@ -3210,33 +3269,55 @@ pub fn for_each_relevant_impl(&self, 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> +} + +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>, flags: Cell, - 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(&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 @@ fn new(tcx: &ctxt<'tcx>, did: DefId) -> Self { 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 } } @@ -3258,6 +3342,15 @@ fn calculate_dtorck(&'tcx self, tcx: &ctxt<'tcx>) { self.flags.set(self.flags.get() | ADTFlags::IS_DTORCK_VALID) } + #[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) { 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 } } -- GitLab