Skip to content

Commit ab77c1d

Browse files
committed
Auto merge of #27551 - arielb1:adt-def, r=nikomatsakis
This ended up being a bigger refactoring than I thought, as I also cleaned a few ugly points in rustc. There are still a few areas that need improvements. Performance numbers: ``` Before: 572.70user 5.52system 7:33.21elapsed 127%CPU (0avgtext+0avgdata 1173368maxresident)k llvm-time: 385.858 After: 545.27user 5.49system 7:10.22elapsed 128%CPU (0avgtext+0avgdata 1145348maxresident)k llvm-time: 387.119 ``` A good 5% perf improvement. Note that after this patch >70% of the time is spent in LLVM - Amdahl's law is in full effect. Passes make check locally. r? @nikomatsakis
2 parents 9bba711 + eedb1cc commit ab77c1d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2091
-2210
lines changed

src/librustc/diagnostics.rs

-59
Original file line numberDiff line numberDiff line change
@@ -692,64 +692,6 @@ There's no easy fix for this, generally code will need to be refactored so that
692692
you no longer need to derive from `Super<Self>`.
693693
"####,
694694

695-
E0079: r##"
696-
Enum variants which contain no data can be given a custom integer
697-
representation. This error indicates that the value provided is not an integer
698-
literal and is therefore invalid.
699-
700-
For example, in the following code,
701-
702-
```
703-
enum Foo {
704-
Q = "32"
705-
}
706-
```
707-
708-
we try to set the representation to a string.
709-
710-
There's no general fix for this; if you can work with an integer then just set
711-
it to one:
712-
713-
```
714-
enum Foo {
715-
Q = 32
716-
}
717-
```
718-
719-
however if you actually wanted a mapping between variants and non-integer
720-
objects, it may be preferable to use a method with a match instead:
721-
722-
```
723-
enum Foo { Q }
724-
impl Foo {
725-
fn get_str(&self) -> &'static str {
726-
match *self {
727-
Foo::Q => "32",
728-
}
729-
}
730-
}
731-
```
732-
"##,
733-
734-
E0080: r##"
735-
This error indicates that the compiler was unable to sensibly evaluate an
736-
integer expression provided as an enum discriminant. Attempting to divide by 0
737-
or causing integer overflow are two ways to induce this error. For example:
738-
739-
```
740-
enum Enum {
741-
X = (1 << 500),
742-
Y = (1 / 0)
743-
}
744-
```
745-
746-
Ensure that the expressions given can be evaluated as the desired integer type.
747-
See the FFI section of the Reference for more information about using a custom
748-
integer type:
749-
750-
https://doc.rust-lang.org/reference.html#ffi-attributes
751-
"##,
752-
753695
E0109: r##"
754696
You tried to give a type parameter to a type which doesn't need it. Erroneous
755697
code example:
@@ -1937,6 +1879,5 @@ register_diagnostics! {
19371879
E0314, // closure outlives stack frame
19381880
E0315, // cannot invoke closure outside of its lifetime
19391881
E0316, // nested quantification of lifetimes
1940-
E0370, // discriminant overflow
19411882
E0400 // overloaded derefs are not allowed in constants
19421883
}

src/librustc/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(clone_from_slice)]
3333
#![feature(collections)]
3434
#![feature(const_fn)]
35+
#![feature(core)]
3536
#![feature(duration)]
3637
#![feature(duration_span)]
3738
#![feature(dynamic_lib)]
@@ -42,6 +43,7 @@
4243
#![feature(iter_cmp)]
4344
#![feature(iter_arith)]
4445
#![feature(libc)]
46+
#![feature(nonzero)]
4547
#![feature(num_bits_bytes)]
4648
#![feature(path_ext)]
4749
#![feature(quote)]
@@ -65,6 +67,7 @@
6567
#![allow(trivial_casts)]
6668

6769
extern crate arena;
70+
extern crate core;
6871
extern crate flate;
6972
extern crate fmt_macros;
7073
extern crate getopts;

src/librustc/metadata/csearch.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,6 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
112112
decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
113113
}
114114

115-
pub fn get_enum_variants<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
116-
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
117-
let cstore = &tcx.sess.cstore;
118-
let cdata = cstore.get_crate_data(def.krate);
119-
decoder::get_enum_variants(cstore.intr.clone(), &*cdata, def.node, tcx)
120-
}
121-
122115
/// Returns information about the given implementation.
123116
pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
124117
-> Vec<ty::ImplOrTraitItemId> {
@@ -194,11 +187,9 @@ pub fn get_item_attrs(cstore: &cstore::CStore,
194187
decoder::get_item_attrs(&*cdata, def_id.node)
195188
}
196189

197-
pub fn get_struct_fields(cstore: &cstore::CStore,
198-
def: ast::DefId)
199-
-> Vec<ty::FieldTy> {
190+
pub fn get_struct_field_names(cstore: &cstore::CStore, def: ast::DefId) -> Vec<ast::Name> {
200191
let cdata = cstore.get_crate_data(def.krate);
201-
decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
192+
decoder::get_struct_field_names(&cstore.intr, &*cdata, def.node)
202193
}
203194

204195
pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashMap<ast::NodeId,
@@ -221,6 +212,12 @@ pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::TraitDe
221212
decoder::get_trait_def(&*cdata, def.node, tcx)
222213
}
223214

215+
pub fn get_adt_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::AdtDefMaster<'tcx> {
216+
let cstore = &tcx.sess.cstore;
217+
let cdata = cstore.get_crate_data(def.krate);
218+
decoder::get_adt_def(&cstore.intr, &*cdata, def.node, tcx)
219+
}
220+
224221
pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
225222
-> ty::GenericPredicates<'tcx>
226223
{

src/librustc/metadata/decoder.rs

+121-80
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use middle::def;
3030
use middle::lang_items;
3131
use middle::subst;
3232
use middle::ty::{ImplContainer, TraitContainer};
33-
use middle::ty::{self, Ty};
33+
use middle::ty::{self, RegionEscape, Ty};
3434
use util::nodemap::FnvHashMap;
3535

3636
use std::cell::{Cell, RefCell};
@@ -108,7 +108,7 @@ fn lookup_item<'a>(item_id: ast::NodeId, data: &'a [u8]) -> rbml::Doc<'a> {
108108
find_item(item_id, items)
109109
}
110110

111-
#[derive(PartialEq)]
111+
#[derive(Debug, PartialEq)]
112112
enum Family {
113113
ImmStatic, // c
114114
MutStatic, // b
@@ -390,6 +390,119 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
390390
}
391391
}
392392

393+
pub fn get_adt_def<'tcx>(intr: &IdentInterner,
394+
cdata: Cmd,
395+
item_id: ast::NodeId,
396+
tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
397+
{
398+
fn get_enum_variants<'tcx>(intr: &IdentInterner,
399+
cdata: Cmd,
400+
doc: rbml::Doc,
401+
tcx: &ty::ctxt<'tcx>) -> Vec<ty::VariantDefData<'tcx, 'tcx>> {
402+
let mut disr_val = 0;
403+
reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
404+
let did = translated_def_id(cdata, p);
405+
let item = lookup_item(did.node, cdata.data());
406+
407+
if let Some(disr) = variant_disr_val(item) {
408+
disr_val = disr;
409+
}
410+
let disr = disr_val;
411+
disr_val = disr_val.wrapping_add(1);
412+
413+
ty::VariantDefData {
414+
did: did,
415+
name: item_name(intr, item),
416+
fields: get_variant_fields(intr, cdata, item, tcx),
417+
disr_val: disr
418+
}
419+
}).collect()
420+
}
421+
fn get_variant_fields<'tcx>(intr: &IdentInterner,
422+
cdata: Cmd,
423+
doc: rbml::Doc,
424+
tcx: &ty::ctxt<'tcx>) -> Vec<ty::FieldDefData<'tcx, 'tcx>> {
425+
reader::tagged_docs(doc, tag_item_field).map(|f| {
426+
let ff = item_family(f);
427+
match ff {
428+
PublicField | InheritedField => {},
429+
_ => tcx.sess.bug(&format!("expected field, found {:?}", ff))
430+
};
431+
ty::FieldDefData::new(item_def_id(f, cdata),
432+
item_name(intr, f),
433+
struct_field_family_to_visibility(ff))
434+
}).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| {
435+
let ff = item_family(f);
436+
ty::FieldDefData::new(item_def_id(f, cdata),
437+
special_idents::unnamed_field.name,
438+
struct_field_family_to_visibility(ff))
439+
})).collect()
440+
}
441+
fn get_struct_variant<'tcx>(intr: &IdentInterner,
442+
cdata: Cmd,
443+
doc: rbml::Doc,
444+
did: ast::DefId,
445+
tcx: &ty::ctxt<'tcx>) -> ty::VariantDefData<'tcx, 'tcx> {
446+
ty::VariantDefData {
447+
did: did,
448+
name: item_name(intr, doc),
449+
fields: get_variant_fields(intr, cdata, doc, tcx),
450+
disr_val: 0
451+
}
452+
}
453+
454+
let doc = lookup_item(item_id, cdata.data());
455+
let did = ast::DefId { krate: cdata.cnum, node: item_id };
456+
let (kind, variants) = match item_family(doc) {
457+
Enum => (ty::AdtKind::Enum,
458+
get_enum_variants(intr, cdata, doc, tcx)),
459+
Struct => (ty::AdtKind::Struct,
460+
vec![get_struct_variant(intr, cdata, doc, did, tcx)]),
461+
_ => tcx.sess.bug("get_adt_def called on a non-ADT")
462+
};
463+
464+
let adt = tcx.intern_adt_def(did, kind, variants);
465+
466+
// this needs to be done *after* the variant is interned,
467+
// to support recursive structures
468+
for variant in &adt.variants {
469+
if variant.kind() == ty::VariantKind::Tuple &&
470+
adt.adt_kind() == ty::AdtKind::Enum {
471+
// tuple-like enum variant fields aren't real items - get the types
472+
// from the ctor.
473+
debug!("evaluating the ctor-type of {:?}",
474+
variant.name);
475+
let ctor_ty = get_type(cdata, variant.did.node, tcx).ty;
476+
debug!("evaluating the ctor-type of {:?}.. {:?}",
477+
variant.name,
478+
ctor_ty);
479+
let field_tys = match ctor_ty.sty {
480+
ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
481+
ref inputs, ..
482+
}), ..}) => {
483+
// tuple-struct constructors don't have escaping regions
484+
assert!(!inputs.has_escaping_regions());
485+
inputs
486+
},
487+
_ => tcx.sess.bug("tuple-variant ctor is not an ADT")
488+
};
489+
for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) {
490+
field.fulfill_ty(ty);
491+
}
492+
} else {
493+
for field in &variant.fields {
494+
debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
495+
let ty = get_type(cdata, field.did.node, tcx).ty;
496+
field.fulfill_ty(ty);
497+
debug!("evaluating the type of {:?}::{:?}: {:?}",
498+
variant.name, field.name, ty);
499+
}
500+
}
501+
}
502+
503+
adt
504+
}
505+
393506
pub fn get_predicates<'tcx>(cdata: Cmd,
394507
item_id: ast::NodeId,
395508
tcx: &ty::ctxt<'tcx>)
@@ -687,55 +800,6 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
687800
}
688801
}
689802

690-
pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
691-
tcx: &ty::ctxt<'tcx>) -> Vec<Rc<ty::VariantInfo<'tcx>>> {
692-
let data = cdata.data();
693-
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
694-
let item = find_item(id, items);
695-
let mut disr_val = 0;
696-
reader::tagged_docs(item, tag_items_data_item_variant).map(|p| {
697-
let did = translated_def_id(cdata, p);
698-
let item = find_item(did.node, items);
699-
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
700-
item, tcx, cdata);
701-
let name = item_name(&*intr, item);
702-
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
703-
ty::TyBareFn(_, ref f) =>
704-
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
705-
_ => { // Nullary or struct enum variant.
706-
let mut arg_names = Vec::new();
707-
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)
708-
.iter()
709-
.map(|field_ty| {
710-
arg_names.push(field_ty.name);
711-
get_type(cdata, field_ty.id.node, tcx).ty
712-
})
713-
.collect();
714-
let arg_names = if arg_names.is_empty() { None } else { Some(arg_names) };
715-
716-
(None, arg_tys, arg_names)
717-
}
718-
};
719-
match variant_disr_val(item) {
720-
Some(val) => { disr_val = val; }
721-
_ => { /* empty */ }
722-
}
723-
let old_disr_val = disr_val;
724-
disr_val = disr_val.wrapping_add(1);
725-
Rc::new(ty::VariantInfo {
726-
args: arg_tys,
727-
arg_names: arg_names,
728-
ctor_ty: ctor_ty,
729-
name: name,
730-
// I'm not even sure if we encode visibility
731-
// for variants -- TEST -- tjc
732-
id: did,
733-
disr_val: old_disr_val,
734-
vis: ast::Inherited
735-
})
736-
}).collect()
737-
}
738-
739803
fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
740804
fn get_mutability(ch: u8) -> ast::Mutability {
741805
match ch as char {
@@ -1029,37 +1093,14 @@ fn struct_field_family_to_visibility(family: Family) -> ast::Visibility {
10291093
}
10301094
}
10311095

1032-
pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
1033-
-> Vec<ty::FieldTy> {
1096+
pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
1097+
-> Vec<ast::Name> {
10341098
let data = cdata.data();
10351099
let item = lookup_item(id, data);
1036-
reader::tagged_docs(item, tag_item_field).filter_map(|an_item| {
1037-
let f = item_family(an_item);
1038-
if f == PublicField || f == InheritedField {
1039-
let name = item_name(&*intr, an_item);
1040-
let did = item_def_id(an_item, cdata);
1041-
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1042-
let origin_id = translated_def_id(cdata, tagdoc);
1043-
Some(ty::FieldTy {
1044-
name: name,
1045-
id: did,
1046-
vis: struct_field_family_to_visibility(f),
1047-
origin: origin_id,
1048-
})
1049-
} else {
1050-
None
1051-
}
1052-
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|an_item| {
1053-
let did = item_def_id(an_item, cdata);
1054-
let tagdoc = reader::get_doc(an_item, tag_item_field_origin);
1055-
let f = item_family(an_item);
1056-
let origin_id = translated_def_id(cdata, tagdoc);
1057-
ty::FieldTy {
1058-
name: special_idents::unnamed_field.name,
1059-
id: did,
1060-
vis: struct_field_family_to_visibility(f),
1061-
origin: origin_id,
1062-
}
1100+
reader::tagged_docs(item, tag_item_field).map(|an_item| {
1101+
item_name(intr, an_item)
1102+
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
1103+
special_idents::unnamed_field.name
10631104
})).collect()
10641105
}
10651106

0 commit comments

Comments
 (0)