提交 4816e606 编写于 作者: A Ariel Ben-Yehuda 提交者: Ariel Ben-Yehuda

create VariantDef-s (but don't actually use them)

上级 213b6d71
......@@ -222,10 +222,10 @@ pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::TraitDe
decoder::get_trait_def(&*cdata, def.node, tcx)
}
pub fn get_adt_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> &'tcx ty::ADTDef<'tcx> {
pub fn get_adt_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> &'tcx ty::ADTDef_<'tcx, 'tcx> {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_adt_def(&*cdata, def.node, tcx)
decoder::get_adt_def(&cstore.intr, &*cdata, def.node, tcx)
}
pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
......
......@@ -108,7 +108,7 @@ fn lookup_item<'a>(item_id: ast::NodeId, data: &'a [u8]) -> rbml::Doc<'a> {
find_item(item_id, items)
}
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
enum Family {
ImmStatic, // c
MutStatic, // b
......@@ -390,12 +390,111 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
}
}
pub fn get_adt_def<'tcx>(cdata: Cmd,
pub fn get_adt_def<'tcx>(intr: &IdentInterner,
cdata: Cmd,
item_id: ast::NodeId,
tcx: &ty::ctxt<'tcx>) -> &'tcx ty::ADTDef<'tcx>
tcx: &ty::ctxt<'tcx>) -> &'tcx ty::ADTDef_<'tcx, 'tcx>
{
tcx.intern_adt_def(ast::DefId { krate: cdata.cnum, node: item_id },
ty::ADTKind::Enum)
fn get_enum_variants<'tcx>(intr: &IdentInterner,
cdata: Cmd,
doc: rbml::Doc,
tcx: &ty::ctxt<'tcx>) -> Vec<ty::VariantDef_<'tcx, 'tcx>> {
let mut disr_val = 0;
reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
let did = translated_def_id(cdata, p);
let item = lookup_item(did.node, cdata.data());
if let Some(disr) = variant_disr_val(item) {
disr_val = disr;
}
let disr = disr_val;
disr_val = disr_val.wrapping_add(1);
ty::VariantDef_ {
did: did,
name: item_name(intr, item),
fields: get_variant_fields(intr, cdata, item, tcx),
disr_val: disr
}
}).collect()
}
fn get_variant_fields<'tcx>(intr: &IdentInterner,
cdata: Cmd,
doc: rbml::Doc,
tcx: &ty::ctxt<'tcx>) -> Vec<ty::FieldDef_<'tcx, 'tcx>> {
reader::tagged_docs(doc, tag_item_field).map(|f| {
let ff = item_family(f);
match ff {
PublicField | InheritedField => {},
_ => tcx.sess.bug(&format!("expected field, found {:?}", ff))
};
ty::FieldDef_::new(item_def_id(f, cdata),
item_name(intr, f),
struct_field_family_to_visibility(ff))
}).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| {
let ff = item_family(f);
ty::FieldDef_::new(item_def_id(f, cdata),
special_idents::unnamed_field.name,
struct_field_family_to_visibility(ff))
})).collect()
}
fn get_struct_variant<'tcx>(intr: &IdentInterner,
cdata: Cmd,
doc: rbml::Doc,
did: ast::DefId,
tcx: &ty::ctxt<'tcx>) -> ty::VariantDef_<'tcx, 'tcx> {
ty::VariantDef_ {
did: did,
name: item_name(intr, doc),
fields: get_variant_fields(intr, cdata, doc, tcx),
disr_val: 0
}
}
let doc = lookup_item(item_id, cdata.data());
let did = ast::DefId { krate: cdata.cnum, node: item_id };
let (kind, variants) = match item_family(doc) {
Enum => (ty::ADTKind::Enum,
get_enum_variants(intr, cdata, doc, tcx)),
Struct => (ty::ADTKind::Struct,
vec![get_struct_variant(intr, cdata, doc, did, tcx)]),
_ => tcx.sess.bug("get_adt_def called on a non-ADT")
};
let adt = tcx.intern_adt_def(did, kind, variants);
// this needs to be done *after* the variant is interned,
// to support recursive structures
for variant in &adt.variants {
if variant.kind() == ty::VariantKind::Tuple &&
adt.adt_kind() == ty::ADTKind::Enum {
// tuple-like enum variant fields aren't real items - get the types
// from the ctor.
debug!("evaluating the ctor-type of {:?}",
variant.name);
let ctor_ty = get_type(cdata, variant.did.node, tcx).ty;
debug!("evaluating the ctor-type of {:?}.. {:?}",
variant.name,
ctor_ty);
let field_tys = match ctor_ty.sty {
ty::TyBareFn(_, ref f) => &f.sig.skip_binder().inputs,
_ => tcx.sess.bug("tuple-variant ctor is not an ADT")
};
for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) {
field.fulfill_ty(ty);
}
} else {
for field in &variant.fields {
debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
let ty = get_type(cdata, field.did.node, tcx).ty;
field.fulfill_ty(ty);
debug!("evaluating the type of {:?}::{:?}: {:?}",
variant.name, field.name, ty);
}
}
}
adt
}
pub fn get_predicates<'tcx>(cdata: Cmd,
......
......@@ -41,7 +41,6 @@
use syntax::diagnostic::SpanHandler;
use syntax::parse::token::special_idents;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::visit::Visitor;
use syntax::visit;
use syntax;
......@@ -266,7 +265,7 @@ fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
}
fn encode_struct_fields(rbml_w: &mut Encoder,
fields: &[ty::FieldTy],
fields: &[ty::FieldDef],
origin: DefId) {
for f in fields {
if f.name == special_idents::unnamed_field.name {
......@@ -276,7 +275,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
encode_name(rbml_w, f.name);
}
encode_struct_field_family(rbml_w, f.vis);
encode_def_id(rbml_w, f.id);
encode_def_id(rbml_w, f.did);
rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
rbml_w.end_tag();
}
......@@ -285,57 +284,56 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
fn encode_enum_variant_info(ecx: &EncodeContext,
rbml_w: &mut Encoder,
id: NodeId,
variants: &[P<ast::Variant>],
vis: ast::Visibility,
index: &mut Vec<entry<i64>>) {
debug!("encode_enum_variant_info(id={})", id);
let mut disr_val = 0;
let mut i = 0;
let vi = ecx.tcx.enum_variants(local_def(id));
for variant in variants {
let def_id = local_def(variant.node.id);
let def = ecx.tcx.lookup_adt_def(local_def(id));
for variant in &def.variants {
let vid = variant.did;
assert!(is_local(vid));
index.push(entry {
val: variant.node.id as i64,
val: vid.node as i64,
pos: rbml_w.mark_stable_position(),
});
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
match variant.node.kind {
ast::TupleVariantKind(_) => encode_family(rbml_w, 'v'),
ast::StructVariantKind(_) => encode_family(rbml_w, 'V')
}
encode_name(rbml_w, variant.node.name.name);
encode_def_id(rbml_w, vid);
encode_family(rbml_w, match variant.kind() {
ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
ty::VariantKind::Dict => 'V'
});
encode_name(rbml_w, variant.name);
encode_parent_item(rbml_w, local_def(id));
encode_visibility(rbml_w, variant.node.vis);
encode_attributes(rbml_w, &variant.node.attrs);
encode_repr_attrs(rbml_w, ecx, &variant.node.attrs);
encode_visibility(rbml_w, vis);
let attrs = ecx.tcx.get_attrs(vid);
encode_attributes(rbml_w, &attrs);
encode_repr_attrs(rbml_w, ecx, &attrs);
let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
let stab = stability::lookup(ecx.tcx, vid);
encode_stability(rbml_w, stab);
match variant.node.kind {
ast::TupleVariantKind(_) => {},
ast::StructVariantKind(_) => {
let fields = ecx.tcx.lookup_struct_fields(def_id);
let idx = encode_info_for_struct(ecx,
rbml_w,
&fields[..],
index);
encode_struct_fields(rbml_w, &fields[..], def_id);
encode_index(rbml_w, idx, write_i64);
}
if let ty::VariantKind::Dict = variant.kind() {
let idx = encode_info_for_struct(ecx,
rbml_w,
&variant.fields,
index);
encode_index(rbml_w, idx, write_i64);
}
let specified_disr_val = vi[i].disr_val;
encode_struct_fields(rbml_w, &variant.fields, vid);
let specified_disr_val = variant.disr_val;
if specified_disr_val != disr_val {
encode_disr_val(ecx, rbml_w, specified_disr_val);
disr_val = specified_disr_val;
}
encode_bounds_and_type_for_item(rbml_w, ecx, def_id.local_id());
encode_bounds_and_type_for_item(rbml_w, ecx, vid.node);
ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
ecx.tcx.map.with_path(vid.node, |path| encode_path(rbml_w, path));
rbml_w.end_tag();
disr_val = disr_val.wrapping_add(1);
i += 1;
}
}
......@@ -630,11 +628,11 @@ fn encode_provided_source(rbml_w: &mut Encoder,
}
/* Returns an index of items in this class */
fn encode_info_for_struct(ecx: &EncodeContext,
rbml_w: &mut Encoder,
fields: &[ty::FieldTy],
global_index: &mut Vec<entry<i64>>)
-> Vec<entry<i64>> {
fn encode_info_for_struct<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
rbml_w: &mut Encoder,
fields: &[ty::FieldDef<'tcx>],
global_index: &mut Vec<entry<i64>>)
-> Vec<entry<i64>> {
/* Each class has its own index, since different classes
may have fields with the same name */
let mut index = Vec::new();
......@@ -642,7 +640,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
private fields to get the offsets right */
for field in fields {
let nm = field.name;
let id = field.id.node;
let id = field.did.node;
let pos = rbml_w.mark_stable_position();
index.push(entry {val: id as i64, pos: pos});
......@@ -658,7 +656,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
encode_bounds_and_type_for_item(rbml_w, ecx, id);
encode_def_id(rbml_w, local_def(id));
let stab = stability::lookup(ecx.tcx, field.id);
let stab = stability::lookup(ecx.tcx, field.did);
encode_stability(rbml_w, stab);
rbml_w.end_tag();
......@@ -1150,20 +1148,18 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
encode_enum_variant_info(ecx,
rbml_w,
item.id,
&(*enum_definition).variants,
vis,
index);
}
ast::ItemStruct(ref struct_def, _) => {
let fields = tcx.lookup_struct_fields(def_id);
let def = ecx.tcx.lookup_adt_def(def_id);
let fields = &def.struct_variant().fields;
/* First, encode the fields
These come first because we need to write them to make
the index, and the index needs to be in the item for the
class itself */
let idx = encode_info_for_struct(ecx,
rbml_w,
&fields[..],
index);
let idx = encode_info_for_struct(ecx, rbml_w, &fields, index);
/* Index the class*/
add_to_index(item, rbml_w, index);
......@@ -1185,7 +1181,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
/* Encode def_ids for each field and method
for methods, write all the stuff get_trait_method
needs to know*/
encode_struct_fields(rbml_w, &fields[..], def_id);
encode_struct_fields(rbml_w, &fields, def_id);
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
......
......@@ -513,7 +513,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
&Variant(vid) =>
(vid, cx.tcx.enum_variant_with_id(cid.did, vid).arg_names.is_some()),
_ =>
(cid.did, !cid.is_tuple_struct(cx.tcx))
(cid.did, !cid.struct_variant().is_tuple_struct())
};
if is_structure {
let fields = cx.tcx.lookup_struct_fields(vid);
......
......@@ -74,10 +74,12 @@
use std::cmp;
use std::fmt;
use std::hash::{Hash, SipHasher, Hasher};
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops;
use std::rc::Rc;
use std::slice;
use std::vec::IntoIter;
use collections::enum_set::{self, EnumSet, CLike};
use core::nonzero::NonZero;
......@@ -90,7 +92,7 @@
use syntax::ast_util::{self, is_local, local_def};
use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
use syntax::codemap::Span;
use syntax::parse::token::{self, InternedString, special_idents};
use syntax::parse::token::{InternedString, special_idents};
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::ast;
......@@ -211,7 +213,7 @@ pub fn has_drop_flag(&self) -> bool {
}
}
trait IntTypeExt {
pub trait IntTypeExt {
fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
fn i64_to_disr(&self, val: i64) -> Option<Disr>;
fn u64_to_disr(&self, val: u64) -> Option<Disr>;
......@@ -852,7 +854,7 @@ pub struct ctxt<'tcx> {
pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>,
pub adt_defs: RefCell<DefIdMap<&'tcx ADTDef<'tcx>>>,
pub adt_defs: RefCell<DefIdMap<&'tcx ADTDef_<'tcx, 'tcx>>>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
/// associated predicates.
......@@ -1023,8 +1025,12 @@ pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> {
interned
}
pub fn intern_adt_def(&self, did: DefId, kind: ADTKind) -> &'tcx ADTDef_<'tcx, 'tcx> {
let def = ADTDef_::new(self, did, kind);
pub fn intern_adt_def(&self,
did: DefId,
kind: ADTKind,
variants: Vec<VariantDef_<'tcx, 'tcx>>)
-> &'tcx ADTDef_<'tcx, 'tcx> {
let def = ADTDef_::new(self, did, kind, variants);
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);
......@@ -2190,7 +2196,7 @@ pub struct ExistentialBounds<'tcx> {
pub struct BuiltinBounds(EnumSet<BuiltinBound>);
impl BuiltinBounds {
pub fn empty() -> BuiltinBounds {
pub fn empty() -> BuiltinBounds {
BuiltinBounds(EnumSet::new())
}
......@@ -3274,17 +3280,21 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
}
pub type ADTDef<'tcx> = ADTDef_<'tcx, 'static>;
pub type VariantDef<'tcx> = VariantDef_<'tcx, 'static>;
pub type FieldDef<'tcx> = FieldDef_<'tcx, 'static>;
pub struct VariantDef<'tcx, 'lt: 'tcx> {
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 fields: Vec<FieldDef_<'tcx, 'lt>>
}
pub struct FieldDef<'tcx, 'lt: 'tcx> {
pub struct FieldDef_<'tcx, 'lt: 'tcx> {
pub did: DefId,
pub name: Name, // XXX if tuple-like
// special_idents::unnamed_field.name
// if this is a tuple-like field
pub name: Name,
pub vis: ast::Visibility,
// TyIVar is used here to allow for
ty: TyIVar<'tcx, 'lt>
......@@ -3294,7 +3304,7 @@ pub struct FieldDef<'tcx, 'lt: 'tcx> {
/// is here so 'tcx can be variant.
pub struct ADTDef_<'tcx, 'lt: 'tcx> {
pub did: DefId,
pub variants: Vec<VariantDef<'tcx, 'lt>>,
pub variants: Vec<VariantDef_<'tcx, 'lt>>,
flags: Cell<ADTFlags>,
}
......@@ -3313,11 +3323,18 @@ fn hash<H: Hasher>(&self, s: &mut H) {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ADTKind { Struct, Enum }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum VariantKind { Dict, Tuple, Unit }
impl<'tcx, 'lt> ADTDef_<'tcx, 'lt> {
fn new(tcx: &ctxt<'tcx>, did: DefId, kind: ADTKind) -> Self {
fn new(tcx: &ctxt<'tcx>,
did: DefId,
kind: ADTKind,
variants: Vec<VariantDef_<'tcx, 'lt>>) -> Self {
let mut flags = ADTFlags::NO_ADT_FLAGS;
if tcx.has_attr(did, "fundamental") {
flags = flags | ADTFlags::IS_FUNDAMENTAL;
......@@ -3330,7 +3347,7 @@ fn new(tcx: &ctxt<'tcx>, did: DefId, kind: ADTKind) -> Self {
}
ADTDef {
did: did,
variants: vec![],
variants: variants,
flags: Cell::new(flags),
}
}
......@@ -3374,9 +3391,9 @@ pub fn has_dtor(&self, tcx: &ctxt<'tcx>) -> bool {
tcx.destructor_for_type.borrow().contains_key(&self.did)
}
pub fn is_tuple_struct(&self, tcx: &ctxt<'tcx>) -> bool {
let fields = tcx.lookup_struct_fields(self.did);
!fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
pub fn struct_variant(&self) -> &ty::VariantDef_<'tcx, 'lt> {
assert!(self.adt_kind() == ADTKind::Struct);
&self.variants[0]
}
#[inline]
......@@ -3388,6 +3405,104 @@ pub fn type_scheme(&self, tcx: &ctxt<'tcx>) -> TypeScheme<'tcx> {
pub fn predicates(&self, tcx: &ctxt<'tcx>) -> GenericPredicates<'tcx> {
tcx.lookup_predicates(self.did)
}
#[inline]
pub fn all_fields(&self) ->
iter::FlatMap<
slice::Iter<VariantDef_<'tcx, 'lt>>,
slice::Iter<FieldDef_<'tcx, 'lt>>,
for<'s> fn(&'s VariantDef_<'tcx, 'lt>)
-> slice::Iter<'s, FieldDef_<'tcx, 'lt>>
> {
self.variants.iter().flat_map(VariantDef_::fields_iter)
}
#[inline]
pub fn is_empty(&self) -> bool {
// FIXME(#TODO(wxyz)): be smarter here
self.variants.is_empty()
}
#[inline]
pub fn is_univariant(&self) -> bool {
self.variants.len() == 1
}
pub fn is_payloadfree(&self) -> bool {
!self.variants.is_empty() &&
self.variants.iter().all(|v| v.fields.is_empty())
}
pub fn variant_with_id(&self, vid: DefId) -> &VariantDef_<'tcx, 'lt> {
self.variants
.iter()
.find(|v| v.did == vid)
.expect("variant_with_id: unknown variant")
}
pub fn variant_of_def(&self, def: def::Def) -> &VariantDef_<'tcx, 'lt> {
match def {
def::DefVariant(_, vid, _) => self.variant_with_id(vid),
def::DefStruct(..) | def::DefTy(..) => self.struct_variant(),
_ => panic!("unexpected def {:?} in variant_of_def", def)
}
}
}
impl<'tcx, 'lt> VariantDef_<'tcx, 'lt> {
#[inline]
fn fields_iter(&self) -> slice::Iter<FieldDef_<'tcx, 'lt>> {
self.fields.iter()
}
pub fn kind(&self) -> VariantKind {
match self.fields.get(0) {
None => VariantKind::Unit,
Some(&FieldDef_ { name, .. }) if name == special_idents::unnamed_field.name => {
VariantKind::Tuple
}
Some(_) => VariantKind::Dict
}
}
pub fn is_tuple_struct(&self) -> bool {
self.kind() == VariantKind::Tuple
}
#[inline]
pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef_<'tcx, 'lt>> {
self.fields.iter().find(|f| f.name == name)
}
#[inline]
pub fn field_named(&self, name: ast::Name) -> &FieldDef_<'tcx, 'lt> {
self.find_field_named(name).unwrap()
}
}
impl<'tcx, 'lt> FieldDef_<'tcx, 'lt> {
pub fn new(did: DefId,
name: Name,
vis: ast::Visibility) -> Self {
FieldDef_ {
did: did,
name: name,
vis: vis,
ty: TyIVar::new()
}
}
pub fn ty(&self, tcx: &ctxt<'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
self.unsubst_ty().subst(tcx, subst)
}
pub fn unsubst_ty(&self) -> Ty<'tcx> {
self.ty.unwrap()
}
pub fn fulfill_ty(&self, ty: Ty<'lt>) {
self.ty.fulfill(ty);
}
}
/// Records the substitutions used to translate the polytype for an
......@@ -6132,7 +6247,7 @@ pub fn lookup_trait_def(&self, did: ast::DefId) -> &'tcx TraitDef<'tcx> {
}
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_adt_def(&self, did: ast::DefId) -> &'tcx ADTDef<'tcx> {
pub fn lookup_adt_def(&self, did: ast::DefId) -> &'tcx ADTDef_<'tcx, 'tcx> {
lookup_locally_or_in_crate_store(
"adt_defs", did, &self.adt_defs,
|| csearch::get_adt_def(self, did)
......
......@@ -2980,7 +2980,7 @@ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|base_t, _| {
match base_t.sty {
ty::TyStruct(base_def, substs) => {
tuple_like = base_def.is_tuple_struct(tcx);
tuple_like = base_def.struct_variant().is_tuple_struct();
if tuple_like {
debug!("tuple struct named {:?}", base_t);
let fields = tcx.lookup_struct_fields(base_def.did);
......
......@@ -71,9 +71,12 @@
use middle::free_region::FreeRegionMap;
use middle::region;
use middle::resolve_lifetime;
use middle::const_eval::{self, ConstVal};
use middle::const_eval::EvalHint::UncheckedExprHint;
use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme, IntTypeExt};
use middle::ty::{VariantKind};
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
use middle::infer;
use rscope::*;
......@@ -89,8 +92,10 @@
use syntax::abi;
use syntax::ast;
use syntax::ast_util::local_def;
use syntax::attr;
use syntax::codemap::Span;
use syntax::parse::token::special_idents;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::visit;
......@@ -563,48 +568,6 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}
fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
enum_scheme: ty::TypeScheme<'tcx>,
enum_predicates: ty::GenericPredicates<'tcx>,
variants: &[P<ast::Variant>]) {
let tcx = ccx.tcx;
let icx = ccx.icx(&enum_predicates);
// Create a set of parameter types shared among all the variants.
for variant in variants {
let variant_def_id = local_def(variant.node.id);
// Nullary enum constructors get turned into constants; n-ary enum
// constructors get turned into functions.
let result_ty = match variant.node.kind {
ast::TupleVariantKind(ref args) if !args.is_empty() => {
let rs = ExplicitRscope;
let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
tcx.mk_ctor_fn(variant_def_id, &input_tys, enum_scheme.ty)
}
ast::TupleVariantKind(_) => {
enum_scheme.ty
}
ast::StructVariantKind(ref struct_def) => {
convert_struct(ccx, &**struct_def, enum_scheme.clone(),
enum_predicates.clone(), variant.node.id);
enum_scheme.ty
}
};
let variant_scheme = TypeScheme {
generics: enum_scheme.generics.clone(),
ty: result_ty
};
tcx.register_item_type(variant_def_id, variant_scheme.clone());
tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
write_ty_to_tcx(tcx, variant.node.id, result_ty);
}
}
fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
container: ImplOrTraitItemContainer,
sig: &ast::MethodSig,
......@@ -657,10 +620,12 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
struct_generics: &ty::Generics<'tcx>,
struct_predicates: &ty::GenericPredicates<'tcx>,
v: &ast::StructField,
ty_f: &'tcx ty::FieldDef_<'tcx, 'tcx>,
origin: ast::DefId)
-> ty::FieldTy
{
let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
ty_f.fulfill_ty(tt);
write_ty_to_tcx(ccx.tcx, v.node.id, tt);
/* add the field to the tcache */
......@@ -803,10 +768,11 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
ast::ItemEnum(ref enum_definition, _) => {
let (scheme, predicates) = convert_typed_item(ccx, it);
write_ty_to_tcx(tcx, it.id, scheme.ty);
get_enum_variant_types(ccx,
scheme,
predicates,
&enum_definition.variants);
convert_enum_variant_types(ccx,
tcx.lookup_adt_def(local_def(it.id)),
scheme,
predicates,
&enum_definition.variants);
},
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
let trait_ref =
......@@ -1048,10 +1014,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
}
},
ast::ItemStruct(ref struct_def, _) => {
// Write the class type.
let (scheme, predicates) = convert_typed_item(ccx, it);
write_ty_to_tcx(tcx, it.id, scheme.ty);
convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
let variant = tcx.lookup_adt_def(local_def(it.id)).struct_variant();
convert_struct_variant_types(ccx, &struct_def, variant, &scheme, &predicates);
if let Some(ctor_id) = struct_def.ctor_id {
convert_variant_ctor(tcx, ctor_id, variant, scheme, predicates);
}
},
ast::ItemTy(_, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
......@@ -1068,74 +1038,216 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
}
}
fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
struct_def: &ast::StructDef,
scheme: ty::TypeScheme<'tcx>,
predicates: ty::GenericPredicates<'tcx>,
id: ast::NodeId) {
fn convert_variant_ctor<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
ctor_id: ast::NodeId,
variant: &'tcx ty::VariantDef<'tcx>,
scheme: ty::TypeScheme<'tcx>,
predicates: ty::GenericPredicates<'tcx>) {
let ctor_ty = match variant.kind() {
VariantKind::Unit | VariantKind::Dict => scheme.ty,
VariantKind::Tuple => {
let inputs: Vec<_> =
variant.fields
.iter()
.map(|field| field.unsubst_ty())
.collect();
tcx.mk_ctor_fn(local_def(ctor_id),
&inputs[..],
scheme.ty)
}
};
write_ty_to_tcx(tcx, ctor_id, ctor_ty);
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
tcx.register_item_type(local_def(ctor_id),
TypeScheme {
generics: scheme.generics,
ty: ctor_ty
});
}
fn convert_struct_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def: &ast::StructDef,
variant: &'tcx ty::VariantDef_<'tcx, 'tcx>,
scheme: &ty::TypeScheme<'tcx>,
predicates: &ty::GenericPredicates<'tcx>) {
let field_tys = def.fields.iter().zip(variant.fields.iter()).map(|(f, ty_f)| {
convert_field(ccx, &scheme.generics, &predicates, f, ty_f, variant.did)
}).collect();
ccx.tcx.struct_fields.borrow_mut().insert(variant.did, Rc::new(field_tys));
}
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
def: &'tcx ty::ADTDef_<'tcx, 'tcx>,
scheme: ty::TypeScheme<'tcx>,
predicates: ty::GenericPredicates<'tcx>,
variants: &[P<ast::Variant>]) {
let tcx = ccx.tcx;
let icx = ccx.icx(&predicates);
// Write the type of each of the members and check for duplicate fields.
let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
let field_tys = struct_def.fields.iter().map(|f| {
let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
// Create a set of parameter types shared among all the variants.
for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
match variant.node.kind {
ast::TupleVariantKind(ref args) => {
let rs = ExplicitRscope;
let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
for (field, &ty) in ty_variant.fields.iter().zip(input_tys.iter()) {
field.fulfill_ty(ty);
}
}
ast::StructVariantKind(ref struct_def) => {
convert_struct_variant_types(ccx, &struct_def, ty_variant, &scheme, &predicates);
}
};
if result.name != special_idents::unnamed_field.name {
let dup = match seen_fields.get(&result.name) {
Some(prev_span) => {
convert_variant_ctor(
tcx,
variant.node.id,
ty_variant,
scheme.clone(),
predicates.clone()
);
}
}
fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
did: ast::DefId,
name: ast::Name,
disr_val: ty::Disr,
def: &ast::StructDef) -> ty::VariantDef_<'tcx, 'tcx> {
let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
let fields = def.fields.iter().map(|f| {
let fid = local_def(f.node.id);
match f.node.kind {
ast::NamedField(ident, vis) => {
let dup_span = seen_fields.get(&ident.name).cloned();
if let Some(prev_span) = dup_span {
span_err!(tcx.sess, f.span, E0124,
"field `{}` is already declared",
result.name);
span_note!(tcx.sess, *prev_span, "previously declared here");
true
},
None => false,
};
// FIXME(#6393) this whole dup thing is just to satisfy
// the borrow checker :-(
if !dup {
seen_fields.insert(result.name, f.span);
ident.name);
span_note!(tcx.sess, prev_span, "previously declared here");
} else {
seen_fields.insert(ident.name, f.span);
}
ty::FieldDef_::new(fid, ident.name, vis)
},
ast::UnnamedField(vis) => {
ty::FieldDef_::new(fid, special_idents::unnamed_field.name, vis)
}
}
result
}).collect();
ty::VariantDef_ {
did: did,
name: name,
disr_val: disr_val,
fields: fields
}
}
tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
it: &ast::Item,
def: &ast::StructDef)
-> &'tcx ty::ADTDef_<'tcx, 'tcx>
{
let did = local_def(it.id);
tcx.intern_adt_def(
did,
ty::ADTKind::Struct,
vec![convert_struct_variant(tcx, did, it.ident.name, 0, def)]
)
}
// If this struct is enum-like or tuple-like, create the type of its
// constructor.
if let Some(ctor_id) = struct_def.ctor_id {
let substs = mk_item_substs(ccx, &scheme.generics);
let selfty = tcx.mk_struct(tcx.lookup_adt_def(local_def(id)),
tcx.mk_substs(substs));
if struct_def.fields.is_empty() {
// Enum-like.
write_ty_to_tcx(tcx, ctor_id, selfty);
fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
it: &ast::Item,
def: &ast::EnumDef)
-> &'tcx ty::ADTDef_<'tcx, 'tcx>
{
fn evaluate_disr_expr<'tcx>(tcx: &ty::ctxt<'tcx>,
repr_ty: Ty<'tcx>,
e: &ast::Expr) -> Option<ty::Disr> {
debug!("disr expr, checking {}", pprust::expr_to_string(e));
let hint = UncheckedExprHint(repr_ty);
match const_eval::eval_const_expr_partial(tcx, e, hint) {
Ok(ConstVal::Int(val)) => Some(val as ty::Disr),
Ok(ConstVal::Uint(val)) => Some(val as ty::Disr),
Ok(_) => {
// let sign_desc = if repr_type.is_signed() {
// "signed"
// } else {
// "unsigned"
// };
// span_err!(self.sess, e.span, E0079,
// "expected {} integer constant",
// sign_desc);
None
},
Err(_) => {
// span_err!(self.sess, err.span, E0080,
// "constant evaluation error: {}",
// err.description());
None
}
}
}
tcx.register_item_type(local_def(ctor_id), scheme);
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
} else if struct_def.fields[0].node.kind.is_unnamed() {
// Tuple-like.
let inputs: Vec<_> =
struct_def.fields
.iter()
.map(|field| tcx.lookup_item_type(
local_def(field.node.id)).ty)
.collect();
let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
&inputs[..],
selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
tcx.register_item_type(local_def(ctor_id),
TypeScheme {
generics: scheme.generics,
ty: ctor_fn_ty
});
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
fn next_disr(repr_type: attr::IntType,
prev_disr_val: Option<ty::Disr>) -> Option<ty::Disr> {
if let Some(prev_disr_val) = prev_disr_val {
let result = repr_type.disr_incr(prev_disr_val);
// if let None = result {
// self.report_discrim_overflow(v.span, &v.node.name.name.as_str(),
// repr_type, prev_disr_val);
// }
result
} else {
Some(ty::INITIAL_DISCRIMINANT_VALUE)
}
}
fn convert_enum_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
v: &ast::Variant,
disr: ty::Disr)
-> ty::VariantDef_<'tcx, 'tcx>
{
let did = local_def(v.node.id);
let name = v.node.name.name;
match v.node.kind {
ast::TupleVariantKind(ref va) => {
ty::VariantDef_ {
did: did,
name: name,
disr_val: disr,
fields: va.iter().map(|&ast::VariantArg { id, .. }| {
ty::FieldDef_::new(
local_def(id),
special_idents::unnamed_field.name,
ast::Visibility::Public
)
}).collect()
}
}
ast::StructVariantKind(ref def) => {
convert_struct_variant(tcx, did, name, disr, &def)
}
}
}
let did = local_def(it.id);
let repr_hints = tcx.lookup_repr_hints(did);
let (repr_type, repr_type_ty) = tcx.enum_repr_type(repr_hints.get(0));
let mut prev_disr = None;
let variants = def.variants.iter().map(|v| {
let disr = match v.node.disr_expr {
Some(ref e) => evaluate_disr_expr(tcx, repr_type_ty, e),
None => next_disr(repr_type, prev_disr)
}.unwrap_or(repr_type.disr_wrap_incr(prev_disr));
let v = convert_enum_variant(tcx, v, disr);
prev_disr = Some(disr);
v
}).collect();
tcx.intern_adt_def(local_def(it.id), ty::ADTKind::Enum, variants)
}
/// Ensures that the super-predicates of the trait with def-id
......@@ -1469,18 +1581,17 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
ty::TypeScheme { ty: ty, generics: ty_generics }
}
ast::ItemEnum(_, ref generics) => {
// Create a new generic polytype.
ast::ItemEnum(ref ei, 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), ty::ADTKind::Enum);
let def = convert_enum_def(tcx, it, ei);
let t = tcx.mk_enum(def, tcx.mk_substs(substs));
ty::TypeScheme { ty: t, generics: ty_generics }
}
ast::ItemStruct(_, ref generics) => {
ast::ItemStruct(ref si, 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), ty::ADTKind::Struct);
let def = convert_struct_def(tcx, it, si);
let t = tcx.mk_struct(def, tcx.mk_substs(substs));
ty::TypeScheme { ty: t, generics: ty_generics }
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册