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
This commit is contained in:
commit
ab77c1d8d0
63 changed files with 2092 additions and 2211 deletions
|
|
@ -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:
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -112,13 +112,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> {
|
||||
|
|
@ -194,11 +187,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,
|
||||
|
|
@ -221,6 +212,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>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -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,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>)
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ use syntax::attr::AttrMetaMethods;
|
|||
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,9 +265,9 @@ fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
|
|||
}
|
||||
|
||||
fn encode_struct_fields(rbml_w: &mut Encoder,
|
||||
fields: &[ty::FieldTy],
|
||||
variant: ty::VariantDef,
|
||||
origin: DefId) {
|
||||
for f in fields {
|
||||
for f in &variant.fields {
|
||||
if f.name == special_idents::unnamed_field.name {
|
||||
rbml_w.start_tag(tag_item_unnamed_field);
|
||||
} else {
|
||||
|
|
@ -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,53 @@ 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 stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
|
||||
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, 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, index);
|
||||
encode_index(rbml_w, idx, write_i64);
|
||||
}
|
||||
let specified_disr_val = vi[i].disr_val;
|
||||
|
||||
encode_struct_fields(rbml_w, variant, 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,19 +625,19 @@ 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,
|
||||
variant: ty::VariantDef<'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();
|
||||
/* We encode both private and public fields -- need to include
|
||||
private fields to get the offsets right */
|
||||
for field in fields {
|
||||
for field in &variant.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 +653,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 +1145,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||
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 variant = def.struct_variant();
|
||||
|
||||
/* 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, variant, index);
|
||||
|
||||
/* Index the class*/
|
||||
add_to_index(item, rbml_w, index);
|
||||
|
|
@ -1185,7 +1178,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||
/* 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, variant, def_id);
|
||||
|
||||
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
|
||||
|
||||
|
|
|
|||
|
|
@ -468,9 +468,10 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
|
|||
'c' => return tcx.types.char,
|
||||
't' => {
|
||||
assert_eq!(next(st), '[');
|
||||
let def = parse_def_(st, NominalType, conv);
|
||||
let did = parse_def_(st, NominalType, conv);
|
||||
let substs = parse_substs_(st, conv);
|
||||
assert_eq!(next(st), ']');
|
||||
let def = st.tcx.lookup_adt_def(did);
|
||||
return tcx.mk_enum(def, st.tcx.mk_substs(substs));
|
||||
}
|
||||
'x' => {
|
||||
|
|
@ -558,7 +559,8 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
|
|||
let did = parse_def_(st, NominalType, conv);
|
||||
let substs = parse_substs_(st, conv);
|
||||
assert_eq!(next(st), ']');
|
||||
return st.tcx.mk_struct(did, st.tcx.mk_substs(substs));
|
||||
let def = st.tcx.lookup_adt_def(did);
|
||||
return st.tcx.mk_struct(def, st.tcx.mk_substs(substs));
|
||||
}
|
||||
'k' => {
|
||||
assert_eq!(next(st), '[');
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
|
|||
}
|
||||
}
|
||||
ty::TyEnum(def, substs) => {
|
||||
mywrite!(w, "t[{}|", (cx.ds)(def));
|
||||
mywrite!(w, "t[{}|", (cx.ds)(def.did));
|
||||
enc_substs(w, cx, substs);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
|
|||
mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name)
|
||||
}
|
||||
ty::TyStruct(def, substs) => {
|
||||
mywrite!(w, "a[{}|", (cx.ds)(def));
|
||||
mywrite!(w, "a[{}|", (cx.ds)(def.did));
|
||||
enc_substs(w, cx, substs);
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,15 +58,14 @@ pub enum CastKind {
|
|||
}
|
||||
|
||||
impl<'tcx> CastTy<'tcx> {
|
||||
pub fn from_ty(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
|
||||
-> Option<CastTy<'tcx>> {
|
||||
pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
|
||||
match t.sty {
|
||||
ty::TyBool => Some(CastTy::Int(IntTy::Bool)),
|
||||
ty::TyChar => Some(CastTy::Int(IntTy::Char)),
|
||||
ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
|
||||
ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
|
||||
ty::TyFloat(_) => Some(CastTy::Float),
|
||||
ty::TyEnum(..) if t.is_c_like_enum(tcx) =>
|
||||
ty::TyEnum(d,_) if d.is_payloadfree() =>
|
||||
Some(CastTy::Int(IntTy::CEnum)),
|
||||
ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
|
||||
ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
|
||||
|
|
|
|||
|
|
@ -546,8 +546,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
|||
fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
|
||||
e: &ast::Expr, node_ty: Ty<'tcx>) {
|
||||
match node_ty.sty {
|
||||
ty::TyStruct(did, _) |
|
||||
ty::TyEnum(did, _) if v.tcx.has_dtor(did) => {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor(v.tcx) => {
|
||||
v.add_qualif(ConstQualif::NEEDS_DROP);
|
||||
if v.mode != Mode::Var {
|
||||
v.tcx.sess.span_err(e.span,
|
||||
|
|
|
|||
|
|
@ -234,12 +234,12 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
|
|||
match p.node {
|
||||
ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
|
||||
let pat_ty = cx.tcx.pat_ty(p);
|
||||
if let ty::TyEnum(def_id, _) = pat_ty.sty {
|
||||
if let ty::TyEnum(edef, _) = pat_ty.sty {
|
||||
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
|
||||
if let Some(DefLocal(_)) = def {
|
||||
if cx.tcx.enum_variants(def_id).iter().any(|variant|
|
||||
if edef.variants.iter().any(|variant|
|
||||
variant.name == ident.node.name
|
||||
&& variant.args.is_empty()
|
||||
&& variant.kind() == VariantKind::Unit
|
||||
) {
|
||||
span_warn!(cx.tcx.sess, p.span, E0170,
|
||||
"pattern binding `{}` is named the same as one \
|
||||
|
|
@ -501,23 +501,17 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
|
|||
///
|
||||
/// left_ty: struct X { a: (bool, &'static str), b: usize}
|
||||
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
|
||||
fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
|
||||
pats: Vec<&Pat>, left_ty: Ty) -> P<Pat> {
|
||||
fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
pats: Vec<&Pat>, left_ty: Ty<'tcx>) -> P<Pat> {
|
||||
let pats_len = pats.len();
|
||||
let mut pats = pats.into_iter().map(|p| P((*p).clone()));
|
||||
let pat = match left_ty.sty {
|
||||
ty::TyTuple(_) => ast::PatTup(pats.collect()),
|
||||
|
||||
ty::TyEnum(cid, _) | ty::TyStruct(cid, _) => {
|
||||
let (vid, is_structure) = match ctor {
|
||||
&Variant(vid) =>
|
||||
(vid, cx.tcx.enum_variant_with_id(cid, vid).arg_names.is_some()),
|
||||
_ =>
|
||||
(cid, !cx.tcx.is_tuple_struct(cid))
|
||||
};
|
||||
if is_structure {
|
||||
let fields = cx.tcx.lookup_struct_fields(vid);
|
||||
let field_pats: Vec<_> = fields.into_iter()
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
|
||||
let v = adt.variant_of_ctor(ctor);
|
||||
if let VariantKind::Dict = v.kind() {
|
||||
let field_pats: Vec<_> = v.fields.iter()
|
||||
.zip(pats)
|
||||
.filter(|&(_, ref pat)| pat.node != ast::PatWild(ast::PatWildSingle))
|
||||
.map(|(field, pat)| Spanned {
|
||||
|
|
@ -529,9 +523,9 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
|
|||
}
|
||||
}).collect();
|
||||
let has_more_fields = field_pats.len() < pats_len;
|
||||
ast::PatStruct(def_to_path(cx.tcx, vid), field_pats, has_more_fields)
|
||||
ast::PatStruct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
|
||||
} else {
|
||||
ast::PatEnum(def_to_path(cx.tcx, vid), Some(pats.collect()))
|
||||
ast::PatEnum(def_to_path(cx.tcx, v.did), Some(pats.collect()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -580,6 +574,17 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
|
|||
})
|
||||
}
|
||||
|
||||
impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
|
||||
fn variant_of_ctor(&self,
|
||||
ctor: &Constructor)
|
||||
-> &VariantDefData<'tcx, 'container> {
|
||||
match ctor {
|
||||
&Variant(vid) => self.variant_with_id(vid),
|
||||
_ => self.struct_variant()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
|
||||
left_ty: Ty, max_slice_length: usize) -> Option<Constructor> {
|
||||
let used_constructors: Vec<Constructor> = rows.iter()
|
||||
|
|
@ -594,7 +599,7 @@ fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
|
|||
/// values of type `left_ty`. For vectors, this would normally be an infinite set
|
||||
/// but is instead bounded by the maximum fixed length of slice patterns in
|
||||
/// the column of patterns being analyzed.
|
||||
fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
|
||||
fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
|
||||
max_slice_length: usize) -> Vec<Constructor> {
|
||||
match left_ty.sty {
|
||||
ty::TyBool =>
|
||||
|
|
@ -603,17 +608,11 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
|
|||
ty::TyRef(_, ty::TypeAndMut { ty, .. }) => match ty.sty {
|
||||
ty::TySlice(_) =>
|
||||
range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
|
||||
_ => vec!(Single)
|
||||
_ => vec![Single]
|
||||
},
|
||||
|
||||
ty::TyEnum(eid, _) =>
|
||||
cx.tcx.enum_variants(eid)
|
||||
.iter()
|
||||
.map(|va| Variant(va.id))
|
||||
.collect(),
|
||||
|
||||
_ =>
|
||||
vec!(Single)
|
||||
ty::TyEnum(def, _) => def.variants.iter().map(|v| Variant(v.did)).collect(),
|
||||
_ => vec![Single]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -804,7 +803,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
|
|||
///
|
||||
/// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
|
||||
/// A struct pattern's arity is the number of fields it contains, etc.
|
||||
pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
|
||||
pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
|
||||
match ty.sty {
|
||||
ty::TyTuple(ref fs) => fs.len(),
|
||||
ty::TyBox(_) => 1,
|
||||
|
|
@ -817,13 +816,9 @@ pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usi
|
|||
ty::TyStr => 0,
|
||||
_ => 1
|
||||
},
|
||||
ty::TyEnum(eid, _) => {
|
||||
match *ctor {
|
||||
Variant(id) => cx.tcx.enum_variant_with_id(eid, id).args.len(),
|
||||
_ => unreachable!()
|
||||
}
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
|
||||
adt.variant_of_ctor(ctor).fields.len()
|
||||
}
|
||||
ty::TyStruct(cid, _) => cx.tcx.lookup_struct_fields(cid).len(),
|
||||
ty::TyArray(_, n) => n,
|
||||
_ => 0
|
||||
}
|
||||
|
|
@ -902,39 +897,20 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
|||
}
|
||||
|
||||
ast::PatStruct(_, ref pattern_fields, _) => {
|
||||
// Is this a struct or an enum variant?
|
||||
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
|
||||
let class_id = match def {
|
||||
DefConst(..) | DefAssociatedConst(..) =>
|
||||
cx.tcx.sess.span_bug(pat_span, "const pattern should've \
|
||||
been rewritten"),
|
||||
DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
|
||||
Some(variant_id)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
_ => {
|
||||
// Assume this is a struct.
|
||||
match cx.tcx.node_id_to_type(pat_id).ty_to_def_id() {
|
||||
None => {
|
||||
cx.tcx.sess.span_bug(pat_span,
|
||||
"struct pattern wasn't of a \
|
||||
type with a def ID?!")
|
||||
}
|
||||
Some(def_id) => Some(def_id),
|
||||
}
|
||||
}
|
||||
};
|
||||
class_id.map(|variant_id| {
|
||||
let struct_fields = cx.tcx.lookup_struct_fields(variant_id);
|
||||
let args = struct_fields.iter().map(|sf| {
|
||||
let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
|
||||
let variant = adt.variant_of_ctor(constructor);
|
||||
let def_variant = adt.variant_of_def(def);
|
||||
if variant.did == def_variant.did {
|
||||
Some(variant.fields.iter().map(|sf| {
|
||||
match pattern_fields.iter().find(|f| f.node.ident.name == sf.name) {
|
||||
Some(ref f) => &*f.node.pat,
|
||||
_ => DUMMY_WILD_PAT
|
||||
}
|
||||
}).collect();
|
||||
args
|
||||
})
|
||||
}).collect())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
ast::PatTup(ref args) =>
|
||||
|
|
|
|||
|
|
@ -100,51 +100,32 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) {
|
||||
match self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
ty::TyStruct(id, _) => {
|
||||
let fields = self.tcx.lookup_struct_fields(id);
|
||||
let field_id = fields.iter()
|
||||
.find(|field| field.name == name).unwrap().id;
|
||||
self.live_symbols.insert(field_id.node);
|
||||
},
|
||||
_ => ()
|
||||
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
self.live_symbols.insert(def.struct_variant().field_named(name).did.node);
|
||||
} else {
|
||||
self.tcx.sess.span_bug(lhs.span, "named field access on non-struct")
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: usize) {
|
||||
match self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
ty::TyStruct(id, _) => {
|
||||
let fields = self.tcx.lookup_struct_fields(id);
|
||||
let field_id = fields[idx].id;
|
||||
self.live_symbols.insert(field_id.node);
|
||||
},
|
||||
_ => ()
|
||||
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
self.live_symbols.insert(def.struct_variant().fields[idx].did.node);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
|
||||
pats: &[codemap::Spanned<ast::FieldPat>]) {
|
||||
let id = match self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def() {
|
||||
def::DefVariant(_, id, _) => id,
|
||||
_ => {
|
||||
match self.tcx.node_id_to_type(lhs.id).ty_to_def_id() {
|
||||
None => {
|
||||
self.tcx.sess.span_bug(lhs.span,
|
||||
"struct pattern wasn't of a \
|
||||
type with a def ID?!")
|
||||
}
|
||||
Some(def_id) => def_id,
|
||||
}
|
||||
}
|
||||
let def = self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def();
|
||||
let pat_ty = self.tcx.node_id_to_type(lhs.id);
|
||||
let variant = match pat_ty.sty {
|
||||
ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => adt.variant_of_def(def),
|
||||
_ => self.tcx.sess.span_bug(lhs.span, "non-ADT in struct pattern")
|
||||
};
|
||||
let fields = self.tcx.lookup_struct_fields(id);
|
||||
for pat in pats {
|
||||
if let ast::PatWild(ast::PatWildSingle) = pat.node.pat.node {
|
||||
continue;
|
||||
}
|
||||
let field_id = fields.iter()
|
||||
.find(|field| field.name == pat.node.ident.name).unwrap().id;
|
||||
self.live_symbols.insert(field_id.node);
|
||||
self.live_symbols.insert(variant.field_named(pat.node.ident.name).did.node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -694,41 +694,36 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
|||
|
||||
// Select just those fields of the `with`
|
||||
// expression that will actually be used
|
||||
let with_fields = match with_cmt.ty.sty {
|
||||
ty::TyStruct(did, substs) => {
|
||||
self.tcx().struct_fields(did, substs)
|
||||
}
|
||||
_ => {
|
||||
// the base expression should always evaluate to a
|
||||
// struct; however, when EUV is run during typeck, it
|
||||
// may not. This will generate an error earlier in typeck,
|
||||
// so we can just ignore it.
|
||||
if !self.tcx().sess.has_errors() {
|
||||
self.tcx().sess.span_bug(
|
||||
with_expr.span,
|
||||
"with expression doesn't evaluate to a struct");
|
||||
if let ty::TyStruct(def, substs) = with_cmt.ty.sty {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for with_field in &def.struct_variant().fields {
|
||||
if !contains_field_named(with_field, fields) {
|
||||
let cmt_field = self.mc.cat_field(
|
||||
&*with_expr,
|
||||
with_cmt.clone(),
|
||||
with_field.name,
|
||||
with_field.ty(self.tcx(), substs)
|
||||
);
|
||||
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
|
||||
}
|
||||
assert!(self.tcx().sess.has_errors());
|
||||
vec!()
|
||||
}
|
||||
} else {
|
||||
// the base expression should always evaluate to a
|
||||
// struct; however, when EUV is run during typeck, it
|
||||
// may not. This will generate an error earlier in typeck,
|
||||
// so we can just ignore it.
|
||||
if !self.tcx().sess.has_errors() {
|
||||
self.tcx().sess.span_bug(
|
||||
with_expr.span,
|
||||
"with expression doesn't evaluate to a struct");
|
||||
}
|
||||
};
|
||||
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for with_field in &with_fields {
|
||||
if !contains_field_named(with_field, fields) {
|
||||
let cmt_field = self.mc.cat_field(&*with_expr,
|
||||
with_cmt.clone(),
|
||||
with_field.name,
|
||||
with_field.mt.ty);
|
||||
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
|
||||
}
|
||||
}
|
||||
|
||||
// walk the with expression so that complex expressions
|
||||
// are properly handled.
|
||||
self.walk_expr(with_expr);
|
||||
|
||||
fn contains_field_named(field: &ty::Field,
|
||||
fn contains_field_named(field: ty::FieldDef,
|
||||
fields: &Vec<ast::Field>)
|
||||
-> bool
|
||||
{
|
||||
|
|
@ -1106,7 +1101,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
|||
|
||||
Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
|
||||
let downcast_cmt =
|
||||
if tcx.enum_is_univariant(enum_did) {
|
||||
if tcx.lookup_adt_def(enum_did).is_univariant() {
|
||||
cmt_pat
|
||||
} else {
|
||||
let cmt_pat_ty = cmt_pat.ty;
|
||||
|
|
|
|||
|
|
@ -53,15 +53,15 @@ pub fn simplify_type(tcx: &ty::ctxt,
|
|||
ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)),
|
||||
ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)),
|
||||
ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)),
|
||||
ty::TyEnum(def_id, _) => Some(EnumSimplifiedType(def_id)),
|
||||
ty::TyEnum(def, _) => Some(EnumSimplifiedType(def.did)),
|
||||
ty::TyStr => Some(StrSimplifiedType),
|
||||
ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType),
|
||||
ty::TyRawPtr(_) => Some(PtrSimplifiedType),
|
||||
ty::TyTrait(ref trait_info) => {
|
||||
Some(TraitSimplifiedType(trait_info.principal_def_id()))
|
||||
}
|
||||
ty::TyStruct(def_id, _) => {
|
||||
Some(StructSimplifiedType(def_id))
|
||||
ty::TyStruct(def, _) => {
|
||||
Some(StructSimplifiedType(def.did))
|
||||
}
|
||||
ty::TyRef(_, mt) => {
|
||||
// since we introduce auto-refs during method lookup, we
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
|||
self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
|
||||
}
|
||||
|
||||
ty::TyEnum(def_id, substs) |
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let item_scheme = self.tcx().lookup_item_type(def_id);
|
||||
self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
|
||||
ty::TyEnum(def, substs) |
|
||||
ty::TyStruct(def, substs) => {
|
||||
let item_scheme = def.type_scheme(self.tcx());
|
||||
self.accumulate_from_adt(ty, def.did, &item_scheme.generics, substs)
|
||||
}
|
||||
|
||||
ty::TyArray(t, _) |
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
|
|||
let cmt = match opt_def {
|
||||
Some(def::DefVariant(enum_did, variant_did, _))
|
||||
// univariant enums do not need downcasts
|
||||
if !self.tcx().enum_is_univariant(enum_did) => {
|
||||
if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
|
||||
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
|
||||
}
|
||||
_ => cmt
|
||||
|
|
|
|||
|
|
@ -415,16 +415,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
|
|||
ast::ExprField(ref base_e, ref field) => {
|
||||
span = field.span;
|
||||
match tcx.expr_ty_adjusted(base_e).sty {
|
||||
ty::TyStruct(did, _) => {
|
||||
tcx.lookup_struct_fields(did)
|
||||
.iter()
|
||||
.find(|f| f.name == field.node.name)
|
||||
.unwrap_or_else(|| {
|
||||
tcx.sess.span_bug(field.span,
|
||||
"stability::check_expr: unknown named field access")
|
||||
})
|
||||
.id
|
||||
}
|
||||
ty::TyStruct(def, _) => def.struct_variant().field_named(field.node.name).did,
|
||||
_ => tcx.sess.span_bug(e.span,
|
||||
"stability::check_expr: named field access on non-struct")
|
||||
}
|
||||
|
|
@ -432,15 +423,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
|
|||
ast::ExprTupField(ref base_e, ref field) => {
|
||||
span = field.span;
|
||||
match tcx.expr_ty_adjusted(base_e).sty {
|
||||
ty::TyStruct(did, _) => {
|
||||
tcx.lookup_struct_fields(did)
|
||||
.get(field.node)
|
||||
.unwrap_or_else(|| {
|
||||
tcx.sess.span_bug(field.span,
|
||||
"stability::check_expr: unknown unnamed field access")
|
||||
})
|
||||
.id
|
||||
}
|
||||
ty::TyStruct(def, _) => def.struct_variant().fields[field.node].did,
|
||||
ty::TyTuple(..) => return,
|
||||
_ => tcx.sess.span_bug(e.span,
|
||||
"stability::check_expr: unnamed field access on \
|
||||
|
|
@ -450,20 +433,13 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
|
|||
ast::ExprStruct(_, ref expr_fields, _) => {
|
||||
let type_ = tcx.expr_ty(e);
|
||||
match type_.sty {
|
||||
ty::TyStruct(did, _) => {
|
||||
let struct_fields = tcx.lookup_struct_fields(did);
|
||||
ty::TyStruct(def, _) => {
|
||||
// check the stability of each field that appears
|
||||
// in the construction expression.
|
||||
for field in expr_fields {
|
||||
let did = struct_fields
|
||||
.iter()
|
||||
.find(|f| f.name == field.ident.node.name)
|
||||
.unwrap_or_else(|| {
|
||||
tcx.sess.span_bug(field.span,
|
||||
"stability::check_expr: unknown named \
|
||||
field access")
|
||||
})
|
||||
.id;
|
||||
let did = def.struct_variant()
|
||||
.field_named(field.ident.node.name)
|
||||
.did;
|
||||
maybe_do_stability_check(tcx, did, field.span, cb);
|
||||
}
|
||||
|
||||
|
|
@ -505,34 +481,26 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
|
|||
debug!("check_pat(pat = {:?})", pat);
|
||||
if is_internal(tcx, pat.span) { return; }
|
||||
|
||||
let did = match tcx.pat_ty_opt(pat) {
|
||||
Some(&ty::TyS { sty: ty::TyStruct(did, _), .. }) => did,
|
||||
let v = match tcx.pat_ty_opt(pat) {
|
||||
Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) => def.struct_variant(),
|
||||
Some(_) | None => return,
|
||||
};
|
||||
let struct_fields = tcx.lookup_struct_fields(did);
|
||||
match pat.node {
|
||||
// Foo(a, b, c)
|
||||
ast::PatEnum(_, Some(ref pat_fields)) => {
|
||||
for (field, struct_field) in pat_fields.iter().zip(&struct_fields) {
|
||||
for (field, struct_field) in pat_fields.iter().zip(&v.fields) {
|
||||
// a .. pattern is fine, but anything positional is
|
||||
// not.
|
||||
if let ast::PatWild(ast::PatWildMulti) = field.node {
|
||||
continue
|
||||
}
|
||||
maybe_do_stability_check(tcx, struct_field.id, field.span, cb)
|
||||
maybe_do_stability_check(tcx, struct_field.did, field.span, cb)
|
||||
}
|
||||
}
|
||||
// Foo { a, b, c }
|
||||
ast::PatStruct(_, ref pat_fields, _) => {
|
||||
for field in pat_fields {
|
||||
let did = struct_fields
|
||||
.iter()
|
||||
.find(|f| f.name == field.node.ident.name)
|
||||
.unwrap_or_else(|| {
|
||||
tcx.sess.span_bug(field.span,
|
||||
"stability::check_pat: unknown named field access")
|
||||
})
|
||||
.id;
|
||||
let did = v.field_named(field.node.ident.name).did;
|
||||
maybe_do_stability_check(tcx, did, field.span, cb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,8 +278,8 @@ fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
|
|||
match ty.sty {
|
||||
ty::TyBox(..) | ty::TyRef(..) =>
|
||||
true,
|
||||
ty::TyEnum(def_id, _) | ty::TyStruct(def_id, _) =>
|
||||
tcx.has_attr(def_id, "fundamental"),
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) =>
|
||||
def.is_fundamental(),
|
||||
ty::TyTrait(ref data) =>
|
||||
tcx.has_attr(data.principal_def_id(), "fundamental"),
|
||||
_ =>
|
||||
|
|
@ -316,9 +316,9 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
infer_is_local.0
|
||||
}
|
||||
|
||||
ty::TyEnum(def_id, _) |
|
||||
ty::TyStruct(def_id, _) => {
|
||||
def_id.krate == ast::LOCAL_CRATE
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) => {
|
||||
def.did.krate == ast::LOCAL_CRATE
|
||||
}
|
||||
|
||||
ty::TyBox(_) => { // Box<T>
|
||||
|
|
|
|||
|
|
@ -1721,21 +1721,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ok_if(substs.upvar_tys.clone())
|
||||
}
|
||||
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let types: Vec<Ty> =
|
||||
self.tcx().struct_fields(def_id, substs).iter()
|
||||
.map(|f| f.mt.ty)
|
||||
.collect();
|
||||
nominal(bound, types)
|
||||
}
|
||||
|
||||
ty::TyEnum(def_id, substs) => {
|
||||
let types: Vec<Ty> =
|
||||
self.tcx().substd_enum_variants(def_id, substs)
|
||||
.iter()
|
||||
.flat_map(|variant| &variant.args)
|
||||
.cloned()
|
||||
.collect();
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||
let types: Vec<Ty> = def.all_fields().map(|f| {
|
||||
f.ty(self.tcx(), substs)
|
||||
}).collect();
|
||||
nominal(bound, types)
|
||||
}
|
||||
|
||||
|
|
@ -1861,25 +1850,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
// for `PhantomData<T>`, we pass `T`
|
||||
ty::TyStruct(def_id, substs)
|
||||
if Some(def_id) == self.tcx().lang_items.phantom_data() =>
|
||||
{
|
||||
ty::TyStruct(def, substs) if def.is_phantom_data() => {
|
||||
substs.types.get_slice(TypeSpace).to_vec()
|
||||
}
|
||||
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
self.tcx().struct_fields(def_id, substs)
|
||||
.iter()
|
||||
.map(|f| f.mt.ty)
|
||||
.collect()
|
||||
}
|
||||
|
||||
ty::TyEnum(def_id, substs) => {
|
||||
self.tcx().substd_enum_variants(def_id, substs)
|
||||
.iter()
|
||||
.flat_map(|variant| &variant.args)
|
||||
.map(|&ty| ty)
|
||||
.collect()
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||
def.all_fields()
|
||||
.map(|f| f.ty(self.tcx(), substs))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2523,10 +2501,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
(&ty::TyStruct(def_id, substs_a), &ty::TyStruct(_, substs_b)) => {
|
||||
let fields = tcx.lookup_struct_fields(def_id).iter().map(|f| {
|
||||
tcx.lookup_field_type_unsubstituted(def_id, f.id)
|
||||
}).collect::<Vec<_>>();
|
||||
(&ty::TyStruct(def, substs_a), &ty::TyStruct(_, substs_b)) => {
|
||||
let fields = def
|
||||
.all_fields()
|
||||
.map(|f| f.unsubst_ty())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// The last field of the structure has to exist and contain type parameters.
|
||||
let field = if let Some(&field) = fields.last() {
|
||||
|
|
@ -2572,7 +2551,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let param_b = *substs_b.types.get(TypeSpace, i);
|
||||
new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
|
||||
}
|
||||
let new_struct = tcx.mk_struct(def_id, tcx.mk_substs(new_substs));
|
||||
let new_struct = tcx.mk_struct(def, tcx.mk_substs(new_substs));
|
||||
let origin = infer::Misc(obligation.cause.span);
|
||||
if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
|
||||
return Err(Unimplemented);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -275,15 +275,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Field<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Field<'tcx> {
|
||||
ty::Field {
|
||||
name: self.name,
|
||||
mt: self.mt.fold_with(folder),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Region {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
|
||||
folder.fold_region(*self)
|
||||
|
|
|
|||
|
|
@ -485,11 +485,11 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
|
|||
Ok(a)
|
||||
}
|
||||
|
||||
(&ty::TyEnum(a_id, a_substs), &ty::TyEnum(b_id, b_substs))
|
||||
if a_id == b_id =>
|
||||
(&ty::TyEnum(a_def, a_substs), &ty::TyEnum(b_def, b_substs))
|
||||
if a_def == b_def =>
|
||||
{
|
||||
let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
|
||||
Ok(tcx.mk_enum(a_id, tcx.mk_substs(substs)))
|
||||
let substs = try!(relate_item_substs(relation, a_def.did, a_substs, b_substs));
|
||||
Ok(tcx.mk_enum(a_def, tcx.mk_substs(substs)))
|
||||
}
|
||||
|
||||
(&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) =>
|
||||
|
|
@ -499,11 +499,11 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
|
|||
Ok(tcx.mk_trait(principal, bounds))
|
||||
}
|
||||
|
||||
(&ty::TyStruct(a_id, a_substs), &ty::TyStruct(b_id, b_substs))
|
||||
if a_id == b_id =>
|
||||
(&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs))
|
||||
if a_def == b_def =>
|
||||
{
|
||||
let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
|
||||
Ok(tcx.mk_struct(a_id, tcx.mk_substs(substs)))
|
||||
let substs = try!(relate_item_substs(relation, a_def.did, a_substs, b_substs));
|
||||
Ok(tcx.mk_struct(a_def, tcx.mk_substs(substs)))
|
||||
}
|
||||
|
||||
(&ty::TyClosure(a_id, ref a_substs),
|
||||
|
|
|
|||
|
|
@ -366,6 +366,14 @@ impl<'tcx> fmt::Debug for ty::TraitDef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
ty::tls::with(|tcx| {
|
||||
write!(f, "{}", tcx.item_path_str(self.did))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ty::BoundRegion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if verbose() {
|
||||
|
|
@ -648,14 +656,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
|
|||
TyInfer(infer_ty) => write!(f, "{}", infer_ty),
|
||||
TyError => write!(f, "[type error]"),
|
||||
TyParam(ref param_ty) => write!(f, "{}", param_ty),
|
||||
TyEnum(did, substs) | TyStruct(did, substs) => {
|
||||
TyEnum(def, substs) | TyStruct(def, substs) => {
|
||||
ty::tls::with(|tcx| {
|
||||
if did.krate == ast::LOCAL_CRATE &&
|
||||
!tcx.tcache.borrow().contains_key(&did) {
|
||||
write!(f, "{}<..>", tcx.item_path_str(did))
|
||||
if def.did.krate == ast::LOCAL_CRATE &&
|
||||
!tcx.tcache.borrow().contains_key(&def.did) {
|
||||
write!(f, "{}<..>", tcx.item_path_str(def.did))
|
||||
} else {
|
||||
parameterized(f, substs, did, &[],
|
||||
|tcx| tcx.lookup_item_type(did).generics)
|
||||
parameterized(f, substs, def.did, &[],
|
||||
|tcx| tcx.lookup_item_type(def.did).generics)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue