Skip to content

store ADT information in an AdtDef structure in a unified way #27551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Aug 7, 2015
59 changes: 0 additions & 59 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,64 +692,6 @@ There's no easy fix for this, generally code will need to be refactored so that
you no longer need to derive from `Super<Self>`.
"####,

E0079: r##"
Enum variants which contain no data can be given a custom integer
representation. This error indicates that the value provided is not an integer
literal and is therefore invalid.

For example, in the following code,

```
enum Foo {
Q = "32"
}
```

we try to set the representation to a string.

There's no general fix for this; if you can work with an integer then just set
it to one:

```
enum Foo {
Q = 32
}
```

however if you actually wanted a mapping between variants and non-integer
objects, it may be preferable to use a method with a match instead:

```
enum Foo { Q }
impl Foo {
fn get_str(&self) -> &'static str {
match *self {
Foo::Q => "32",
}
}
}
```
"##,

E0080: r##"
This error indicates that the compiler was unable to sensibly evaluate an
integer expression provided as an enum discriminant. Attempting to divide by 0
or causing integer overflow are two ways to induce this error. For example:

```
enum Enum {
X = (1 << 500),
Y = (1 / 0)
}
```

Ensure that the expressions given can be evaluated as the desired integer type.
See the FFI section of the Reference for more information about using a custom
integer type:

https://doc.rust-lang.org/reference.html#ffi-attributes
"##,

E0109: r##"
You tried to give a type parameter to a type which doesn't need it. Erroneous
code example:
Expand Down Expand Up @@ -1937,6 +1879,5 @@ register_diagnostics! {
E0314, // closure outlives stack frame
E0315, // cannot invoke closure outside of its lifetime
E0316, // nested quantification of lifetimes
E0370, // discriminant overflow
E0400 // overloaded derefs are not allowed in constants
}
3 changes: 3 additions & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#![feature(clone_from_slice)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(core)]
#![feature(duration)]
#![feature(duration_span)]
#![feature(dynamic_lib)]
Expand All @@ -42,6 +43,7 @@
#![feature(iter_cmp)]
#![feature(iter_arith)]
#![feature(libc)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(path_ext)]
#![feature(quote)]
Expand All @@ -65,6 +67,7 @@
#![allow(trivial_casts)]

extern crate arena;
extern crate core;
extern crate flate;
extern crate fmt_macros;
extern crate getopts;
Expand Down
19 changes: 8 additions & 11 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,6 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
}

pub fn get_enum_variants<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_enum_variants(cstore.intr.clone(), &*cdata, def.node, tcx)
}

/// Returns information about the given implementation.
pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
-> Vec<ty::ImplOrTraitItemId> {
Expand Down Expand Up @@ -195,11 +188,9 @@ pub fn get_item_attrs(cstore: &cstore::CStore,
decoder::get_item_attrs(&*cdata, def_id.node)
}

pub fn get_struct_fields(cstore: &cstore::CStore,
def: ast::DefId)
-> Vec<ty::FieldTy> {
pub fn get_struct_field_names(cstore: &cstore::CStore, def: ast::DefId) -> Vec<ast::Name> {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
decoder::get_struct_field_names(&cstore.intr, &*cdata, def.node)
}

pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashMap<ast::NodeId,
Expand All @@ -222,6 +213,12 @@ 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) -> ty::AdtDefMaster<'tcx> {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_adt_def(&cstore.intr, &*cdata, def.node, tcx)
}

pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
-> ty::GenericPredicates<'tcx>
{
Expand Down
201 changes: 121 additions & 80 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use middle::def;
use middle::lang_items;
use middle::subst;
use middle::ty::{ImplContainer, TraitContainer};
use middle::ty::{self, Ty};
use middle::ty::{self, RegionEscape, Ty};
use util::nodemap::FnvHashMap;

use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -390,6 +390,119 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
}
}

pub fn get_adt_def<'tcx>(intr: &IdentInterner,
cdata: Cmd,
item_id: ast::NodeId,
tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
{
fn get_enum_variants<'tcx>(intr: &IdentInterner,
cdata: Cmd,
doc: rbml::Doc,
tcx: &ty::ctxt<'tcx>) -> Vec<ty::VariantDefData<'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::VariantDefData {
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::FieldDefData<'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::FieldDefData::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::FieldDefData::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::VariantDefData<'tcx, 'tcx> {
ty::VariantDefData {
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(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
ref inputs, ..
}), ..}) => {
// tuple-struct constructors don't have escaping regions
assert!(!inputs.has_escaping_regions());
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,
item_id: ast::NodeId,
tcx: &ty::ctxt<'tcx>)
Expand Down Expand Up @@ -687,55 +800,6 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
}
}

pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
tcx: &ty::ctxt<'tcx>) -> Vec<Rc<ty::VariantInfo<'tcx>>> {
let data = cdata.data();
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
let item = find_item(id, items);
let mut disr_val = 0;
reader::tagged_docs(item, tag_items_data_item_variant).map(|p| {
let did = translated_def_id(cdata, p);
let item = find_item(did.node, items);
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
item, tcx, cdata);
let name = item_name(&*intr, item);
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
ty::TyBareFn(_, ref f) =>
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
_ => { // Nullary or struct enum variant.
let mut arg_names = Vec::new();
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)
.iter()
.map(|field_ty| {
arg_names.push(field_ty.name);
get_type(cdata, field_ty.id.node, tcx).ty
})
.collect();
let arg_names = if arg_names.is_empty() { None } else { Some(arg_names) };

(None, arg_tys, arg_names)
}
};
match variant_disr_val(item) {
Some(val) => { disr_val = val; }
_ => { /* empty */ }
}
let old_disr_val = disr_val;
disr_val = disr_val.wrapping_add(1);
Rc::new(ty::VariantInfo {
args: arg_tys,
arg_names: arg_names,
ctor_ty: ctor_ty,
name: name,
// I'm not even sure if we encode visibility
// for variants -- TEST -- tjc
id: did,
disr_val: old_disr_val,
vis: ast::Inherited
})
}).collect()
}

fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
fn get_mutability(ch: u8) -> ast::Mutability {
match ch as char {
Expand Down Expand Up @@ -1029,37 +1093,14 @@ fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
}
}

pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
-> Vec<ty::FieldTy> {
pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
-> Vec<ast::Name> {
let data = cdata.data();
let item = lookup_item(id, data);
reader::tagged_docs(item, tag_item_field).filter_map(|an_item| {
let f = item_family(an_item);
if f == PublicField || f == InheritedField {
let name = item_name(&*intr, an_item);
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let origin_id = translated_def_id(cdata, tagdoc);
Some(ty::FieldTy {
name: name,
id: did,
vis: struct_field_family_to_visibility(f),
origin: origin_id,
})
} else {
None
}
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|an_item| {
let did = item_def_id(an_item, cdata);
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
let f = item_family(an_item);
let origin_id = translated_def_id(cdata, tagdoc);
ty::FieldTy {
name: special_idents::unnamed_field.name,
id: did,
vis: struct_field_family_to_visibility(f),
origin: origin_id,
}
reader::tagged_docs(item, tag_item_field).map(|an_item| {
item_name(intr, an_item)
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
special_idents::unnamed_field.name
})).collect()
}

Expand Down
Loading