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);
|
||||
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,9 +625,9 @@ fn encode_provided_source(rbml_w: &mut Encoder,
|
|||
}
|
||||
|
||||
/* Returns an index of items in this class */
|
||||
fn encode_info_for_struct(ecx: &EncodeContext,
|
||||
fn encode_info_for_struct<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||
rbml_w: &mut Encoder,
|
||||
fields: &[ty::FieldTy],
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
global_index: &mut Vec<entry<i64>>)
|
||||
-> Vec<entry<i64>> {
|
||||
/* Each class has its own index, since different classes
|
||||
|
@ -640,9 +635,9 @@ fn encode_info_for_struct(ecx: &EncodeContext,
|
|||
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,11 +694,20 @@ 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)
|
||||
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);
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
} 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,
|
||||
|
@ -708,27 +717,13 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
|||
with_expr.span,
|
||||
"with expression doesn't evaluate to a struct");
|
||||
}
|
||||
assert!(self.tcx().sess.has_errors());
|
||||
vec!()
|
||||
}
|
||||
};
|
||||
|
||||
// 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,24 +1850,13 @@ 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)
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -746,8 +746,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
|||
}
|
||||
LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
|
||||
match lp_base.to_type().sty {
|
||||
ty::TyStruct(def_id, _) | ty::TyEnum(def_id, _) => {
|
||||
if self.tcx().has_dtor(def_id) {
|
||||
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor(self.tcx()) => {
|
||||
// In the case where the owner implements drop, then
|
||||
// the path must be initialized to prevent a case of
|
||||
// partial reinitialization
|
||||
|
@ -763,7 +762,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
|||
false
|
||||
});
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
|
|
@ -438,11 +438,10 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
(&ty::TyStruct(def_id, ref _substs), None) => {
|
||||
let fields = tcx.lookup_struct_fields(def_id);
|
||||
(&ty::TyStruct(def, _), None) => {
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
for f in &fields {
|
||||
for f in &def.struct_variant().fields {
|
||||
if f.name == ast_name {
|
||||
continue;
|
||||
}
|
||||
|
@ -451,7 +450,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
|
|||
}
|
||||
}
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
for (i, _f) in fields.iter().enumerate() {
|
||||
for (i, _f) in def.struct_variant().fields.iter().enumerate() {
|
||||
if i == tuple_idx {
|
||||
continue
|
||||
}
|
||||
|
@ -462,35 +461,26 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
(&ty::TyEnum(enum_def_id, substs), ref enum_variant_info) => {
|
||||
let variant_info = {
|
||||
let mut variants = tcx.substd_enum_variants(enum_def_id, substs);
|
||||
match *enum_variant_info {
|
||||
Some((variant_def_id, ref _lp2)) =>
|
||||
variants.iter()
|
||||
.find(|variant| variant.id == variant_def_id)
|
||||
.expect("enum_variant_with_id(): no variant exists with that ID")
|
||||
.clone(),
|
||||
(&ty::TyEnum(def, _), ref enum_variant_info) => {
|
||||
let variant = match *enum_variant_info {
|
||||
Some((vid, ref _lp2)) => def.variant_with_id(vid),
|
||||
None => {
|
||||
assert_eq!(variants.len(), 1);
|
||||
variants.pop().unwrap()
|
||||
}
|
||||
assert!(def.is_univariant());
|
||||
&def.variants[0]
|
||||
}
|
||||
};
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
let variant_arg_names = variant_info.arg_names.as_ref().unwrap();
|
||||
for &variant_arg_name in variant_arg_names {
|
||||
if variant_arg_name == ast_name {
|
||||
for field in &variant.fields {
|
||||
if field.name == ast_name {
|
||||
continue;
|
||||
}
|
||||
let field_name = mc::NamedField(variant_arg_name);
|
||||
add_fragment_sibling_local(field_name, Some(variant_info.id));
|
||||
let field_name = mc::NamedField(field.name);
|
||||
add_fragment_sibling_local(field_name, Some(variant.did));
|
||||
}
|
||||
}
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
let variant_arg_types = &variant_info.args;
|
||||
for (i, _variant_arg_ty) in variant_arg_types.iter().enumerate() {
|
||||
for (i, _f) in variant.fields.iter().enumerate() {
|
||||
if tuple_idx == i {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -179,8 +179,8 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
|||
mc::cat_interior(ref b, mc::InteriorField(_)) |
|
||||
mc::cat_interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
|
||||
match b.ty.sty {
|
||||
ty::TyStruct(did, _) | ty::TyEnum(did, _) => {
|
||||
if bccx.tcx.has_dtor(did) {
|
||||
ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
|
||||
if def.has_dtor(bccx.tcx) {
|
||||
Some(cmt.clone())
|
||||
} else {
|
||||
check_and_get_illegal_move_origin(bccx, b)
|
||||
|
|
|
@ -136,8 +136,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
|||
mc::cat_downcast(ref b, _) |
|
||||
mc::cat_interior(ref b, mc::InteriorField(_)) => {
|
||||
match b.ty.sty {
|
||||
ty::TyStruct(did, _) |
|
||||
ty::TyEnum(did, _) if bccx.tcx.has_dtor(did) => {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor(bccx.tcx) => {
|
||||
bccx.span_err(
|
||||
move_from.span,
|
||||
&format!("cannot move out of type `{}`, \
|
||||
|
|
74
src/librustc_data_structures/ivar.rs
Normal file
74
src/librustc_data_structures/ivar.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt;
|
||||
use std::cell::Cell;
|
||||
|
||||
/// A write-once variable. When constructed, it is empty, and
|
||||
/// can only be set once.
|
||||
///
|
||||
/// Ivars ensure that data that can only be initialised once. A full
|
||||
/// implementation is used for concurrency and blocks on a read of an
|
||||
/// unfulfilled value. This implementation is more minimal and panics
|
||||
/// if you attempt to read the value before it has been set. It is also
|
||||
/// not `Sync`, but may be extended in the future to be usable as a true
|
||||
/// concurrency type.
|
||||
///
|
||||
/// The `T: Copy` bound is not strictly needed, but it is required by
|
||||
/// Cell (so removing it would require using UnsafeCell), and it
|
||||
/// suffices for the current purposes.
|
||||
#[derive(PartialEq)]
|
||||
pub struct Ivar<T: Copy> {
|
||||
data: Cell<Option<T>>
|
||||
}
|
||||
|
||||
impl<T: Copy> Ivar<T> {
|
||||
pub fn new() -> Ivar<T> {
|
||||
Ivar {
|
||||
data: Cell::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<T> {
|
||||
self.data.get()
|
||||
}
|
||||
|
||||
pub fn fulfill(&self, value: T) {
|
||||
assert!(self.data.get().is_none(),
|
||||
"Value already set!");
|
||||
self.data.set(Some(value));
|
||||
}
|
||||
|
||||
pub fn is_fulfilled(&self) -> bool {
|
||||
self.data.get().is_some()
|
||||
}
|
||||
|
||||
pub fn unwrap(&self) -> T {
|
||||
self.get().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy+fmt::Debug> fmt::Debug for Ivar<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.get() {
|
||||
Some(val) => write!(f, "Ivar({:?})", val),
|
||||
None => f.write_str("Ivar(<unfulfilled>)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> Clone for Ivar<T> {
|
||||
fn clone(&self) -> Ivar<T> {
|
||||
match self.get() {
|
||||
Some(val) => Ivar { data: Cell::new(Some(val)) },
|
||||
None => Ivar::new()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,4 +36,5 @@ extern crate serialize as rustc_serialize; // used by deriving
|
|||
pub mod snapshot_vec;
|
||||
pub mod graph;
|
||||
pub mod bitvec;
|
||||
pub mod ivar;
|
||||
pub mod unify;
|
||||
|
|
|
@ -45,7 +45,6 @@ use std::collections::{HashSet, BitSet};
|
|||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::{cmp, slice};
|
||||
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::{abi, ast};
|
||||
use syntax::ast_util::{self, is_shift_binop, local_def};
|
||||
|
@ -413,18 +412,23 @@ enum FfiResult {
|
|||
/// to function pointers and references, but could be
|
||||
/// expanded to cover NonZero raw pointers and newtypes.
|
||||
/// FIXME: This duplicates code in trans.
|
||||
fn is_repr_nullable_ptr<'tcx>(variants: &Vec<Rc<ty::VariantInfo<'tcx>>>) -> bool {
|
||||
if variants.len() == 2 {
|
||||
let mut data_idx = 0;
|
||||
fn is_repr_nullable_ptr<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def: ty::AdtDef<'tcx>,
|
||||
substs: &Substs<'tcx>)
|
||||
-> bool {
|
||||
if def.variants.len() == 2 {
|
||||
let data_idx;
|
||||
|
||||
if variants[0].args.is_empty() {
|
||||
if def.variants[0].fields.is_empty() {
|
||||
data_idx = 1;
|
||||
} else if !variants[1].args.is_empty() {
|
||||
} else if def.variants[1].fields.is_empty() {
|
||||
data_idx = 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if variants[data_idx].args.len() == 1 {
|
||||
match variants[data_idx].args[0].sty {
|
||||
if def.variants[data_idx].fields.len() == 1 {
|
||||
match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
|
||||
ty::TyBareFn(None, _) => { return true; }
|
||||
ty::TyRef(..) => { return true; }
|
||||
_ => { }
|
||||
|
@ -463,8 +467,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
match ty.sty {
|
||||
ty::TyStruct(did, substs) => {
|
||||
if !cx.lookup_repr_hints(did).contains(&attr::ReprExtern) {
|
||||
ty::TyStruct(def, substs) => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
return FfiUnsafe(
|
||||
"found struct without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
|
@ -474,39 +478,36 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
// We can't completely trust repr(C) markings; make sure the
|
||||
// fields are actually safe.
|
||||
let fields = cx.struct_fields(did, substs);
|
||||
|
||||
if fields.is_empty() {
|
||||
if def.struct_variant().fields.is_empty() {
|
||||
return FfiUnsafe(
|
||||
"found zero-size struct in foreign module, consider \
|
||||
adding a member to this struct");
|
||||
}
|
||||
|
||||
for field in fields {
|
||||
let field_ty = infer::normalize_associated_type(cx, &field.mt.ty);
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = infer::normalize_associated_type(cx, &field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadStruct(did, s); }
|
||||
FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
ty::TyEnum(did, substs) => {
|
||||
let variants = cx.substd_enum_variants(did, substs);
|
||||
if variants.is_empty() {
|
||||
ty::TyEnum(def, substs) => {
|
||||
if def.variants.is_empty() {
|
||||
// Empty enums are okay... although sort of useless.
|
||||
return FfiSafe
|
||||
}
|
||||
|
||||
// Check for a repr() attribute to specify the size of the
|
||||
// discriminant.
|
||||
let repr_hints = cx.lookup_repr_hints(did);
|
||||
let repr_hints = cx.lookup_repr_hints(def.did);
|
||||
match &**repr_hints {
|
||||
[] => {
|
||||
// Special-case types like `Option<extern fn()>`.
|
||||
if !is_repr_nullable_ptr(&variants) {
|
||||
if !is_repr_nullable_ptr(cx, def, substs) {
|
||||
return FfiUnsafe(
|
||||
"found enum without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
|
@ -537,14 +538,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Check the contained variants.
|
||||
for variant in variants {
|
||||
for arg in &variant.args {
|
||||
let arg = infer::normalize_associated_type(cx, arg);
|
||||
for variant in &def.variants {
|
||||
for field in &variant.fields {
|
||||
let arg = infer::normalize_associated_type(cx, &field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, arg);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadEnum(did, s); }
|
||||
FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -842,8 +843,8 @@ impl LintPass for RawPointerDerive {
|
|||
}
|
||||
|
||||
match cx.tcx.node_id_to_type(item.id).sty {
|
||||
ty::TyEnum(did, _) => did,
|
||||
ty::TyStruct(did, _) => did,
|
||||
ty::TyEnum(def, _) => def.did,
|
||||
ty::TyStruct(def, _) => def.did,
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
|
@ -989,16 +990,16 @@ impl LintPass for UnusedResults {
|
|||
let warned = match t.sty {
|
||||
ty::TyTuple(ref tys) if tys.is_empty() => return,
|
||||
ty::TyBool => return,
|
||||
ty::TyStruct(did, _) |
|
||||
ty::TyEnum(did, _) => {
|
||||
if ast_util::is_local(did) {
|
||||
if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) => {
|
||||
if ast_util::is_local(def.did) {
|
||||
if let ast_map::NodeItem(it) = cx.tcx.map.get(def.did.node) {
|
||||
check_must_use(cx, &it.attrs, s.span)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
|
||||
let attrs = csearch::get_item_attrs(&cx.sess().cstore, def.did);
|
||||
check_must_use(cx, &attrs[..], s.span)
|
||||
}
|
||||
}
|
||||
|
@ -1956,14 +1957,14 @@ impl LintPass for MissingCopyImplementations {
|
|||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
cx.tcx.mk_struct(local_def(item.id),
|
||||
cx.tcx.mk_struct(cx.tcx.lookup_adt_def(local_def(item.id)),
|
||||
cx.tcx.mk_substs(Substs::empty()))
|
||||
}
|
||||
ast::ItemEnum(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
cx.tcx.mk_enum(local_def(item.id),
|
||||
cx.tcx.mk_enum(cx.tcx.lookup_adt_def(local_def(item.id)),
|
||||
cx.tcx.mk_substs(Substs::empty()))
|
||||
}
|
||||
_ => return,
|
||||
|
@ -2575,9 +2576,9 @@ impl LintPass for DropWithReprExtern {
|
|||
};
|
||||
|
||||
match dtor_self_type.sty {
|
||||
ty::TyEnum(self_type_did, _) |
|
||||
ty::TyStruct(self_type_did, _) |
|
||||
ty::TyClosure(self_type_did, _) => {
|
||||
ty::TyEnum(self_type_def, _) |
|
||||
ty::TyStruct(self_type_def, _) => {
|
||||
let self_type_did = self_type_def.did;
|
||||
let hints = ctx.tcx.lookup_repr_hints(self_type_did);
|
||||
if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
|
||||
ctx.tcx.ty_dtor(self_type_did).has_drop_flag() {
|
||||
|
|
|
@ -34,7 +34,6 @@ use self::FieldName::*;
|
|||
use std::mem::replace;
|
||||
|
||||
use rustc::ast_map;
|
||||
use rustc::metadata::csearch;
|
||||
use rustc::middle::def;
|
||||
use rustc::middle::privacy::ImportUse::*;
|
||||
use rustc::middle::privacy::LastPrivate::*;
|
||||
|
@ -688,28 +687,26 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
|||
// Checks that a field is in scope.
|
||||
fn check_field(&mut self,
|
||||
span: Span,
|
||||
id: ast::DefId,
|
||||
def: ty::AdtDef<'tcx>,
|
||||
v: ty::VariantDef<'tcx>,
|
||||
name: FieldName) {
|
||||
let fields = self.tcx.lookup_struct_fields(id);
|
||||
let field = match name {
|
||||
NamedField(f_name) => {
|
||||
debug!("privacy - check named field {} in struct {:?}", f_name, id);
|
||||
fields.iter().find(|f| f.name == f_name).unwrap()
|
||||
debug!("privacy - check named field {} in struct {:?}", f_name, def);
|
||||
v.field_named(f_name)
|
||||
}
|
||||
UnnamedField(idx) => &fields[idx]
|
||||
UnnamedField(idx) => &v.fields[idx]
|
||||
};
|
||||
if field.vis == ast::Public ||
|
||||
(is_local(field.id) && self.private_accessible(field.id.node)) {
|
||||
(is_local(field.did) && self.private_accessible(field.did.node)) {
|
||||
return
|
||||
}
|
||||
|
||||
let struct_type = self.tcx.lookup_item_type(id).ty;
|
||||
let struct_desc = match struct_type.sty {
|
||||
ty::TyStruct(_, _) =>
|
||||
format!("struct `{}`", self.tcx.item_path_str(id)),
|
||||
let struct_desc = match def.adt_kind() {
|
||||
ty::AdtKind::Struct =>
|
||||
format!("struct `{}`", self.tcx.item_path_str(def.did)),
|
||||
// struct variant fields have inherited visibility
|
||||
ty::TyEnum(..) => return,
|
||||
_ => self.tcx.sess.span_bug(span, "can't find struct for field")
|
||||
ty::AdtKind::Enum => return
|
||||
};
|
||||
let msg = match name {
|
||||
NamedField(name) => format!("field `{}` of {} is private",
|
||||
|
@ -883,13 +880,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
|||
fn visit_expr(&mut self, expr: &ast::Expr) {
|
||||
match expr.node {
|
||||
ast::ExprField(ref base, ident) => {
|
||||
if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty {
|
||||
self.check_field(expr.span, id, NamedField(ident.node.name));
|
||||
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
|
||||
self.check_field(expr.span,
|
||||
def,
|
||||
def.struct_variant(),
|
||||
NamedField(ident.node.name));
|
||||
}
|
||||
}
|
||||
ast::ExprTupField(ref base, idx) => {
|
||||
if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty {
|
||||
self.check_field(expr.span, id, UnnamedField(idx.node));
|
||||
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
|
||||
self.check_field(expr.span,
|
||||
def,
|
||||
def.struct_variant(),
|
||||
UnnamedField(idx.node));
|
||||
}
|
||||
}
|
||||
ast::ExprMethodCall(ident, _, _) => {
|
||||
|
@ -898,67 +901,36 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
|||
debug!("(privacy checking) checking impl method");
|
||||
self.check_method(expr.span, method.def_id, ident.node.name);
|
||||
}
|
||||
ast::ExprStruct(_, ref fields, _) => {
|
||||
match self.tcx.expr_ty(expr).sty {
|
||||
ty::TyStruct(ctor_id, _) => {
|
||||
ast::ExprStruct(..) => {
|
||||
let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
|
||||
let variant = adt.variant_of_def(self.tcx.resolve_expr(expr));
|
||||
// RFC 736: ensure all unmentioned fields are visible.
|
||||
// Rather than computing the set of unmentioned fields
|
||||
// (i.e. `all_fields - fields`), just check them all.
|
||||
let all_fields = self.tcx.lookup_struct_fields(ctor_id);
|
||||
for field in all_fields {
|
||||
self.check_field(expr.span, ctor_id,
|
||||
NamedField(field.name));
|
||||
}
|
||||
}
|
||||
ty::TyEnum(_, _) => {
|
||||
match self.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
|
||||
def::DefVariant(_, variant_id, _) => {
|
||||
for field in fields {
|
||||
self.check_field(expr.span, variant_id,
|
||||
NamedField(field.ident.node.name));
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(expr.span,
|
||||
"resolve didn't \
|
||||
map enum struct \
|
||||
constructor to a \
|
||||
variant def"),
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(expr.span, "struct expr \
|
||||
didn't have \
|
||||
struct type?!"),
|
||||
for field in &variant.fields {
|
||||
self.check_field(expr.span, adt, variant, NamedField(field.name));
|
||||
}
|
||||
}
|
||||
ast::ExprPath(..) => {
|
||||
let guard = |did: ast::DefId| {
|
||||
let fields = self.tcx.lookup_struct_fields(did);
|
||||
let any_priv = fields.iter().any(|f| {
|
||||
|
||||
if let def::DefStruct(_) = self.tcx.resolve_expr(expr) {
|
||||
let expr_ty = self.tcx.expr_ty(expr);
|
||||
let def = match expr_ty.sty {
|
||||
ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
|
||||
output: ty::FnConverging(ty), ..
|
||||
}), ..}) => ty,
|
||||
_ => expr_ty
|
||||
}.ty_adt_def().unwrap();
|
||||
let any_priv = def.struct_variant().fields.iter().any(|f| {
|
||||
f.vis != ast::Public && (
|
||||
!is_local(f.id) ||
|
||||
!self.private_accessible(f.id.node))
|
||||
!is_local(f.did) ||
|
||||
!self.private_accessible(f.did.node))
|
||||
});
|
||||
if any_priv {
|
||||
self.tcx.sess.span_err(expr.span,
|
||||
"cannot invoke tuple struct constructor \
|
||||
with private fields");
|
||||
}
|
||||
};
|
||||
match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
|
||||
Some(def::DefStruct(did)) => {
|
||||
guard(if is_local(did) {
|
||||
local_def(self.tcx.map.get_parent(did.node))
|
||||
} else {
|
||||
// "tuple structs" with zero fields (such as
|
||||
// `pub struct Foo;`) don't have a ctor_id, hence
|
||||
// the unwrap_or to the same struct id.
|
||||
let maybe_did =
|
||||
csearch::get_tuple_struct_definition_if_ctor(
|
||||
&self.tcx.sess.cstore, did);
|
||||
maybe_did.unwrap_or(did)
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -976,44 +948,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
|||
|
||||
match pattern.node {
|
||||
ast::PatStruct(_, ref fields, _) => {
|
||||
match self.tcx.pat_ty(pattern).sty {
|
||||
ty::TyStruct(id, _) => {
|
||||
let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
|
||||
let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def();
|
||||
let variant = adt.variant_of_def(def);
|
||||
for field in fields {
|
||||
self.check_field(pattern.span, id,
|
||||
self.check_field(pattern.span, adt, variant,
|
||||
NamedField(field.node.ident.name));
|
||||
}
|
||||
}
|
||||
ty::TyEnum(_, _) => {
|
||||
match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
|
||||
Some(def::DefVariant(_, variant_id, _)) => {
|
||||
for field in fields {
|
||||
self.check_field(pattern.span, variant_id,
|
||||
NamedField(field.node.ident.name));
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(pattern.span,
|
||||
"resolve didn't \
|
||||
map enum struct \
|
||||
pattern to a \
|
||||
variant def"),
|
||||
}
|
||||
}
|
||||
_ => self.tcx.sess.span_bug(pattern.span,
|
||||
"struct pattern didn't have \
|
||||
struct type?!"),
|
||||
}
|
||||
}
|
||||
|
||||
// Patterns which bind no fields are allowable (the path is check
|
||||
// elsewhere).
|
||||
ast::PatEnum(_, Some(ref fields)) => {
|
||||
match self.tcx.pat_ty(pattern).sty {
|
||||
ty::TyStruct(id, _) => {
|
||||
ty::TyStruct(def, _) => {
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
if let ast::PatWild(..) = field.node {
|
||||
continue
|
||||
}
|
||||
self.check_field(field.span, id, UnnamedField(i));
|
||||
self.check_field(field.span,
|
||||
def,
|
||||
def.struct_variant(),
|
||||
UnnamedField(i));
|
||||
}
|
||||
}
|
||||
ty::TyEnum(..) => {
|
||||
|
|
|
@ -791,9 +791,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
|||
crate) building type and value for {}",
|
||||
final_ident);
|
||||
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
||||
let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
|
||||
f.name
|
||||
}).collect::<Vec<_>>();
|
||||
let fields = csearch::get_struct_field_names(&self.session.cstore, def_id);
|
||||
|
||||
if fields.is_empty() {
|
||||
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
|
||||
|
|
|
@ -742,6 +742,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
ex: &ast::Expr,
|
||||
path: &ast::Path,
|
||||
fields: &Vec<ast::Field>,
|
||||
variant: ty::VariantDef,
|
||||
base: &Option<P<ast::Expr>>) {
|
||||
if generated_code(path.span) {
|
||||
return
|
||||
|
@ -756,7 +757,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
Some(struct_lit_data.span),
|
||||
struct_lit_data.ref_id,
|
||||
struct_lit_data.scope);
|
||||
let struct_def = struct_lit_data.ref_id;
|
||||
let scope = self.save_ctxt.enclosing_scope(ex.id);
|
||||
|
||||
for field in fields {
|
||||
|
@ -765,7 +765,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
}
|
||||
|
||||
let field_data = self.save_ctxt.get_field_ref_data(field,
|
||||
struct_def,
|
||||
variant,
|
||||
scope);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
field.ident.span,
|
||||
|
@ -804,45 +804,26 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
|||
match p.node {
|
||||
ast::PatStruct(ref path, ref fields, _) => {
|
||||
visit::walk_path(self, path);
|
||||
let adt = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap();
|
||||
let def = self.tcx.def_map.borrow()[&p.id].full_def();
|
||||
let variant = adt.variant_of_def(def);
|
||||
|
||||
let def = self.tcx.def_map.borrow().get(&p.id).unwrap().full_def();
|
||||
let struct_def = match def {
|
||||
def::DefConst(..) | def::DefAssociatedConst(..) => None,
|
||||
def::DefVariant(_, variant_id, _) => Some(variant_id),
|
||||
_ => {
|
||||
match self.tcx.node_id_to_type(p.id).ty_to_def_id() {
|
||||
None => {
|
||||
self.sess.span_bug(p.span,
|
||||
&format!("Could not find struct_def for `{}`",
|
||||
self.span.snippet(p.span)));
|
||||
}
|
||||
Some(def_id) => Some(def_id),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(struct_def) = struct_def {
|
||||
let struct_fields = self.tcx.lookup_struct_fields(struct_def);
|
||||
for &Spanned { node: ref field, span } in fields {
|
||||
if generated_code(span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let sub_span = self.span.span_for_first_ident(span);
|
||||
for f in &struct_fields {
|
||||
if f.name == field.ident.name {
|
||||
if let Some(f) = variant.find_field_named(field.ident.name) {
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
span,
|
||||
sub_span,
|
||||
f.id,
|
||||
f.did,
|
||||
self.cur_scope);
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.visit_pat(&field.pat);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => visit::walk_pat(self, p)
|
||||
}
|
||||
}
|
||||
|
@ -1091,8 +1072,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
|||
self.process_path(ex.id, path, None);
|
||||
visit::walk_expr(self, ex);
|
||||
}
|
||||
ast::ExprStruct(ref path, ref fields, ref base) =>
|
||||
self.process_struct_lit(ex, path, fields, base),
|
||||
ast::ExprStruct(ref path, ref fields, ref base) => {
|
||||
let adt = self.tcx.expr_ty(ex).ty_adt_def().unwrap();
|
||||
let def = self.tcx.resolve_expr(ex);
|
||||
self.process_struct_lit(ex,
|
||||
path,
|
||||
fields,
|
||||
adt.variant_of_def(def),
|
||||
base)
|
||||
}
|
||||
ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
|
||||
ast::ExprField(ref sub_ex, _) => {
|
||||
if generated_code(sub_ex.span) {
|
||||
|
@ -1119,19 +1107,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
|
|||
|
||||
let ty = &self.tcx.expr_ty_adjusted(&**sub_ex).sty;
|
||||
match *ty {
|
||||
ty::TyStruct(def_id, _) => {
|
||||
let fields = self.tcx.lookup_struct_fields(def_id);
|
||||
for (i, f) in fields.iter().enumerate() {
|
||||
if i == idx.node {
|
||||
ty::TyStruct(def, _) => {
|
||||
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
|
||||
self.fmt.ref_str(recorder::VarRef,
|
||||
ex.span,
|
||||
sub_span,
|
||||
f.id,
|
||||
def.struct_variant().fields[idx.node].did,
|
||||
self.cur_scope);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::TyTuple(_) => {}
|
||||
_ => self.sess.span_bug(ex.span,
|
||||
|
|
|
@ -447,24 +447,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
ast::ExprField(ref sub_ex, ident) => {
|
||||
let ty = &self.tcx.expr_ty_adjusted(&sub_ex).sty;
|
||||
match *ty {
|
||||
ty::TyStruct(def_id, _) => {
|
||||
let fields = self.tcx.lookup_struct_fields(def_id);
|
||||
for f in &fields {
|
||||
if f.name == ident.node.name {
|
||||
ty::TyStruct(def, _) => {
|
||||
let f = def.struct_variant().field_named(ident.node.name);
|
||||
let sub_span = self.span_utils.span_for_last_ident(expr.span);
|
||||
return Some(Data::VariableRefData(VariableRefData {
|
||||
name: ident.node.to_string(),
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(expr.id),
|
||||
ref_id: f.id,
|
||||
ref_id: f.did,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.span_bug(expr.span,
|
||||
&format!("Couldn't find field {} on {:?}",
|
||||
ident.node, ty))
|
||||
}
|
||||
_ => {
|
||||
debug!("Expected struct type, found {:?}", ty);
|
||||
None
|
||||
|
@ -474,12 +466,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
ast::ExprStruct(ref path, _, _) => {
|
||||
let ty = &self.tcx.expr_ty_adjusted(expr).sty;
|
||||
match *ty {
|
||||
ty::TyStruct(def_id, _) => {
|
||||
ty::TyStruct(def, _) => {
|
||||
let sub_span = self.span_utils.span_for_last_ident(path.span);
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
span: sub_span.unwrap(),
|
||||
scope: self.enclosing_scope(expr.id),
|
||||
ref_id: def_id,
|
||||
ref_id: def.did,
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
|
@ -621,28 +613,20 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
|
||||
pub fn get_field_ref_data(&self,
|
||||
field_ref: &ast::Field,
|
||||
struct_id: DefId,
|
||||
variant: ty::VariantDef,
|
||||
parent: NodeId)
|
||||
-> VariableRefData {
|
||||
let fields = self.tcx.lookup_struct_fields(struct_id);
|
||||
let field_name = field_ref.ident.node.to_string();
|
||||
for f in &fields {
|
||||
if f.name == field_ref.ident.node.name {
|
||||
let f = variant.field_named(field_ref.ident.node.name);
|
||||
// We don't really need a sub-span here, but no harm done
|
||||
let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
|
||||
return VariableRefData {
|
||||
name: field_name,
|
||||
VariableRefData {
|
||||
name: field_ref.ident.node.to_string(),
|
||||
span: sub_span.unwrap(),
|
||||
scope: parent,
|
||||
ref_id: f.id,
|
||||
};
|
||||
ref_id: f.did,
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.span_bug(field_ref.span,
|
||||
&format!("Couldn't find field {}", field_name));
|
||||
}
|
||||
|
||||
pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
|
||||
// FIXME
|
||||
unimplemented!();
|
||||
|
|
|
@ -656,7 +656,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
|
||||
match opt_def {
|
||||
Some(def::DefVariant(enum_id, var_id, _)) => {
|
||||
let variant = tcx.enum_variant_with_id(enum_id, var_id);
|
||||
let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
|
||||
Variant(variant.disr_val,
|
||||
adt::represent_node(bcx, cur.id),
|
||||
var_id,
|
||||
|
@ -1186,14 +1186,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
).collect();
|
||||
|
||||
match left_ty.sty {
|
||||
ty::TyStruct(def_id, substs) if !type_is_sized(bcx.tcx(), left_ty) => {
|
||||
ty::TyStruct(def, substs) if !type_is_sized(bcx.tcx(), left_ty) => {
|
||||
// The last field is technically unsized but
|
||||
// since we can only ever match that field behind
|
||||
// a reference we construct a fat ptr here.
|
||||
let fields = bcx.tcx().lookup_struct_fields(def_id);
|
||||
let unsized_ty = fields.iter().last().map(|field| {
|
||||
let fty = bcx.tcx().lookup_field_type(def_id, field.id, substs);
|
||||
monomorphize::normalize_associated_type(bcx.tcx(), &fty)
|
||||
let unsized_ty = def.struct_variant().fields.last().map(|field| {
|
||||
monomorphize::field_ty(bcx.tcx(), substs, field)
|
||||
}).unwrap();
|
||||
let llty = type_of::type_of(bcx.ccx(), unsized_ty);
|
||||
let scratch = alloca_no_lifetime(bcx, llty, "__struct_field_fat_ptr");
|
||||
|
@ -1833,7 +1831,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
match opt_def {
|
||||
Some(def::DefVariant(enum_id, var_id, _)) => {
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
let vinfo = ccx.tcx().enum_variant_with_id(enum_id, var_id);
|
||||
let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
|
||||
let args = extract_variant_args(bcx,
|
||||
&*repr,
|
||||
vinfo.disr_val,
|
||||
|
@ -1877,21 +1875,20 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
let tcx = bcx.tcx();
|
||||
let pat_ty = node_id_type(bcx, pat.id);
|
||||
let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
|
||||
expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
|
||||
let pat_v = VariantInfo::of_node(tcx, pat_ty, pat.id);
|
||||
for f in fields {
|
||||
let ix = tcx.field_idx_strict(f.node.ident.name, field_tys);
|
||||
let name = f.node.ident.name;
|
||||
let fldptr = adt::trans_field_ptr(
|
||||
bcx,
|
||||
&*pat_repr,
|
||||
val.val,
|
||||
discr,
|
||||
ix);
|
||||
pat_v.discr,
|
||||
pat_v.field_index(name));
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
&*f.node.pat,
|
||||
MatchInput::from_val(fldptr),
|
||||
cleanup_scope);
|
||||
}
|
||||
})
|
||||
}
|
||||
ast::PatTup(ref elems) => {
|
||||
let repr = adt::represent_node(bcx, pat.id);
|
||||
|
|
|
@ -245,14 +245,12 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ty::TyTuple(ref elems) => {
|
||||
Univariant(mk_struct(cx, &elems[..], false, t), 0)
|
||||
}
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let fields = cx.tcx().lookup_struct_fields(def_id);
|
||||
let mut ftys = fields.iter().map(|field| {
|
||||
let fty = cx.tcx().lookup_field_type(def_id, field.id, substs);
|
||||
monomorphize::normalize_associated_type(cx.tcx(), &fty)
|
||||
ty::TyStruct(def, substs) => {
|
||||
let mut ftys = def.struct_variant().fields.iter().map(|field| {
|
||||
monomorphize::field_ty(cx.tcx(), substs, field)
|
||||
}).collect::<Vec<_>>();
|
||||
let packed = cx.tcx().lookup_packed(def_id);
|
||||
let dtor = cx.tcx().ty_dtor(def_id).has_drop_flag();
|
||||
let packed = cx.tcx().lookup_packed(def.did);
|
||||
let dtor = cx.tcx().ty_dtor(def.did).has_drop_flag();
|
||||
if dtor {
|
||||
ftys.push(cx.tcx().dtor_type());
|
||||
}
|
||||
|
@ -262,12 +260,12 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ty::TyClosure(_, ref substs) => {
|
||||
Univariant(mk_struct(cx, &substs.upvar_tys, false, t), 0)
|
||||
}
|
||||
ty::TyEnum(def_id, substs) => {
|
||||
let cases = get_cases(cx.tcx(), def_id, substs);
|
||||
let hint = *cx.tcx().lookup_repr_hints(def_id).get(0)
|
||||
ty::TyEnum(def, substs) => {
|
||||
let cases = get_cases(cx.tcx(), def, substs);
|
||||
let hint = *cx.tcx().lookup_repr_hints(def.did).get(0)
|
||||
.unwrap_or(&attr::ReprAny);
|
||||
|
||||
let dtor = cx.tcx().ty_dtor(def_id).has_drop_flag();
|
||||
let dtor = cx.tcx().ty_dtor(def.did).has_drop_flag();
|
||||
|
||||
if cases.is_empty() {
|
||||
// Uninhabitable; represent as unit
|
||||
|
@ -296,7 +294,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as Disr)) {
|
||||
cx.sess().bug(&format!("non-C-like enum {} with specified \
|
||||
discriminants",
|
||||
cx.tcx().item_path_str(def_id)));
|
||||
cx.tcx().item_path_str(def.did)));
|
||||
}
|
||||
|
||||
if cases.len() == 1 {
|
||||
|
@ -443,11 +441,11 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
ty::TyBareFn(..) => Some(path),
|
||||
|
||||
// Is this the NonZero lang item wrapping a pointer or integer type?
|
||||
ty::TyStruct(did, substs) if Some(did) == tcx.lang_items.non_zero() => {
|
||||
let nonzero_fields = tcx.lookup_struct_fields(did);
|
||||
ty::TyStruct(def, substs) if Some(def.did) == tcx.lang_items.non_zero() => {
|
||||
let nonzero_fields = &def.struct_variant().fields;
|
||||
assert_eq!(nonzero_fields.len(), 1);
|
||||
let nonzero_field = tcx.lookup_field_type(did, nonzero_fields[0].id, substs);
|
||||
match nonzero_field.sty {
|
||||
let field_ty = monomorphize::field_ty(tcx, substs, &nonzero_fields[0]);
|
||||
match field_ty.sty {
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) if !type_is_sized(tcx, ty) => {
|
||||
path.push_all(&[0, FAT_PTR_ADDR]);
|
||||
Some(path)
|
||||
|
@ -462,10 +460,9 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
|
||||
// Perhaps one of the fields of this struct is non-zero
|
||||
// let's recurse and find out
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let fields = tcx.lookup_struct_fields(def_id);
|
||||
for (j, field) in fields.iter().enumerate() {
|
||||
let field_ty = tcx.lookup_field_type(def_id, field.id, substs);
|
||||
ty::TyStruct(def, substs) => {
|
||||
for (j, field) in def.struct_variant().fields.iter().enumerate() {
|
||||
let field_ty = monomorphize::field_ty(tcx, substs, field);
|
||||
if let Some(mut fpath) = find_discr_field_candidate(tcx, field_ty, path.clone()) {
|
||||
fpath.push(j);
|
||||
return Some(fpath);
|
||||
|
@ -530,14 +527,14 @@ impl<'tcx> Case<'tcx> {
|
|||
}
|
||||
|
||||
fn get_cases<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def_id: ast::DefId,
|
||||
adt: ty::AdtDef<'tcx>,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> Vec<Case<'tcx>> {
|
||||
tcx.enum_variants(def_id).iter().map(|vi| {
|
||||
let arg_tys = vi.args.iter().map(|&raw_ty| {
|
||||
monomorphize::apply_param_substs(tcx, substs, &raw_ty)
|
||||
adt.variants.iter().map(|vi| {
|
||||
let field_tys = vi.fields.iter().map(|field| {
|
||||
monomorphize::field_ty(tcx, substs, field)
|
||||
}).collect();
|
||||
Case { discr: vi.disr_val, tys: arg_tys }
|
||||
Case { discr: vi.disr_val, tys: field_tys }
|
||||
}).collect()
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ use trans::cleanup::{self, CleanupMethods, DropHint};
|
|||
use trans::closure;
|
||||
use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral};
|
||||
use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
|
||||
use trans::common::{CrateContext, DropFlagHintsMap, FunctionContext};
|
||||
use trans::common::{Result, NodeIdAndSpan};
|
||||
use trans::common::{CrateContext, DropFlagHintsMap, Field, FunctionContext};
|
||||
use trans::common::{Result, NodeIdAndSpan, VariantInfo};
|
||||
use trans::common::{node_id_type, return_type_is_void};
|
||||
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
|
||||
use trans::common;
|
||||
|
@ -386,7 +386,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
||||
repr: &adt::Repr<'tcx>,
|
||||
av: ValueRef,
|
||||
variant: &ty::VariantInfo<'tcx>,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
substs: &Substs<'tcx>,
|
||||
f: &mut F)
|
||||
-> Block<'blk, 'tcx> where
|
||||
|
@ -396,8 +396,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
let tcx = cx.tcx();
|
||||
let mut cx = cx;
|
||||
|
||||
for (i, &arg) in variant.args.iter().enumerate() {
|
||||
let arg = monomorphize::apply_param_substs(tcx, substs, &arg);
|
||||
for (i, field) in variant.fields.iter().enumerate() {
|
||||
let arg = monomorphize::field_ty(tcx, substs, field);
|
||||
cx = f(cx, adt::trans_field_ptr(cx, repr, av, variant.disr_val, i), arg);
|
||||
}
|
||||
return cx;
|
||||
|
@ -415,9 +415,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
match t.sty {
|
||||
ty::TyStruct(..) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| {
|
||||
for (i, field_ty) in field_tys.iter().enumerate() {
|
||||
let field_ty = field_ty.mt.ty;
|
||||
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
|
||||
for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
|
||||
let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i);
|
||||
|
||||
let val = if common::type_is_sized(cx.tcx(), field_ty) {
|
||||
|
@ -430,7 +429,6 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
};
|
||||
cx = f(cx, val, field_ty);
|
||||
}
|
||||
})
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
|
@ -455,13 +453,12 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
cx = f(cx, llfld_a, *arg);
|
||||
}
|
||||
}
|
||||
ty::TyEnum(tid, substs) => {
|
||||
ty::TyEnum(en, substs) => {
|
||||
let fcx = cx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let variants = ccx.tcx().enum_variants(tid);
|
||||
let n_variants = (*variants).len();
|
||||
let n_variants = en.variants.len();
|
||||
|
||||
// NB: we must hit the discriminant first so that structural
|
||||
// comparison know not to proceed when the discriminants differ.
|
||||
|
@ -470,7 +467,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
(_match::Single, None) => {
|
||||
if n_variants != 0 {
|
||||
assert!(n_variants == 1);
|
||||
cx = iter_variant(cx, &*repr, av, &*(*variants)[0],
|
||||
cx = iter_variant(cx, &*repr, av, &en.variants[0],
|
||||
substs, &mut f);
|
||||
}
|
||||
}
|
||||
|
@ -496,7 +493,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
n_variants);
|
||||
let next_cx = fcx.new_temp_block("enum-iter-next");
|
||||
|
||||
for variant in &(*variants) {
|
||||
for variant in &en.variants {
|
||||
let variant_cx =
|
||||
fcx.new_temp_block(
|
||||
&format!("enum-iter-variant-{}",
|
||||
|
@ -513,7 +510,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
|
|||
iter_variant(variant_cx,
|
||||
&*repr,
|
||||
data_ptr,
|
||||
&**variant,
|
||||
variant,
|
||||
substs,
|
||||
&mut f);
|
||||
Br(variant_cx, next_cx.llbb, DebugLoc::None);
|
||||
|
@ -624,7 +621,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
|
|||
let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
|
||||
(ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
|
||||
}
|
||||
ty::TyStruct(_, _) if rhs_t.is_simd(cx.tcx()) => {
|
||||
ty::TyStruct(def, _) if def.is_simd() => {
|
||||
let mut res = C_bool(cx.ccx(), false);
|
||||
for i in 0 .. rhs_t.simd_size(cx.tcx()) {
|
||||
res = Or(cx, res,
|
||||
|
@ -1693,9 +1690,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
|
||||
pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
_enum_id: ast::NodeId,
|
||||
variant: &ast::Variant,
|
||||
_args: &[ast::VariantArg],
|
||||
ctor_id: ast::NodeId,
|
||||
disr: ty::Disr,
|
||||
param_substs: &'tcx Substs<'tcx>,
|
||||
llfndecl: ValueRef) {
|
||||
|
@ -1703,7 +1698,7 @@ pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
|
||||
trans_enum_variant_or_tuple_like_struct(
|
||||
ccx,
|
||||
variant.node.id,
|
||||
ctor_id,
|
||||
disr,
|
||||
param_substs,
|
||||
llfndecl);
|
||||
|
@ -1775,7 +1770,6 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
}
|
||||
|
||||
pub fn trans_tuple_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
_fields: &[ast::StructField],
|
||||
ctor_id: ast::NodeId,
|
||||
param_substs: &'tcx Substs<'tcx>,
|
||||
llfndecl: ValueRef) {
|
||||
|
|
|
@ -182,10 +182,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
|
|||
fn_callee(bcx, fn_datum)
|
||||
}
|
||||
def::DefVariant(tid, vid, _) => {
|
||||
let vinfo = bcx.tcx().enum_variant_with_id(tid, vid);
|
||||
|
||||
// Nullary variants are not callable
|
||||
assert!(!vinfo.args.is_empty());
|
||||
let vinfo = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
|
||||
assert_eq!(vinfo.kind(), ty::VariantKind::Tuple);
|
||||
|
||||
Callee {
|
||||
bcx: bcx,
|
||||
|
|
|
@ -49,6 +49,7 @@ use std::cell::{Cell, RefCell};
|
|||
use std::result::Result as StdResult;
|
||||
use std::vec::Vec;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::local_def;
|
||||
use syntax::codemap::{DUMMY_SP, Span};
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
|
@ -173,12 +174,10 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
|
|||
|
||||
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let fields = ccx.tcx().lookup_struct_fields(def_id);
|
||||
ty::TyStruct(def, substs) => {
|
||||
let fields = &def.struct_variant().fields;
|
||||
fields.len() == 1 && {
|
||||
let ty = ccx.tcx().lookup_field_type(def_id, fields[0].id, substs);
|
||||
let ty = monomorphize::normalize_associated_type(ccx.tcx(), &ty);
|
||||
type_is_immediate(ccx, ty)
|
||||
type_is_immediate(ccx, monomorphize::field_ty(ccx.tcx(), substs, &fields[0]))
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
|
@ -193,7 +192,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
|||
let simple = ty.is_scalar() ||
|
||||
ty.is_unique() || ty.is_region_ptr() ||
|
||||
type_is_newtype_immediate(ccx, ty) ||
|
||||
ty.is_simd(tcx);
|
||||
ty.is_simd();
|
||||
if simple && !type_is_fat_ptr(tcx, ty) {
|
||||
return true;
|
||||
}
|
||||
|
@ -271,6 +270,67 @@ pub fn expr_info(expr: &ast::Expr) -> NodeIdAndSpan {
|
|||
NodeIdAndSpan { id: expr.id, span: expr.span }
|
||||
}
|
||||
|
||||
/// The concrete version of ty::FieldDef. The name is the field index if
|
||||
/// the field is numeric.
|
||||
pub struct Field<'tcx>(pub ast::Name, pub Ty<'tcx>);
|
||||
|
||||
/// The concrete version of ty::VariantDef
|
||||
pub struct VariantInfo<'tcx> {
|
||||
pub discr: ty::Disr,
|
||||
pub fields: Vec<Field<'tcx>>
|
||||
}
|
||||
|
||||
impl<'tcx> VariantInfo<'tcx> {
|
||||
pub fn from_ty(tcx: &ty::ctxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
opt_def: Option<def::Def>)
|
||||
-> Self
|
||||
{
|
||||
match ty.sty {
|
||||
ty::TyStruct(adt, substs) | ty::TyEnum(adt, substs) => {
|
||||
let variant = match opt_def {
|
||||
None => adt.struct_variant(),
|
||||
Some(def) => adt.variant_of_def(def)
|
||||
};
|
||||
|
||||
VariantInfo {
|
||||
discr: variant.disr_val,
|
||||
fields: variant.fields.iter().map(|f| {
|
||||
Field(f.name, monomorphize::field_ty(tcx, substs, f))
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyTuple(ref v) => {
|
||||
VariantInfo {
|
||||
discr: 0,
|
||||
fields: v.iter().enumerate().map(|(i, &t)| {
|
||||
Field(token::intern(&i.to_string()), t)
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
tcx.sess.bug(&format!(
|
||||
"cannot get field types from the type {:?}",
|
||||
ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the variant corresponding to a given node (e.g. expr)
|
||||
pub fn of_node(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, id: ast::NodeId) -> Self {
|
||||
let node_def = tcx.def_map.borrow().get(&id).map(|v| v.full_def());
|
||||
Self::from_ty(tcx, ty, node_def)
|
||||
}
|
||||
|
||||
pub fn field_index(&self, name: ast::Name) -> usize {
|
||||
self.fields.iter().position(|&Field(n,_)| n == name).unwrap_or_else(|| {
|
||||
panic!("unknown field `{}`", name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BuilderRef_res {
|
||||
pub b: BuilderRef,
|
||||
}
|
||||
|
@ -1178,3 +1238,26 @@ pub fn langcall(bcx: Block,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the VariantDef corresponding to an inlined variant node
|
||||
pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
inlined_vid: ast::NodeId)
|
||||
-> ty::VariantDef<'tcx>
|
||||
{
|
||||
|
||||
let ctor_ty = ccx.tcx().node_id_to_type(inlined_vid);
|
||||
debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
|
||||
inlined_vid);
|
||||
let adt_def = match ctor_ty.sty {
|
||||
ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
|
||||
output: ty::FnConverging(ty), ..
|
||||
}), ..}) => ty,
|
||||
_ => ctor_ty
|
||||
}.ty_adt_def().unwrap();
|
||||
adt_def.variants.iter().find(|v| {
|
||||
local_def(inlined_vid) == v.did ||
|
||||
ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
|
||||
}).unwrap_or_else(|| {
|
||||
ccx.sess().bug(&format!("no variant for {:?}::{}", adt_def, inlined_vid))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -500,7 +500,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
debug!("const_expr_unadjusted: te1={}, ty={:?}",
|
||||
cx.tn().val_to_string(te1),
|
||||
ty);
|
||||
let is_simd = ty.is_simd(cx.tcx());
|
||||
let is_simd = ty.is_simd();
|
||||
let intype = if is_simd {
|
||||
ty.simd_type(cx.tcx())
|
||||
} else {
|
||||
|
@ -579,17 +579,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ast::ExprField(ref base, field) => {
|
||||
let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
|
||||
let brepr = adt::represent_type(cx, bt);
|
||||
expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
|
||||
let ix = cx.tcx().field_idx_strict(field.node.name, field_tys);
|
||||
adt::const_get_field(cx, &*brepr, bv, discr, ix)
|
||||
})
|
||||
let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
|
||||
let ix = vinfo.field_index(field.node.name);
|
||||
adt::const_get_field(cx, &*brepr, bv, vinfo.discr, ix)
|
||||
},
|
||||
ast::ExprTupField(ref base, idx) => {
|
||||
let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
|
||||
let brepr = adt::represent_type(cx, bt);
|
||||
expr::with_field_tys(cx.tcx(), bt, None, |discr, _| {
|
||||
adt::const_get_field(cx, &*brepr, bv, discr, idx.node)
|
||||
})
|
||||
let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
|
||||
adt::const_get_field(cx, &*brepr, bv, vinfo.discr, idx.node)
|
||||
},
|
||||
|
||||
ast::ExprIndex(ref base, ref index) => {
|
||||
|
@ -664,8 +662,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
}
|
||||
unsafe { match (
|
||||
CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"),
|
||||
CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast"),
|
||||
CastTy::from_ty(t_expr).expect("bad input type for cast"),
|
||||
CastTy::from_ty(t_cast).expect("bad output type for cast"),
|
||||
) {
|
||||
(CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => {
|
||||
let repr = adt::represent_type(cx, t_expr);
|
||||
|
@ -748,21 +746,19 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
None => None
|
||||
};
|
||||
|
||||
expr::with_field_tys(cx.tcx(), ety, Some(e.id), |discr, field_tys| {
|
||||
let cs = field_tys.iter().enumerate()
|
||||
.map(|(ix, &field_ty)| {
|
||||
match (fs.iter().find(|f| field_ty.name == f.ident.node.name), base_val) {
|
||||
let VariantInfo { discr, fields } = VariantInfo::of_node(cx.tcx(), ety, e.id);
|
||||
let cs = fields.iter().enumerate().map(|(ix, &Field(f_name, _))| {
|
||||
match (fs.iter().find(|f| f_name == f.ident.node.name), base_val) {
|
||||
(Some(ref f), _) => const_expr(cx, &*f.expr, param_substs, fn_args).0,
|
||||
(_, Some((bv, _))) => adt::const_get_field(cx, &*repr, bv, discr, ix),
|
||||
(_, None) => cx.sess().span_bug(e.span, "missing struct field"),
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
if ety.is_simd(cx.tcx()) {
|
||||
if ety.is_simd() {
|
||||
C_vector(&cs[..])
|
||||
} else {
|
||||
adt::trans_const(cx, &*repr, discr, &cs[..])
|
||||
}
|
||||
})
|
||||
},
|
||||
ast::ExprVec(ref es) => {
|
||||
let unit_ty = ety.sequence_element_type(cx.tcx());
|
||||
|
@ -806,15 +802,19 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
const_deref_ptr(cx, get_const_val(cx, def_id, e))
|
||||
}
|
||||
def::DefVariant(enum_did, variant_did, _) => {
|
||||
let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did);
|
||||
if !vinfo.args.is_empty() {
|
||||
// N-ary variant.
|
||||
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
|
||||
} else {
|
||||
// Nullary variant.
|
||||
let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
|
||||
match vinfo.kind() {
|
||||
ty::VariantKind::Unit => {
|
||||
let repr = adt::represent_type(cx, ety);
|
||||
adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
|
||||
}
|
||||
ty::VariantKind::Tuple => {
|
||||
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
|
||||
}
|
||||
ty::VariantKind::Dict => {
|
||||
cx.sess().span_bug(e.span, "path-expr refers to a dict variant!")
|
||||
}
|
||||
}
|
||||
}
|
||||
def::DefStruct(_) => {
|
||||
if let ty::TyBareFn(..) = ety.sty {
|
||||
|
@ -850,7 +850,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs)
|
||||
}
|
||||
def::DefStruct(_) => {
|
||||
if ety.is_simd(cx.tcx()) {
|
||||
if ety.is_simd() {
|
||||
C_vector(&arg_vals[..])
|
||||
} else {
|
||||
let repr = adt::represent_type(cx, ety);
|
||||
|
@ -859,7 +859,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
def::DefVariant(enum_did, variant_did, _) => {
|
||||
let repr = adt::represent_type(cx, ety);
|
||||
let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did);
|
||||
let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
|
||||
adt::trans_const(cx,
|
||||
&*repr,
|
||||
vinfo.disr_val,
|
||||
|
|
|
@ -44,7 +44,7 @@ use std::rc::Rc;
|
|||
use syntax::util::interner::Interner;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::{ast, codemap, ast_util};
|
||||
use syntax::parse::token::{self, special_idents};
|
||||
use syntax::parse::token;
|
||||
|
||||
|
||||
const DW_LANG_RUST: c_uint = 0x9000;
|
||||
|
@ -178,13 +178,13 @@ impl<'tcx> TypeMap<'tcx> {
|
|||
ty::TyFloat(_) => {
|
||||
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
||||
},
|
||||
ty::TyEnum(def_id, substs) => {
|
||||
ty::TyEnum(def, substs) => {
|
||||
unique_type_id.push_str("enum ");
|
||||
from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
|
||||
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
|
||||
},
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
ty::TyStruct(def, substs) => {
|
||||
unique_type_id.push_str("struct ");
|
||||
from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
|
||||
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
|
||||
},
|
||||
ty::TyTuple(ref component_types) if component_types.is_empty() => {
|
||||
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
||||
|
@ -710,8 +710,12 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ty::TyTuple(ref elements) if elements.is_empty() => {
|
||||
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
||||
}
|
||||
ty::TyEnum(def_id, _) => {
|
||||
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
|
||||
ty::TyEnum(def, _) => {
|
||||
prepare_enum_metadata(cx,
|
||||
t,
|
||||
def.did,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyArray(typ, len) => {
|
||||
fixed_vec_metadata(cx, unique_type_id, typ, Some(len as u64), usage_site_span)
|
||||
|
@ -780,11 +784,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
ty::TyStruct(..) => {
|
||||
prepare_struct_metadata(cx,
|
||||
t,
|
||||
def_id,
|
||||
substs,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
|
@ -1092,7 +1094,8 @@ impl<'tcx> MemberDescriptionFactory<'tcx> {
|
|||
|
||||
// Creates MemberDescriptions for the fields of a struct
|
||||
struct StructMemberDescriptionFactory<'tcx> {
|
||||
fields: Vec<ty::Field<'tcx>>,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
substs: &'tcx subst::Substs<'tcx>,
|
||||
is_simd: bool,
|
||||
span: Span,
|
||||
}
|
||||
|
@ -1100,34 +1103,40 @@ struct StructMemberDescriptionFactory<'tcx> {
|
|||
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
||||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
||||
-> Vec<MemberDescription> {
|
||||
if self.fields.is_empty() {
|
||||
if let ty::VariantKind::Unit = self.variant.kind() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let field_size = if self.is_simd {
|
||||
machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as usize
|
||||
let fty = monomorphize::field_ty(cx.tcx(),
|
||||
self.substs,
|
||||
&self.variant.fields[0]);
|
||||
Some(machine::llsize_of_alloc(
|
||||
cx,
|
||||
type_of::type_of(cx, fty)
|
||||
) as usize)
|
||||
} else {
|
||||
0xdeadbeef
|
||||
None
|
||||
};
|
||||
|
||||
self.fields.iter().enumerate().map(|(i, field)| {
|
||||
let name = if field.name == special_idents::unnamed_field.name {
|
||||
self.variant.fields.iter().enumerate().map(|(i, f)| {
|
||||
let name = if let ty::VariantKind::Tuple = self.variant.kind() {
|
||||
format!("__{}", i)
|
||||
} else {
|
||||
field.name.to_string()
|
||||
f.name.to_string()
|
||||
};
|
||||
let fty = monomorphize::field_ty(cx.tcx(), self.substs, f);
|
||||
|
||||
let offset = if self.is_simd {
|
||||
assert!(field_size != 0xdeadbeef);
|
||||
FixedMemberOffset { bytes: i * field_size }
|
||||
FixedMemberOffset { bytes: i * field_size.unwrap() }
|
||||
} else {
|
||||
ComputedMemberOffset
|
||||
};
|
||||
|
||||
MemberDescription {
|
||||
name: name,
|
||||
llvm_type: type_of::type_of(cx, field.mt.ty),
|
||||
type_metadata: type_metadata(cx, field.mt.ty, self.span),
|
||||
llvm_type: type_of::type_of(cx, fty),
|
||||
type_metadata: type_metadata(cx, fty, self.span),
|
||||
offset: offset,
|
||||
flags: FLAGS_NONE,
|
||||
}
|
||||
|
@ -1138,15 +1147,18 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
|||
|
||||
fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
struct_type: Ty<'tcx>,
|
||||
def_id: ast::DefId,
|
||||
substs: &subst::Substs<'tcx>,
|
||||
unique_type_id: UniqueTypeId,
|
||||
span: Span)
|
||||
-> RecursiveTypeDescription<'tcx> {
|
||||
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
|
||||
let struct_llvm_type = type_of::in_memory_type_of(cx, struct_type);
|
||||
|
||||
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
|
||||
let (variant, substs) = match struct_type.sty {
|
||||
ty::TyStruct(def, substs) => (def.struct_variant(), substs),
|
||||
_ => cx.tcx().sess.bug("prepare_struct_metadata on a non-struct")
|
||||
};
|
||||
|
||||
let (containing_scope, _) = get_namespace_and_span_for_item(cx, variant.did);
|
||||
|
||||
let struct_metadata_stub = create_struct_stub(cx,
|
||||
struct_llvm_type,
|
||||
|
@ -1154,14 +1166,6 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
unique_type_id,
|
||||
containing_scope);
|
||||
|
||||
let mut fields = cx.tcx().struct_fields(def_id, substs);
|
||||
|
||||
// The `Ty` values returned by `ty::struct_fields` can still contain
|
||||
// `TyProjection` variants, so normalize those away.
|
||||
for field in &mut fields {
|
||||
field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty);
|
||||
}
|
||||
|
||||
create_and_register_recursive_type_forward_declaration(
|
||||
cx,
|
||||
struct_type,
|
||||
|
@ -1169,8 +1173,9 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
struct_metadata_stub,
|
||||
struct_llvm_type,
|
||||
StructMDF(StructMemberDescriptionFactory {
|
||||
fields: fields,
|
||||
is_simd: struct_type.is_simd(cx.tcx()),
|
||||
variant: variant,
|
||||
substs: substs,
|
||||
is_simd: struct_type.is_simd(),
|
||||
span: span,
|
||||
})
|
||||
)
|
||||
|
@ -1244,7 +1249,6 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
struct EnumMemberDescriptionFactory<'tcx> {
|
||||
enum_type: Ty<'tcx>,
|
||||
type_rep: Rc<adt::Repr<'tcx>>,
|
||||
variants: Rc<Vec<Rc<ty::VariantInfo<'tcx>>>>,
|
||||
discriminant_type_metadata: Option<DIType>,
|
||||
containing_scope: DIScope,
|
||||
file_metadata: DIFile,
|
||||
|
@ -1254,11 +1258,11 @@ struct EnumMemberDescriptionFactory<'tcx> {
|
|||
impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
||||
-> Vec<MemberDescription> {
|
||||
let adt = &self.enum_type.ty_adt_def().unwrap();
|
||||
match *self.type_rep {
|
||||
adt::General(_, ref struct_defs, _) => {
|
||||
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
|
||||
.expect(""));
|
||||
|
||||
struct_defs
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
@ -1269,7 +1273,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
&*self.variants[i],
|
||||
&adt.variants[i],
|
||||
discriminant_info,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
|
@ -1291,9 +1295,9 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
}).collect()
|
||||
},
|
||||
adt::Univariant(ref struct_def, _) => {
|
||||
assert!(self.variants.len() <= 1);
|
||||
assert!(adt.variants.len() <= 1);
|
||||
|
||||
if self.variants.is_empty() {
|
||||
if adt.variants.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
let (variant_type_metadata,
|
||||
|
@ -1302,7 +1306,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
&*self.variants[0],
|
||||
&adt.variants[0],
|
||||
NoDiscriminant,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
|
@ -1331,7 +1335,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
// DWARF representation of enums uniform.
|
||||
|
||||
// First create a description of the artificial wrapper struct:
|
||||
let non_null_variant = &self.variants[non_null_variant_index as usize];
|
||||
let non_null_variant = &adt.variants[non_null_variant_index as usize];
|
||||
let non_null_variant_name = non_null_variant.name.as_str();
|
||||
|
||||
// The llvm type and metadata of the pointer
|
||||
|
@ -1346,9 +1350,12 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
// For the metadata of the wrapper struct, we need to create a
|
||||
// MemberDescription of the struct's single field.
|
||||
let sole_struct_member_description = MemberDescription {
|
||||
name: match non_null_variant.arg_names {
|
||||
Some(ref names) => names[0].to_string(),
|
||||
None => "__0".to_string()
|
||||
name: match non_null_variant.kind() {
|
||||
ty::VariantKind::Tuple => "__0".to_string(),
|
||||
ty::VariantKind::Dict => {
|
||||
non_null_variant.fields[0].name.to_string()
|
||||
}
|
||||
ty::VariantKind::Unit => unreachable!()
|
||||
},
|
||||
llvm_type: non_null_llvm_type,
|
||||
type_metadata: non_null_type_metadata,
|
||||
|
@ -1377,7 +1384,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
// Encode the information about the null variant in the union
|
||||
// member's name.
|
||||
let null_variant_index = (1 - non_null_variant_index) as usize;
|
||||
let null_variant_name = self.variants[null_variant_index].name;
|
||||
let null_variant_name = adt.variants[null_variant_index].name;
|
||||
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
||||
0,
|
||||
null_variant_name);
|
||||
|
@ -1402,7 +1409,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
&*self.variants[nndiscr as usize],
|
||||
&adt.variants[nndiscr as usize],
|
||||
OptimizedDiscriminant,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
|
@ -1418,7 +1425,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|||
// Encode the information about the null variant in the union
|
||||
// member's name.
|
||||
let null_variant_index = (1 - nndiscr) as usize;
|
||||
let null_variant_name = self.variants[null_variant_index].name;
|
||||
let null_variant_name = adt.variants[null_variant_index].name;
|
||||
let discrfield = discrfield.iter()
|
||||
.skip(1)
|
||||
.map(|x| x.to_string())
|
||||
|
@ -1482,7 +1489,7 @@ enum EnumDiscriminantInfo {
|
|||
fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
enum_type: Ty<'tcx>,
|
||||
struct_def: &adt::Struct<'tcx>,
|
||||
variant_info: &ty::VariantInfo<'tcx>,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
discriminant_info: EnumDiscriminantInfo,
|
||||
containing_scope: DIScope,
|
||||
span: Span)
|
||||
|
@ -1496,7 +1503,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
struct_def.packed);
|
||||
// Could do some consistency checks here: size, align, field count, discr type
|
||||
|
||||
let variant_name = variant_info.name.as_str();
|
||||
let variant_name = variant.name.as_str();
|
||||
let unique_type_id = debug_context(cx).type_map
|
||||
.borrow_mut()
|
||||
.get_unique_type_id_of_enum_variant(
|
||||
|
@ -1511,19 +1518,21 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
containing_scope);
|
||||
|
||||
// Get the argument names from the enum variant info
|
||||
let mut arg_names: Vec<_> = match variant_info.arg_names {
|
||||
Some(ref names) => {
|
||||
names.iter()
|
||||
.map(|name| name.to_string())
|
||||
.collect()
|
||||
}
|
||||
None => {
|
||||
variant_info.args
|
||||
let mut arg_names: Vec<_> = match variant.kind() {
|
||||
ty::VariantKind::Unit => vec![],
|
||||
ty::VariantKind::Tuple => {
|
||||
variant.fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| format!("__{}", i))
|
||||
.collect()
|
||||
}
|
||||
ty::VariantKind::Dict => {
|
||||
variant.fields
|
||||
.iter()
|
||||
.map(|f| f.name.to_string())
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
// If this is not a univariant enum, there is also the discriminant field.
|
||||
|
@ -1565,7 +1574,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
let loc = span_start(cx, definition_span);
|
||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||
|
||||
let variants = cx.tcx().enum_variants(enum_def_id);
|
||||
let variants = &enum_type.ty_adt_def().unwrap().variants;
|
||||
|
||||
let enumerators_metadata: Vec<DIDescriptor> = variants
|
||||
.iter()
|
||||
|
@ -1667,7 +1676,6 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type: enum_type,
|
||||
type_rep: type_rep.clone(),
|
||||
variants: variants,
|
||||
discriminant_type_metadata: discriminant_type_metadata,
|
||||
containing_scope: containing_scope,
|
||||
file_metadata: file_metadata,
|
||||
|
|
|
@ -54,9 +54,9 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ty::TyUint(ast::TyU64) => output.push_str("u64"),
|
||||
ty::TyFloat(ast::TyF32) => output.push_str("f32"),
|
||||
ty::TyFloat(ast::TyF64) => output.push_str("f64"),
|
||||
ty::TyStruct(def_id, substs) |
|
||||
ty::TyEnum(def_id, substs) => {
|
||||
push_item_name(cx, def_id, qualified, output);
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
push_item_name(cx, def.did, qualified, output);
|
||||
push_type_params(cx, substs, output);
|
||||
},
|
||||
ty::TyTuple(ref component_types) => {
|
||||
|
|
|
@ -68,7 +68,6 @@ use trans::debuginfo::{self, DebugLoc, ToDebugLoc};
|
|||
use trans::glue;
|
||||
use trans::machine;
|
||||
use trans::meth;
|
||||
use trans::monomorphize;
|
||||
use trans::tvec;
|
||||
use trans::type_of;
|
||||
use middle::cast::{CastKind, CastTy};
|
||||
|
@ -708,7 +707,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
|||
base: &ast::Expr,
|
||||
get_idx: F)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> where
|
||||
F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::Field<'tcx>]) -> usize,
|
||||
F: FnOnce(&'blk ty::ctxt<'tcx>, &VariantInfo<'tcx>) -> usize,
|
||||
{
|
||||
let mut bcx = bcx;
|
||||
let _icx = push_ctxt("trans_rec_field");
|
||||
|
@ -716,12 +715,13 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
|||
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
|
||||
let bare_ty = base_datum.ty;
|
||||
let repr = adt::represent_type(bcx.ccx(), bare_ty);
|
||||
with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
|
||||
let ix = get_idx(bcx.tcx(), field_tys);
|
||||
let vinfo = VariantInfo::from_ty(bcx.tcx(), bare_ty, None);
|
||||
|
||||
let ix = get_idx(bcx.tcx(), &vinfo);
|
||||
let d = base_datum.get_element(
|
||||
bcx,
|
||||
field_tys[ix].mt.ty,
|
||||
|srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
|
||||
vinfo.fields[ix].1,
|
||||
|srcval| adt::trans_field_ptr(bcx, &*repr, srcval, vinfo.discr, ix));
|
||||
|
||||
if type_is_sized(bcx.tcx(), d.ty) {
|
||||
DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
|
||||
|
@ -735,8 +735,6 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
|||
// the data and cleanup is scheduled elsewhere.
|
||||
DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr(d.kind)))
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/// Translates `base.field`.
|
||||
|
@ -744,7 +742,7 @@ fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
base: &ast::Expr,
|
||||
field: ast::Name)
|
||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||
trans_field(bcx, base, |tcx, field_tys| tcx.field_idx_strict(field, field_tys))
|
||||
trans_field(bcx, base, |_, vinfo| vinfo.field_index(field))
|
||||
}
|
||||
|
||||
/// Translates `base.<idx>`.
|
||||
|
@ -1125,7 +1123,8 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
None,
|
||||
expr.span,
|
||||
expr.id,
|
||||
tcx.mk_struct(did, tcx.mk_substs(substs)),
|
||||
tcx.mk_struct(tcx.lookup_adt_def(did),
|
||||
tcx.mk_substs(substs)),
|
||||
dest)
|
||||
} else {
|
||||
tcx.sess.span_bug(expr.span,
|
||||
|
@ -1248,8 +1247,8 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
|
||||
match def {
|
||||
def::DefVariant(tid, vid, _) => {
|
||||
let variant_info = bcx.tcx().enum_variant_with_id(tid, vid);
|
||||
if !variant_info.args.is_empty() {
|
||||
let variant = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
|
||||
if let ty::VariantKind::Tuple = variant.kind() {
|
||||
// N-ary variant.
|
||||
let llfn = callee::trans_fn_ref(bcx.ccx(), vid,
|
||||
ExprId(ref_expr.id),
|
||||
|
@ -1260,15 +1259,14 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
// Nullary variant.
|
||||
let ty = expr_ty(bcx, ref_expr);
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
adt::trans_set_discr(bcx, &*repr, lldest,
|
||||
variant_info.disr_val);
|
||||
adt::trans_set_discr(bcx, &*repr, lldest, variant.disr_val);
|
||||
return bcx;
|
||||
}
|
||||
}
|
||||
def::DefStruct(_) => {
|
||||
let ty = expr_ty(bcx, ref_expr);
|
||||
match ty.sty {
|
||||
ty::TyStruct(did, _) if bcx.tcx().has_dtor(did) => {
|
||||
ty::TyStruct(def, _) if def.has_dtor(bcx.tcx()) => {
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
adt::trans_set_discr(bcx, &*repr, lldest, 0);
|
||||
}
|
||||
|
@ -1361,71 +1359,6 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper for enumerating the field types of structs, enums, or records. The optional node ID here
|
||||
/// is the node ID of the path identifying the enum variant in use. If none, this cannot possibly
|
||||
/// an enum variant (so, if it is and `node_id_opt` is none, this function panics).
|
||||
pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
node_id_opt: Option<ast::NodeId>,
|
||||
op: F)
|
||||
-> R where
|
||||
F: FnOnce(ty::Disr, &[ty::Field<'tcx>]) -> R,
|
||||
{
|
||||
match ty.sty {
|
||||
ty::TyStruct(did, substs) => {
|
||||
let fields = tcx.struct_fields(did, substs);
|
||||
let fields = monomorphize::normalize_associated_type(tcx, &fields);
|
||||
op(0, &fields[..])
|
||||
}
|
||||
|
||||
ty::TyTuple(ref v) => {
|
||||
let fields: Vec<_> = v.iter().enumerate().map(|(i, &f)| {
|
||||
ty::Field {
|
||||
name: token::intern(&i.to_string()),
|
||||
mt: ty::TypeAndMut {
|
||||
ty: f,
|
||||
mutbl: ast::MutImmutable
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
op(0, &fields)
|
||||
}
|
||||
|
||||
ty::TyEnum(_, substs) => {
|
||||
// We want the *variant* ID here, not the enum ID.
|
||||
match node_id_opt {
|
||||
None => {
|
||||
tcx.sess.bug(&format!(
|
||||
"cannot get field types from the enum type {:?} \
|
||||
without a node ID",
|
||||
ty));
|
||||
}
|
||||
Some(node_id) => {
|
||||
let def = tcx.def_map.borrow().get(&node_id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefVariant(enum_id, variant_id, _) => {
|
||||
let variant_info = tcx.enum_variant_with_id(enum_id, variant_id);
|
||||
let fields = tcx.struct_fields(variant_id, substs);
|
||||
let fields = monomorphize::normalize_associated_type(tcx, &fields);
|
||||
op(variant_info.disr_val, &fields[..])
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.bug("resolve didn't map this expr to a \
|
||||
variant ID")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
tcx.sess.bug(&format!(
|
||||
"cannot get field types from the type {:?}",
|
||||
ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
fields: &[ast::Field],
|
||||
base: Option<&ast::Expr>,
|
||||
|
@ -1436,31 +1369,22 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
let _icx = push_ctxt("trans_rec");
|
||||
|
||||
let tcx = bcx.tcx();
|
||||
with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| {
|
||||
let mut need_base = vec![true; field_tys.len()];
|
||||
let vinfo = VariantInfo::of_node(tcx, ty, expr_id);
|
||||
|
||||
let mut need_base = vec![true; vinfo.fields.len()];
|
||||
|
||||
let numbered_fields = fields.iter().map(|field| {
|
||||
let opt_pos =
|
||||
field_tys.iter().position(|field_ty|
|
||||
field_ty.name == field.ident.node.name);
|
||||
let result = match opt_pos {
|
||||
Some(i) => {
|
||||
need_base[i] = false;
|
||||
(i, &*field.expr)
|
||||
}
|
||||
None => {
|
||||
tcx.sess.span_bug(field.span,
|
||||
"Couldn't find field in struct type")
|
||||
}
|
||||
};
|
||||
result
|
||||
let pos = vinfo.field_index(field.ident.node.name);
|
||||
need_base[pos] = false;
|
||||
(pos, &*field.expr)
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let optbase = match base {
|
||||
Some(base_expr) => {
|
||||
let mut leftovers = Vec::new();
|
||||
for (i, b) in need_base.iter().enumerate() {
|
||||
if *b {
|
||||
leftovers.push((i, field_tys[i].mt.ty));
|
||||
leftovers.push((i, vinfo.fields[i].1));
|
||||
}
|
||||
}
|
||||
Some(StructBaseInfo {expr: base_expr,
|
||||
|
@ -1476,12 +1400,11 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
|
||||
trans_adt(bcx,
|
||||
ty,
|
||||
discr,
|
||||
vinfo.discr,
|
||||
&numbered_fields,
|
||||
optbase,
|
||||
dest,
|
||||
DebugLoc::At(expr_id, expr_span))
|
||||
})
|
||||
}
|
||||
|
||||
/// Information that `trans_adt` needs in order to fill in the fields
|
||||
|
@ -1530,7 +1453,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
// panic occur before the ADT as a whole is ready.
|
||||
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
|
||||
|
||||
if ty.is_simd(bcx.tcx()) {
|
||||
if ty.is_simd() {
|
||||
// Issue 23112: The original logic appeared vulnerable to same
|
||||
// order-of-eval bug. But, SIMD values are tuple-structs;
|
||||
// i.e. functional record update (FRU) syntax is unavailable.
|
||||
|
@ -1774,7 +1697,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
let _icx = push_ctxt("trans_eager_binop");
|
||||
|
||||
let tcx = bcx.tcx();
|
||||
let is_simd = lhs_t.is_simd(tcx);
|
||||
let is_simd = lhs_t.is_simd();
|
||||
let intype = if is_simd {
|
||||
lhs_t.simd_type(tcx)
|
||||
} else {
|
||||
|
@ -2125,8 +2048,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
let r_t_in = CastTy::from_ty(bcx.tcx(), t_in).expect("bad input type for cast");
|
||||
let r_t_out = CastTy::from_ty(bcx.tcx(), t_out).expect("bad output type for cast");
|
||||
let r_t_in = CastTy::from_ty(t_in).expect("bad input type for cast");
|
||||
let r_t_out = CastTy::from_ty(t_out).expect("bad output type for cast");
|
||||
|
||||
let (llexpr, signed) = if let Int(CEnum) = r_t_in {
|
||||
let repr = adt::represent_type(ccx, t_in);
|
||||
|
@ -2579,7 +2502,7 @@ fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
// #1877, #10183: Ensure that input is always valid
|
||||
let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
|
||||
let tcx = bcx.tcx();
|
||||
let is_simd = lhs_t.is_simd(tcx);
|
||||
let is_simd = lhs_t.is_simd();
|
||||
let intype = if is_simd {
|
||||
lhs_t.simd_type(tcx)
|
||||
} else {
|
||||
|
|
|
@ -449,7 +449,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
|
||||
if !tcx.sess.features.borrow().simd_ffi {
|
||||
let check = |ast_ty: &ast::Ty, ty: ty::Ty| {
|
||||
if ty.is_simd(tcx) {
|
||||
if ty.is_simd() {
|
||||
tcx.sess.span_err(ast_ty.span,
|
||||
&format!("use of SIMD type `{}` in FFI is highly experimental and \
|
||||
may result in invalid code",
|
||||
|
|
|
@ -415,11 +415,11 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
|
|||
return (size, align);
|
||||
}
|
||||
match t.sty {
|
||||
ty::TyStruct(id, substs) => {
|
||||
ty::TyStruct(def, substs) => {
|
||||
let ccx = bcx.ccx();
|
||||
// First get the size of all statically known fields.
|
||||
// Don't use type_of::sizing_type_of because that expects t to be sized.
|
||||
assert!(!t.is_simd(bcx.tcx()));
|
||||
assert!(!t.is_simd());
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let sizing_type = adt::sizing_type_context_of(ccx, &*repr, true);
|
||||
debug!("DST {} sizing_type: {}", t, sizing_type.to_string());
|
||||
|
@ -432,9 +432,8 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
|
|||
|
||||
// Recurse to get the size of the dynamically sized field (must be
|
||||
// the last field).
|
||||
let fields = bcx.tcx().struct_fields(id, substs);
|
||||
let last_field = fields[fields.len()-1];
|
||||
let field_ty = last_field.mt.ty;
|
||||
let last_field = def.struct_variant().fields.last().unwrap();
|
||||
let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field);
|
||||
let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
|
||||
|
||||
let dbloc = DebugLoc::None;
|
||||
|
@ -562,27 +561,27 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
|
|||
})
|
||||
}
|
||||
}
|
||||
ty::TyStruct(did, substs) | ty::TyEnum(did, substs) => {
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||
let tcx = bcx.tcx();
|
||||
match (tcx.ty_dtor(did), skip_dtor) {
|
||||
match (tcx.ty_dtor(def.did), skip_dtor) {
|
||||
(ty::TraitDtor(dtor, true), false) => {
|
||||
// FIXME(16758) Since the struct is unsized, it is hard to
|
||||
// find the drop flag (which is at the end of the struct).
|
||||
// Lets just ignore the flag and pretend everything will be
|
||||
// OK.
|
||||
if type_is_sized(bcx.tcx(), t) {
|
||||
trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
|
||||
trans_struct_drop_flag(bcx, t, v0, dtor, def.did, substs)
|
||||
} else {
|
||||
// Give the user a heads up that we are doing something
|
||||
// stupid and dangerous.
|
||||
bcx.sess().warn(&format!("Ignoring drop flag in destructor for {}\
|
||||
because the struct is unsized. See issue\
|
||||
#16758", t));
|
||||
trans_struct_drop(bcx, t, v0, dtor, did, substs)
|
||||
trans_struct_drop(bcx, t, v0, dtor, def.did, substs)
|
||||
}
|
||||
}
|
||||
(ty::TraitDtor(dtor, false), false) => {
|
||||
trans_struct_drop(bcx, t, v0, dtor, did, substs)
|
||||
trans_struct_drop(bcx, t, v0, dtor, def.did, substs)
|
||||
}
|
||||
(ty::NoDtor, _) | (_, true) => {
|
||||
// No dtor? Just the default case
|
||||
|
|
|
@ -102,17 +102,19 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
|
|||
|
||||
let mut my_id = 0;
|
||||
match item.node {
|
||||
ast::ItemEnum(_, _) => {
|
||||
let vs_here = ccx.tcx().enum_variants(local_def(item.id));
|
||||
let vs_there = ccx.tcx().enum_variants(parent_id);
|
||||
for (here, there) in vs_here.iter().zip(vs_there.iter()) {
|
||||
if there.id == fn_id { my_id = here.id.node; }
|
||||
ccx.external().borrow_mut().insert(there.id, Some(here.id.node));
|
||||
ast::ItemEnum(ref ast_def, _) => {
|
||||
let ast_vs = &ast_def.variants;
|
||||
let ty_vs = &ccx.tcx().lookup_adt_def(parent_id).variants;
|
||||
assert_eq!(ast_vs.len(), ty_vs.len());
|
||||
for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
|
||||
if ty_v.did == fn_id { my_id = ast_v.node.id; }
|
||||
ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.id));
|
||||
}
|
||||
}
|
||||
ast::ItemStruct(ref struct_def, _) => {
|
||||
match struct_def.ctor_id {
|
||||
None => {}
|
||||
None => ccx.sess().bug("instantiate_inline: called on a \
|
||||
non-tuple struct"),
|
||||
Some(ctor_id) => {
|
||||
ccx.external().borrow_mut().insert(fn_id, Some(ctor_id));
|
||||
my_id = ctor_id;
|
||||
|
|
|
@ -29,7 +29,6 @@ use middle::ty::{self, HasTypeFlags, Ty};
|
|||
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::local_def;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use std::hash::{Hasher, Hash, SipHasher};
|
||||
|
@ -192,24 +191,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
}
|
||||
ast_map::NodeVariant(v) => {
|
||||
let parent = ccx.tcx().map.get_parent(fn_id.node);
|
||||
let tvs = ccx.tcx().enum_variants(local_def(parent));
|
||||
let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
|
||||
let variant = inlined_variant_def(ccx, fn_id.node);
|
||||
assert_eq!(v.node.name.name, variant.name);
|
||||
let d = mk_lldecl(abi::Rust);
|
||||
attributes::inline(d, attributes::InlineAttr::Hint);
|
||||
match v.node.kind {
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
trans_enum_variant(ccx,
|
||||
parent,
|
||||
&*v,
|
||||
&args[..],
|
||||
this_tv.disr_val,
|
||||
psubsts,
|
||||
d);
|
||||
}
|
||||
ast::StructVariantKind(_) =>
|
||||
ccx.sess().bug("can't monomorphize struct variants"),
|
||||
}
|
||||
trans_enum_variant(ccx, fn_id.node, variant.disr_val, psubsts, d);
|
||||
d
|
||||
}
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
|
@ -255,7 +241,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
let d = mk_lldecl(abi::Rust);
|
||||
attributes::inline(d, attributes::InlineAttr::Hint);
|
||||
base::trans_tuple_struct(ccx,
|
||||
&struct_def.fields,
|
||||
struct_def.ctor_id.expect("ast-mapped tuple struct \
|
||||
didn't have a ctor id"),
|
||||
psubsts,
|
||||
|
@ -302,6 +287,16 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
|
|||
normalize_associated_type(tcx, &substituted)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the normalized type of a struct field
|
||||
pub fn field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
param_substs: &Substs<'tcx>,
|
||||
f: ty::FieldDef<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
normalize_associated_type(tcx, &f.ty(tcx, param_substs))
|
||||
}
|
||||
|
||||
/// Removes associated types, if any. Since this during
|
||||
/// monomorphization, we know that only concrete types are involved,
|
||||
/// and hence we can be sure that all associated types will be
|
||||
|
|
|
@ -222,7 +222,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
|||
}
|
||||
|
||||
ty::TyStruct(..) => {
|
||||
if t.is_simd(cx.tcx()) {
|
||||
if t.is_simd() {
|
||||
let llet = type_of(cx, t.simd_type(cx.tcx()));
|
||||
let n = t.simd_size(cx.tcx()) as u64;
|
||||
ensure_array_fits_in_address_space(cx, llet, n, t);
|
||||
|
@ -333,14 +333,14 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
|||
ty::TyInt(t) => Type::int_from_ty(cx, t),
|
||||
ty::TyUint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::TyFloat(t) => Type::float_from_ty(cx, t),
|
||||
ty::TyEnum(did, ref substs) => {
|
||||
ty::TyEnum(def, ref substs) => {
|
||||
// Only create the named struct, but don't fill it in. We
|
||||
// fill it in *after* placing it into the type cache. This
|
||||
// avoids creating more than one copy of the enum when one
|
||||
// of the enum's variants refers to the enum itself.
|
||||
let repr = adt::represent_type(cx, t);
|
||||
let tps = substs.types.get_slice(subst::TypeSpace);
|
||||
let name = llvm_type_name(cx, did, tps);
|
||||
let name = llvm_type_name(cx, def.did, tps);
|
||||
adt::incomplete_type_of(cx, &*repr, &name[..])
|
||||
}
|
||||
ty::TyClosure(..) => {
|
||||
|
@ -403,8 +403,8 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
|||
let repr = adt::represent_type(cx, t);
|
||||
adt::type_of(cx, &*repr)
|
||||
}
|
||||
ty::TyStruct(did, ref substs) => {
|
||||
if t.is_simd(cx.tcx()) {
|
||||
ty::TyStruct(def, ref substs) => {
|
||||
if t.is_simd() {
|
||||
let llet = in_memory_type_of(cx, t.simd_type(cx.tcx()));
|
||||
let n = t.simd_size(cx.tcx()) as u64;
|
||||
ensure_array_fits_in_address_space(cx, llet, n, t);
|
||||
|
@ -415,7 +415,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
|||
// infinite recursion with recursive struct types.
|
||||
let repr = adt::represent_type(cx, t);
|
||||
let tps = substs.types.get_slice(subst::TypeSpace);
|
||||
let name = llvm_type_name(cx, did, tps);
|
||||
let name = llvm_type_name(cx, def.did, tps);
|
||||
adt::incomplete_type_of(cx, &*repr, &name[..])
|
||||
}
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
|||
// If this was an enum or struct, fill in the type now.
|
||||
match t.sty {
|
||||
ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..)
|
||||
if !t.is_simd(cx.tcx()) => {
|
||||
if !t.is_simd() => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::finish_type_of(cx, &*repr, &mut llty);
|
||||
}
|
||||
|
|
|
@ -528,7 +528,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
|
|||
let tcx = pcx.fcx.ccx.tcx;
|
||||
|
||||
let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
let (enum_def_id, variant_def_id) = match def {
|
||||
let (adt_def, variant) = match def {
|
||||
def::DefTrait(_) => {
|
||||
let name = pprust::path_to_string(path);
|
||||
span_err!(tcx.sess, pat.span, E0168,
|
||||
|
@ -543,11 +543,11 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
|
|||
_ => {
|
||||
let def_type = tcx.lookup_item_type(def.def_id());
|
||||
match def_type.ty.sty {
|
||||
ty::TyStruct(struct_def_id, _) =>
|
||||
(struct_def_id, struct_def_id),
|
||||
ty::TyEnum(enum_def_id, _)
|
||||
if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
|
||||
(enum_def_id, def.def_id()),
|
||||
ty::TyStruct(struct_def, _) =>
|
||||
(struct_def, struct_def.struct_variant()),
|
||||
ty::TyEnum(enum_def, _)
|
||||
if def == def::DefVariant(enum_def.did, def.def_id(), true) =>
|
||||
(enum_def, enum_def.variant_of_def(def)),
|
||||
_ => {
|
||||
let name = pprust::path_to_string(path);
|
||||
span_err!(tcx.sess, pat.span, E0163,
|
||||
|
@ -565,8 +565,8 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
|
|||
|
||||
instantiate_path(pcx.fcx,
|
||||
&path.segments,
|
||||
tcx.lookup_item_type(enum_def_id),
|
||||
&tcx.lookup_predicates(enum_def_id),
|
||||
adt_def.type_scheme(tcx),
|
||||
&adt_def.predicates(tcx),
|
||||
None,
|
||||
def,
|
||||
pat.span,
|
||||
|
@ -581,9 +581,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
|
|||
.map(|substs| substs.substs.clone())
|
||||
.unwrap_or_else(|| Substs::empty());
|
||||
|
||||
let struct_fields = tcx.struct_fields(variant_def_id, &item_substs);
|
||||
check_struct_pat_fields(pcx, pat.span, fields, &struct_fields,
|
||||
variant_def_id, etc);
|
||||
check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
|
||||
}
|
||||
|
||||
pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
|
@ -647,21 +645,25 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||
|
||||
let real_path_ty = fcx.node_ty(pat.id);
|
||||
let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
|
||||
ty::TyEnum(enum_def_id, expected_substs)
|
||||
if def == def::DefVariant(enum_def_id, def.def_id(), false) =>
|
||||
ty::TyEnum(enum_def, expected_substs)
|
||||
if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
|
||||
{
|
||||
let variant = tcx.enum_variant_with_id(enum_def_id, def.def_id());
|
||||
(variant.args.iter()
|
||||
.map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t))
|
||||
let variant = enum_def.variant_of_def(def);
|
||||
(variant.fields
|
||||
.iter()
|
||||
.map(|f| fcx.instantiate_type_scheme(pat.span,
|
||||
expected_substs,
|
||||
&f.unsubst_ty()))
|
||||
.collect(),
|
||||
"variant")
|
||||
}
|
||||
ty::TyStruct(struct_def_id, expected_substs) => {
|
||||
let struct_fields = tcx.struct_fields(struct_def_id, expected_substs);
|
||||
(struct_fields.iter()
|
||||
.map(|field| fcx.instantiate_type_scheme(pat.span,
|
||||
ty::TyStruct(struct_def, expected_substs) => {
|
||||
(struct_def.struct_variant()
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| fcx.instantiate_type_scheme(pat.span,
|
||||
expected_substs,
|
||||
&field.mt.ty))
|
||||
&f.unsubst_ty()))
|
||||
.collect(),
|
||||
"struct")
|
||||
}
|
||||
|
@ -715,15 +717,15 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||
pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
fields: &'tcx [Spanned<ast::FieldPat>],
|
||||
struct_fields: &[ty::Field<'tcx>],
|
||||
struct_id: ast::DefId,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
substs: &Substs<'tcx>,
|
||||
etc: bool) {
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
|
||||
// Index the struct fields' types.
|
||||
let field_type_map = struct_fields
|
||||
let field_map = variant.fields
|
||||
.iter()
|
||||
.map(|field| (field.name, field.mt.ty))
|
||||
.map(|field| (field.name, field))
|
||||
.collect::<FnvHashMap<_, _>>();
|
||||
|
||||
// Keep track of which fields have already appeared in the pattern.
|
||||
|
@ -731,7 +733,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||
|
||||
// Typecheck each field.
|
||||
for &Spanned { node: ref field, span } in fields {
|
||||
let field_type = match used_fields.entry(field.ident.name) {
|
||||
let field_ty = match used_fields.entry(field.ident.name) {
|
||||
Occupied(occupied) => {
|
||||
span_err!(tcx.sess, span, E0025,
|
||||
"field `{}` bound multiple times in the pattern",
|
||||
|
@ -743,25 +745,24 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||
}
|
||||
Vacant(vacant) => {
|
||||
vacant.insert(span);
|
||||
field_type_map.get(&field.ident.name).cloned()
|
||||
field_map.get(&field.ident.name)
|
||||
.map(|f| pcx.fcx.field_ty(span, f, substs))
|
||||
.unwrap_or_else(|| {
|
||||
span_err!(tcx.sess, span, E0026,
|
||||
"struct `{}` does not have a field named `{}`",
|
||||
tcx.item_path_str(struct_id),
|
||||
tcx.item_path_str(variant.did),
|
||||
field.ident);
|
||||
tcx.types.err
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type);
|
||||
|
||||
check_pat(pcx, &*field.pat, field_type);
|
||||
check_pat(pcx, &*field.pat, field_ty);
|
||||
}
|
||||
|
||||
// Report an error if not all the fields were specified.
|
||||
if !etc {
|
||||
for field in struct_fields
|
||||
for field in variant.fields
|
||||
.iter()
|
||||
.filter(|field| !used_fields.contains_key(&field.name)) {
|
||||
span_err!(tcx.sess, span, E0027,
|
||||
|
|
|
@ -79,10 +79,11 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
match t.sty {
|
||||
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
|
||||
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
|
||||
ty::TyStruct(did, substs) => {
|
||||
match fcx.tcx().struct_fields(did, substs).pop() {
|
||||
ty::TyStruct(def, substs) => {
|
||||
// FIXME(arielb1): do some kind of normalization
|
||||
match def.struct_variant().fields.last() {
|
||||
None => None,
|
||||
Some(f) => unsize_kind(fcx, f.mt.ty)
|
||||
Some(f) => unsize_kind(fcx, f.ty(fcx.tcx(), substs))
|
||||
}
|
||||
}
|
||||
// We should really try to normalize here.
|
||||
|
@ -223,8 +224,8 @@ impl<'tcx> CastCheck<'tcx> {
|
|||
use middle::cast::IntTy::*;
|
||||
use middle::cast::CastTy::*;
|
||||
|
||||
let (t_from, t_cast) = match (CastTy::from_ty(fcx.tcx(), self.expr_ty),
|
||||
CastTy::from_ty(fcx.tcx(), self.cast_ty)) {
|
||||
let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty),
|
||||
CastTy::from_ty(self.cast_ty)) {
|
||||
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
|
||||
_ => {
|
||||
return Err(CastError::NonScalar)
|
||||
|
|
|
@ -18,6 +18,7 @@ use util::nodemap::FnvHashSet;
|
|||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{self, Span};
|
||||
use syntax::parse::token::special_idents;
|
||||
|
||||
/// check_drop_impl confirms that the Drop implementation identfied by
|
||||
/// `drop_impl_did` is not any more specialized than the type it is
|
||||
|
@ -41,18 +42,18 @@ pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(),
|
|||
ty: dtor_self_type } = tcx.lookup_item_type(drop_impl_did);
|
||||
let dtor_predicates = tcx.lookup_predicates(drop_impl_did);
|
||||
match dtor_self_type.sty {
|
||||
ty::TyEnum(self_type_did, self_to_impl_substs) |
|
||||
ty::TyStruct(self_type_did, self_to_impl_substs) => {
|
||||
ty::TyEnum(adt_def, self_to_impl_substs) |
|
||||
ty::TyStruct(adt_def, self_to_impl_substs) => {
|
||||
try!(ensure_drop_params_and_item_params_correspond(tcx,
|
||||
drop_impl_did,
|
||||
dtor_generics,
|
||||
&dtor_self_type,
|
||||
self_type_did));
|
||||
adt_def.did));
|
||||
|
||||
ensure_drop_predicates_are_implied_by_item_defn(tcx,
|
||||
drop_impl_did,
|
||||
&dtor_predicates,
|
||||
self_type_did,
|
||||
adt_def.did,
|
||||
self_to_impl_substs)
|
||||
}
|
||||
_ => {
|
||||
|
@ -285,25 +286,26 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
|
|||
// no need for an additional note if the overflow
|
||||
// was somehow on the root.
|
||||
}
|
||||
TypeContext::EnumVariant { def_id, variant, arg_index } => {
|
||||
// FIXME (pnkfelix): eventually lookup arg_name
|
||||
// for the given index on struct variants.
|
||||
TypeContext::ADT { def_id, variant, field, field_index } => {
|
||||
let adt = tcx.lookup_adt_def(def_id);
|
||||
let variant_name = match adt.adt_kind() {
|
||||
ty::AdtKind::Enum => format!("enum {} variant {}",
|
||||
tcx.item_path_str(def_id),
|
||||
variant),
|
||||
ty::AdtKind::Struct => format!("struct {}",
|
||||
tcx.item_path_str(def_id))
|
||||
};
|
||||
let field_name = if field == special_idents::unnamed_field.name {
|
||||
format!("#{}", field_index)
|
||||
} else {
|
||||
format!("`{}`", field)
|
||||
};
|
||||
span_note!(
|
||||
rcx.tcx().sess,
|
||||
span,
|
||||
"overflowed on enum {} variant {} argument {} type: {}",
|
||||
tcx.item_path_str(def_id),
|
||||
variant,
|
||||
arg_index,
|
||||
detected_on_typ);
|
||||
}
|
||||
TypeContext::Struct { def_id, field } => {
|
||||
span_note!(
|
||||
rcx.tcx().sess,
|
||||
span,
|
||||
"overflowed on struct {} field {} type: {}",
|
||||
tcx.item_path_str(def_id),
|
||||
field,
|
||||
"overflowed on {} field {} type: {}",
|
||||
variant_name,
|
||||
field_name,
|
||||
detected_on_typ);
|
||||
}
|
||||
}
|
||||
|
@ -318,14 +320,11 @@ enum Error<'tcx> {
|
|||
#[derive(Copy, Clone)]
|
||||
enum TypeContext {
|
||||
Root,
|
||||
EnumVariant {
|
||||
ADT {
|
||||
def_id: ast::DefId,
|
||||
variant: ast::Name,
|
||||
arg_index: usize,
|
||||
},
|
||||
Struct {
|
||||
def_id: ast::DefId,
|
||||
field: ast::Name,
|
||||
field_index: usize
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,8 +356,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
|
|||
return Err(Error::Overflow(context, ty))
|
||||
}
|
||||
|
||||
let opt_phantom_data_def_id = tcx.lang_items.phantom_data();
|
||||
|
||||
if !cx.breadcrumbs.insert(ty) {
|
||||
debug!("iterate_over_potentially_unsafe_regions_in_type \
|
||||
{}ty: {} scope: {:?} - cached",
|
||||
|
@ -399,7 +396,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
|
|||
// type parameters are unbounded. If both conditions hold, we
|
||||
// simply skip the `type_must_outlive` call entirely (but
|
||||
// resume the recursive checking of the type-substructure).
|
||||
if has_dtor_of_interest(tcx, ty, cx.span) {
|
||||
if has_dtor_of_interest(tcx, ty) {
|
||||
debug!("iterate_over_potentially_unsafe_regions_in_type \
|
||||
{}ty: {} - is a dtorck type!",
|
||||
(0..depth).map(|_| ' ').collect::<String>(),
|
||||
|
@ -432,47 +429,31 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
|
|||
cx, context, ity, depth+1)
|
||||
}
|
||||
|
||||
ty::TyStruct(did, substs) if Some(did) == opt_phantom_data_def_id => {
|
||||
ty::TyStruct(def, substs) if def.is_phantom_data() => {
|
||||
// PhantomData<T> - behaves identically to T
|
||||
let ity = *substs.types.get(subst::TypeSpace, 0);
|
||||
iterate_over_potentially_unsafe_regions_in_type(
|
||||
cx, context, ity, depth+1)
|
||||
}
|
||||
|
||||
ty::TyStruct(did, substs) => {
|
||||
let fields = tcx.lookup_struct_fields(did);
|
||||
for field in &fields {
|
||||
let fty = tcx.lookup_field_type(did, field.id, substs);
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||
let did = def.did;
|
||||
for variant in &def.variants {
|
||||
for (i, field) in variant.fields.iter().enumerate() {
|
||||
let fty = field.ty(tcx, substs);
|
||||
let fty = cx.rcx.fcx.resolve_type_vars_if_possible(
|
||||
cx.rcx.fcx.normalize_associated_types_in(cx.span, &fty));
|
||||
try!(iterate_over_potentially_unsafe_regions_in_type(
|
||||
cx,
|
||||
TypeContext::Struct {
|
||||
TypeContext::ADT {
|
||||
def_id: did,
|
||||
field: field.name,
|
||||
variant: variant.name,
|
||||
field_index: i
|
||||
},
|
||||
fty,
|
||||
depth+1))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
ty::TyEnum(did, substs) => {
|
||||
let all_variant_info = tcx.substd_enum_variants(did, substs);
|
||||
for variant_info in &all_variant_info {
|
||||
for (i, fty) in variant_info.args.iter().enumerate() {
|
||||
let fty = cx.rcx.fcx.resolve_type_vars_if_possible(
|
||||
cx.rcx.fcx.normalize_associated_types_in(cx.span, &fty));
|
||||
try!(iterate_over_potentially_unsafe_regions_in_type(
|
||||
cx,
|
||||
TypeContext::EnumVariant {
|
||||
def_id: did,
|
||||
variant: variant_info.name,
|
||||
arg_index: i,
|
||||
},
|
||||
fty,
|
||||
depth+1));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -510,102 +491,10 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
|
|||
}
|
||||
|
||||
fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
span: Span) -> bool {
|
||||
ty: ty::Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyEnum(def_id, _) | ty::TyStruct(def_id, _) => {
|
||||
let dtor_method_did = match tcx.destructor_for_type.borrow().get(&def_id) {
|
||||
Some(def_id) => *def_id,
|
||||
None => {
|
||||
debug!("ty: {:?} has no dtor, and thus isn't a dropck type", ty);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let impl_did = tcx.impl_of_method(dtor_method_did)
|
||||
.unwrap_or_else(|| {
|
||||
tcx.sess.span_bug(
|
||||
span, "no Drop impl found for drop method")
|
||||
});
|
||||
|
||||
let dtor_typescheme = tcx.lookup_item_type(impl_did);
|
||||
let dtor_generics = dtor_typescheme.generics;
|
||||
|
||||
let mut has_pred_of_interest = false;
|
||||
|
||||
let mut seen_items = Vec::new();
|
||||
let mut items_to_inspect = vec![impl_did];
|
||||
'items: while let Some(item_def_id) = items_to_inspect.pop() {
|
||||
if seen_items.contains(&item_def_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for pred in tcx.lookup_predicates(item_def_id).predicates {
|
||||
let result = match pred {
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::Projection(..) => {
|
||||
// For now, assume all these where-clauses
|
||||
// may give drop implementation capabilty
|
||||
// to access borrowed data.
|
||||
true
|
||||
}
|
||||
|
||||
ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
|
||||
let def_id = t_pred.trait_ref.def_id;
|
||||
if tcx.trait_items(def_id).len() != 0 {
|
||||
// If trait has items, assume it adds
|
||||
// capability to access borrowed data.
|
||||
true
|
||||
} else {
|
||||
// Trait without items is itself
|
||||
// uninteresting from POV of dropck.
|
||||
//
|
||||
// However, may have parent w/ items;
|
||||
// so schedule checking of predicates,
|
||||
items_to_inspect.push(def_id);
|
||||
// and say "no capability found" for now.
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if result {
|
||||
has_pred_of_interest = true;
|
||||
debug!("ty: {:?} has interesting dtor due to generic preds, e.g. {:?}",
|
||||
ty, pred);
|
||||
break 'items;
|
||||
}
|
||||
}
|
||||
|
||||
seen_items.push(item_def_id);
|
||||
}
|
||||
|
||||
// In `impl<'a> Drop ...`, we automatically assume
|
||||
// `'a` is meaningful and thus represents a bound
|
||||
// through which we could reach borrowed data.
|
||||
//
|
||||
// FIXME (pnkfelix): In the future it would be good to
|
||||
// extend the language to allow the user to express,
|
||||
// in the impl signature, that a lifetime is not
|
||||
// actually used (something like `where 'a: ?Live`).
|
||||
let has_region_param_of_interest =
|
||||
dtor_generics.has_region_params(subst::TypeSpace);
|
||||
|
||||
let has_dtor_of_interest =
|
||||
has_region_param_of_interest ||
|
||||
has_pred_of_interest;
|
||||
|
||||
if has_dtor_of_interest {
|
||||
debug!("ty: {:?} has interesting dtor, due to \
|
||||
region params: {} or pred: {}",
|
||||
ty,
|
||||
has_region_param_of_interest,
|
||||
has_pred_of_interest);
|
||||
} else {
|
||||
debug!("ty: {:?} has dtor, but it is uninteresting", ty);
|
||||
}
|
||||
has_dtor_of_interest
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
|
||||
def.is_dtorck(tcx)
|
||||
}
|
||||
ty::TyTrait(..) | ty::TyProjection(..) => {
|
||||
debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
|
||||
|
|
|
@ -286,10 +286,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
|||
self.assemble_inherent_candidates_from_object(self_ty, data);
|
||||
self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
|
||||
}
|
||||
ty::TyEnum(did, _) |
|
||||
ty::TyStruct(did, _) |
|
||||
ty::TyClosure(did, _) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(did);
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(def.did);
|
||||
}
|
||||
ty::TyBox(_) => {
|
||||
if let Some(box_did) = self.tcx().lang_items.owned_box() {
|
||||
|
|
|
@ -65,10 +65,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
None);
|
||||
|
||||
// If the item has the name of a field, give a help note
|
||||
if let (&ty::TyStruct(did, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
|
||||
let fields = cx.lookup_struct_fields(did);
|
||||
|
||||
if let Some(field) = fields.iter().find(|f| f.name == item_name) {
|
||||
if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
|
||||
if let Some(field) = def.struct_variant().find_field_named(item_name) {
|
||||
let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
|
||||
Ok(expr_string) => expr_string,
|
||||
_ => "s".into() // Default to a generic placeholder for the
|
||||
|
@ -89,7 +87,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
};
|
||||
|
||||
// Determine if the field can be used as a function in some way
|
||||
let field_ty = cx.lookup_field_type(did, field.id, substs);
|
||||
let field_ty = field.ty(cx, substs);
|
||||
if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) {
|
||||
let infcx = fcx.infcx();
|
||||
infcx.probe(|_| {
|
||||
|
@ -303,7 +301,7 @@ fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
rcvr_expr: Option<&ast::Expr>) -> bool {
|
||||
fn is_local(ty: Ty) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyEnum(did, _) | ty::TyStruct(did, _) => ast_util::is_local(did),
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) => ast_util::is_local(def.did),
|
||||
|
||||
ty::TyTrait(ref tr) => ast_util::is_local(tr.principal_def_id()),
|
||||
|
||||
|
|
|
@ -1674,34 +1674,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(arielb1): use this instead of field.ty everywhere
|
||||
pub fn field_ty(&self,
|
||||
span: Span,
|
||||
field: ty::FieldDef<'tcx>,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
self.normalize_associated_types_in(span,
|
||||
&field.ty(self.tcx(), substs))
|
||||
}
|
||||
|
||||
// Only for fields! Returns <none> for methods>
|
||||
// Indifferent to privacy flags
|
||||
pub fn lookup_field_ty(&self,
|
||||
span: Span,
|
||||
class_id: ast::DefId,
|
||||
items: &[ty::FieldTy],
|
||||
fieldname: ast::Name,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> Option<Ty<'tcx>>
|
||||
{
|
||||
let o_field = items.iter().find(|f| f.name == fieldname);
|
||||
o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
|
||||
.map(|t| self.normalize_associated_types_in(span, &t))
|
||||
}
|
||||
|
||||
pub fn lookup_tup_field_ty(&self,
|
||||
span: Span,
|
||||
class_id: ast::DefId,
|
||||
items: &[ty::FieldTy],
|
||||
idx: usize,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> Option<Ty<'tcx>>
|
||||
{
|
||||
let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
|
||||
o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
|
||||
.map(|t| self.normalize_associated_types_in(span, &t))
|
||||
}
|
||||
|
||||
fn check_casts(&self) {
|
||||
let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
|
||||
for cast in deferred_cast_checks.drain(..) {
|
||||
|
@ -2878,11 +2863,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
lvalue_pref,
|
||||
|base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::TyStruct(base_id, substs) => {
|
||||
ty::TyStruct(base_def, substs) => {
|
||||
debug!("struct named {:?}", base_t);
|
||||
let fields = tcx.lookup_struct_fields(base_id);
|
||||
fcx.lookup_field_ty(expr.span, base_id, &fields[..],
|
||||
field.node.name, &(*substs))
|
||||
base_def.struct_variant()
|
||||
.find_field_named(field.node.name)
|
||||
.map(|f| fcx.field_ty(expr.span, f, substs))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
|
@ -2919,8 +2904,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
actual)
|
||||
},
|
||||
expr_t, None);
|
||||
if let ty::TyStruct(did, _) = expr_t.sty {
|
||||
suggest_field_names(did, field, tcx, vec![]);
|
||||
if let ty::TyStruct(def, _) = expr_t.sty {
|
||||
suggest_field_names(def.struct_variant(), field, tcx, vec![]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2928,23 +2913,22 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
}
|
||||
|
||||
// displays hints about the closest matches in field names
|
||||
fn suggest_field_names<'tcx>(id : DefId,
|
||||
field : &ast::SpannedIdent,
|
||||
tcx : &ty::ctxt<'tcx>,
|
||||
fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
|
||||
field: &ast::SpannedIdent,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
skip : Vec<InternedString>) {
|
||||
let name = field.node.name.as_str();
|
||||
// only find fits with at least one matching letter
|
||||
let mut best_dist = name.len();
|
||||
let fields = tcx.lookup_struct_fields(id);
|
||||
let mut best = None;
|
||||
for elem in &fields {
|
||||
for elem in &variant.fields {
|
||||
let n = elem.name.as_str();
|
||||
// ignore already set fields
|
||||
if skip.iter().any(|x| *x == n) {
|
||||
continue;
|
||||
}
|
||||
// ignore private fields from non-local crates
|
||||
if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
|
||||
if variant.did.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
|
||||
continue;
|
||||
}
|
||||
let dist = lev_distance(&n, &name);
|
||||
|
@ -2965,7 +2949,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
lvalue_pref: LvaluePreference,
|
||||
base: &'tcx ast::Expr,
|
||||
idx: codemap::Spanned<usize>) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
|
||||
let expr_t = structurally_resolved_type(fcx, expr.span,
|
||||
fcx.expr_ty(base));
|
||||
|
@ -2979,13 +2962,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
lvalue_pref,
|
||||
|base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::TyStruct(base_id, substs) => {
|
||||
tuple_like = tcx.is_tuple_struct(base_id);
|
||||
ty::TyStruct(base_def, substs) => {
|
||||
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_id);
|
||||
fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
|
||||
idx.node, &(*substs))
|
||||
base_def.struct_variant()
|
||||
.fields
|
||||
.get(idx.node)
|
||||
.map(|f| fcx.field_ty(expr.span, f, substs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -3025,75 +3009,63 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
fcx.write_error(expr.id);
|
||||
}
|
||||
|
||||
fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
struct_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
class_id: ast::DefId,
|
||||
node_id: ast::NodeId,
|
||||
substitutions: &'tcx subst::Substs<'tcx>,
|
||||
field_types: &[ty::FieldTy],
|
||||
ast_fields: &'tcx [ast::Field],
|
||||
check_completeness: bool,
|
||||
enum_id_opt: Option<ast::DefId>) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
field: &ast::Field,
|
||||
skip_fields: &[ast::Field]) {
|
||||
fcx.type_error_message(
|
||||
field.ident.span,
|
||||
|actual| if let ty::TyEnum(..) = ty.sty {
|
||||
format!("struct variant `{}::{}` has no field named `{}`",
|
||||
actual, variant.name.as_str(), field.ident.node)
|
||||
} else {
|
||||
format!("structure `{}` has no field named `{}`",
|
||||
actual, field.ident.node)
|
||||
},
|
||||
ty,
|
||||
None);
|
||||
// prevent all specified fields from being suggested
|
||||
let skip_fields = skip_fields.iter().map(|ref x| x.ident.node.name.as_str());
|
||||
suggest_field_names(variant, &field.ident, fcx.tcx(), skip_fields.collect());
|
||||
}
|
||||
|
||||
let mut class_field_map = FnvHashMap();
|
||||
let mut fields_found = 0;
|
||||
for field in field_types {
|
||||
class_field_map.insert(field.name, (field.id, false));
|
||||
|
||||
fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
adt_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
variant_id: ast::DefId,
|
||||
ast_fields: &'tcx [ast::Field],
|
||||
check_completeness: bool) -> Result<(),()> {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let (adt_def, substs) = match adt_ty.sty {
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => (def, substs),
|
||||
_ => tcx.sess.span_bug(span, "non-ADT passed to check_struct_or_variant_fields")
|
||||
};
|
||||
let variant = adt_def.variant_with_id(variant_id);
|
||||
|
||||
let mut remaining_fields = FnvHashMap();
|
||||
for field in &variant.fields {
|
||||
remaining_fields.insert(field.name, field);
|
||||
}
|
||||
|
||||
let mut error_happened = false;
|
||||
|
||||
// Typecheck each field.
|
||||
for field in ast_fields {
|
||||
let mut expected_field_type = tcx.types.err;
|
||||
let expected_field_type;
|
||||
|
||||
let pair = class_field_map.get(&field.ident.node.name).cloned();
|
||||
match pair {
|
||||
None => {
|
||||
fcx.type_error_message(
|
||||
field.ident.span,
|
||||
|actual| match enum_id_opt {
|
||||
Some(enum_id) => {
|
||||
let variant_type = tcx.enum_variant_with_id(enum_id,
|
||||
class_id);
|
||||
format!("struct variant `{}::{}` has no field named `{}`",
|
||||
actual, variant_type.name.as_str(),
|
||||
field.ident.node)
|
||||
}
|
||||
None => {
|
||||
format!("structure `{}` has no field named `{}`",
|
||||
actual,
|
||||
field.ident.node)
|
||||
}
|
||||
},
|
||||
struct_ty,
|
||||
None);
|
||||
// prevent all specified fields from being suggested
|
||||
let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
|
||||
let actual_id = match enum_id_opt {
|
||||
Some(_) => class_id,
|
||||
None => struct_ty.ty_to_def_id().unwrap()
|
||||
};
|
||||
suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
|
||||
if let Some(v_field) = remaining_fields.remove(&field.ident.node.name) {
|
||||
expected_field_type = fcx.field_ty(field.span, v_field, substs);
|
||||
} else {
|
||||
error_happened = true;
|
||||
}
|
||||
Some((_, true)) => {
|
||||
expected_field_type = tcx.types.err;
|
||||
if let Some(_) = variant.find_field_named(field.ident.node.name) {
|
||||
span_err!(fcx.tcx().sess, field.ident.span, E0062,
|
||||
"field `{}` specified more than once",
|
||||
field.ident.node);
|
||||
error_happened = true;
|
||||
}
|
||||
Some((field_id, false)) => {
|
||||
expected_field_type =
|
||||
tcx.lookup_field_type(class_id, field_id, substitutions);
|
||||
expected_field_type =
|
||||
fcx.normalize_associated_types_in(
|
||||
field.span, &expected_field_type);
|
||||
class_field_map.insert(
|
||||
field.ident.node.name, (field_id, true));
|
||||
fields_found += 1;
|
||||
} else {
|
||||
report_unknown_field(fcx, adt_ty, variant, field, ast_fields);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3102,40 +3074,28 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
|
||||
}
|
||||
|
||||
if error_happened {
|
||||
fcx.write_error(node_id);
|
||||
}
|
||||
|
||||
if check_completeness && !error_happened {
|
||||
// Make sure the programmer specified all the fields.
|
||||
assert!(fields_found <= field_types.len());
|
||||
if fields_found < field_types.len() {
|
||||
let mut missing_fields = Vec::new();
|
||||
for class_field in field_types {
|
||||
let name = class_field.name;
|
||||
let (_, seen) = *class_field_map.get(&name).unwrap();
|
||||
if !seen {
|
||||
missing_fields.push(
|
||||
format!("`{}`", name))
|
||||
}
|
||||
}
|
||||
|
||||
if check_completeness &&
|
||||
!error_happened &&
|
||||
!remaining_fields.is_empty()
|
||||
{
|
||||
error_happened = true;
|
||||
span_err!(tcx.sess, span, E0063,
|
||||
"missing field{}: {}",
|
||||
if missing_fields.len() == 1 {""} else {"s"},
|
||||
missing_fields.join(", "));
|
||||
}
|
||||
if remaining_fields.len() == 1 {""} else {"s"},
|
||||
remaining_fields.keys()
|
||||
.map(|n| format!("`{}`", n))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "));
|
||||
}
|
||||
|
||||
if !error_happened {
|
||||
fcx.write_ty(node_id, fcx.ccx.tcx.mk_struct(class_id, substitutions));
|
||||
}
|
||||
if error_happened { Err(()) } else { Ok(()) }
|
||||
}
|
||||
|
||||
fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|
||||
id: ast::NodeId,
|
||||
span: codemap::Span,
|
||||
class_id: ast::DefId,
|
||||
struct_def: ty::AdtDef<'tcx>,
|
||||
fields: &'tcx [ast::Field],
|
||||
base_expr: Option<&'tcx ast::Expr>) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
@ -3143,22 +3103,17 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
// Generate the struct type.
|
||||
let TypeAndSubsts {
|
||||
ty: mut struct_type,
|
||||
substs: struct_substs
|
||||
} = fcx.instantiate_type(span, class_id);
|
||||
substs: _
|
||||
} = fcx.instantiate_type(span, struct_def.did);
|
||||
|
||||
// Look up and check the fields.
|
||||
let class_fields = tcx.lookup_struct_fields(class_id);
|
||||
check_struct_or_variant_fields(fcx,
|
||||
let res = check_struct_or_variant_fields(fcx,
|
||||
struct_type,
|
||||
span,
|
||||
class_id,
|
||||
id,
|
||||
fcx.ccx.tcx.mk_substs(struct_substs),
|
||||
&class_fields[..],
|
||||
struct_def.did,
|
||||
fields,
|
||||
base_expr.is_none(),
|
||||
None);
|
||||
if fcx.node_ty(id).references_error() {
|
||||
base_expr.is_none());
|
||||
if res.is_err() {
|
||||
struct_type = tcx.types.err;
|
||||
}
|
||||
|
||||
|
@ -3180,27 +3135,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
enum_id: ast::DefId,
|
||||
variant_id: ast::DefId,
|
||||
fields: &'tcx [ast::Field]) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
// Look up the number of type parameters and the raw type, and
|
||||
// determine whether the enum is region-parameterized.
|
||||
let TypeAndSubsts {
|
||||
ty: enum_type,
|
||||
substs: substitutions
|
||||
substs: _
|
||||
} = fcx.instantiate_type(span, enum_id);
|
||||
|
||||
// Look up and check the enum variant fields.
|
||||
let variant_fields = tcx.lookup_struct_fields(variant_id);
|
||||
check_struct_or_variant_fields(fcx,
|
||||
let _ = check_struct_or_variant_fields(fcx,
|
||||
enum_type,
|
||||
span,
|
||||
variant_id,
|
||||
id,
|
||||
fcx.ccx.tcx.mk_substs(substitutions),
|
||||
&variant_fields[..],
|
||||
fields,
|
||||
true,
|
||||
Some(enum_id));
|
||||
true);
|
||||
fcx.write_ty(id, enum_type);
|
||||
}
|
||||
|
||||
|
@ -3695,11 +3643,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
// Verify that this was actually a struct.
|
||||
let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
|
||||
match typ.ty.sty {
|
||||
ty::TyStruct(struct_did, _) => {
|
||||
ty::TyStruct(struct_def, _) => {
|
||||
check_struct_constructor(fcx,
|
||||
id,
|
||||
expr.span,
|
||||
struct_did,
|
||||
struct_def,
|
||||
&fields[..],
|
||||
base_expr.as_ref().map(|e| &**e));
|
||||
}
|
||||
|
@ -3835,6 +3783,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
};
|
||||
|
||||
if let Some(did) = did {
|
||||
let def = tcx.lookup_adt_def(did);
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let substs = Substs::new_type(vec![idx_type], vec![]);
|
||||
let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
|
||||
|
@ -3844,7 +3793,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
traits::ItemObligation(did)),
|
||||
&bounds);
|
||||
|
||||
tcx.mk_struct(did, tcx.mk_substs(substs))
|
||||
tcx.mk_struct(def, tcx.mk_substs(substs))
|
||||
} else {
|
||||
span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
|
||||
fcx.tcx().types.err
|
||||
|
@ -3853,8 +3802,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
None => {
|
||||
// Neither start nor end => RangeFull
|
||||
if let Some(did) = tcx.lang_items.range_full_struct() {
|
||||
let substs = Substs::new_type(vec![], vec![]);
|
||||
tcx.mk_struct(did, tcx.mk_substs(substs))
|
||||
tcx.mk_struct(
|
||||
tcx.lookup_adt_def(did),
|
||||
tcx.mk_substs(Substs::empty())
|
||||
)
|
||||
} else {
|
||||
span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
|
||||
fcx.tcx().types.err
|
||||
|
@ -4305,15 +4256,14 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
|
|||
return;
|
||||
}
|
||||
match t.sty {
|
||||
ty::TyStruct(did, substs) => {
|
||||
let fields = tcx.lookup_struct_fields(did);
|
||||
ty::TyStruct(def, substs) => {
|
||||
let fields = &def.struct_variant().fields;
|
||||
if fields.is_empty() {
|
||||
span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
|
||||
return;
|
||||
}
|
||||
let e = tcx.lookup_field_type(did, fields[0].id, substs);
|
||||
if !fields.iter().all(
|
||||
|f| tcx.lookup_field_type(did, f.id, substs) == e) {
|
||||
let e = fields[0].ty(tcx, substs);
|
||||
if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
|
||||
span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
|
||||
return;
|
||||
}
|
||||
|
@ -4381,10 +4331,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
|||
|
||||
let def_id = local_def(id);
|
||||
|
||||
// ty::enum_variants guards against discriminant overflows, so
|
||||
// we need not check for that.
|
||||
let variants = ccx.tcx.enum_variants(def_id);
|
||||
|
||||
let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
|
||||
for (v, variant) in vs.iter().zip(variants.iter()) {
|
||||
let current_disr_val = variant.disr_val;
|
||||
|
||||
|
@ -4393,7 +4340,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
|||
Some(i) => {
|
||||
span_err!(ccx.tcx.sess, v.span, E0081,
|
||||
"discriminant value `{}` already exists", disr_vals[i]);
|
||||
span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
|
||||
span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].did.node),
|
||||
"conflicting discriminant here")
|
||||
}
|
||||
None => {}
|
||||
|
|
|
@ -21,7 +21,7 @@ use super::{
|
|||
structurally_resolved_type,
|
||||
};
|
||||
use middle::traits;
|
||||
use middle::ty::{self, Ty, HasTypeFlags};
|
||||
use middle::ty::{Ty, HasTypeFlags};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
use syntax::parse::token;
|
||||
|
@ -41,7 +41,7 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|
|||
let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr));
|
||||
let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr));
|
||||
|
||||
if is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) {
|
||||
if is_builtin_binop(lhs_ty, rhs_ty, op) {
|
||||
enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
||||
fcx.write_nil(expr.id);
|
||||
} else {
|
||||
|
@ -86,7 +86,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
// traits, because their return type is not bool. Perhaps this
|
||||
// should change, but for now if LHS is SIMD we go down a
|
||||
// different path that bypassess all traits.
|
||||
if lhs_ty.is_simd(fcx.tcx()) {
|
||||
if lhs_ty.is_simd() {
|
||||
check_expr_coercable_to_type(fcx, rhs_expr, lhs_ty);
|
||||
let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr));
|
||||
let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
||||
|
@ -123,7 +123,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty);
|
||||
if
|
||||
!lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() &&
|
||||
is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op)
|
||||
is_builtin_binop(lhs_ty, rhs_ty, op)
|
||||
{
|
||||
let builtin_return_ty =
|
||||
enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
|
||||
|
@ -143,7 +143,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
op: ast::BinOp)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
debug_assert!(is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op));
|
||||
debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op));
|
||||
|
||||
let tcx = fcx.tcx();
|
||||
match BinOpCategory::from(op) {
|
||||
|
@ -156,7 +156,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
BinOpCategory::Shift => {
|
||||
// For integers, the shift amount can be of any integral
|
||||
// type. For simd, the type must match exactly.
|
||||
if lhs_ty.is_simd(tcx) {
|
||||
if lhs_ty.is_simd() {
|
||||
demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);
|
||||
|
||||
// if this is simd, result is same as lhs, else bool
|
||||
if lhs_ty.is_simd(tcx) {
|
||||
if lhs_ty.is_simd() {
|
||||
let unit_ty = lhs_ty.simd_type(tcx);
|
||||
debug!("enforce_builtin_binop_types: lhs_ty={:?} unit_ty={:?}",
|
||||
lhs_ty,
|
||||
|
@ -415,8 +415,7 @@ impl BinOpCategory {
|
|||
/// Reason #2 is the killer. I tried for a while to always use
|
||||
/// overloaded logic and just check the types in constants/trans after
|
||||
/// the fact, and it worked fine, except for SIMD types. -nmatsakis
|
||||
fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>,
|
||||
lhs: Ty<'tcx>,
|
||||
fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>,
|
||||
rhs: Ty<'tcx>,
|
||||
op: ast::BinOp)
|
||||
-> bool
|
||||
|
@ -429,28 +428,28 @@ fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>,
|
|||
BinOpCategory::Shift => {
|
||||
lhs.references_error() || rhs.references_error() ||
|
||||
lhs.is_integral() && rhs.is_integral() ||
|
||||
lhs.is_simd(cx) && rhs.is_simd(cx)
|
||||
lhs.is_simd() && rhs.is_simd()
|
||||
}
|
||||
|
||||
BinOpCategory::Math => {
|
||||
lhs.references_error() || rhs.references_error() ||
|
||||
lhs.is_integral() && rhs.is_integral() ||
|
||||
lhs.is_floating_point() && rhs.is_floating_point() ||
|
||||
lhs.is_simd(cx) && rhs.is_simd(cx)
|
||||
lhs.is_simd() && rhs.is_simd()
|
||||
}
|
||||
|
||||
BinOpCategory::Bitwise => {
|
||||
lhs.references_error() || rhs.references_error() ||
|
||||
lhs.is_integral() && rhs.is_integral() ||
|
||||
lhs.is_floating_point() && rhs.is_floating_point() ||
|
||||
lhs.is_simd(cx) && rhs.is_simd(cx) ||
|
||||
lhs.is_simd() && rhs.is_simd() ||
|
||||
lhs.is_bool() && rhs.is_bool()
|
||||
}
|
||||
|
||||
BinOpCategory::Comparison => {
|
||||
lhs.references_error() || rhs.references_error() ||
|
||||
lhs.is_scalar() && rhs.is_scalar() ||
|
||||
lhs.is_simd(cx) && rhs.is_simd(cx)
|
||||
lhs.is_simd() && rhs.is_simd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -571,9 +571,9 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
|
|||
}
|
||||
|
||||
match t.sty{
|
||||
ty::TyStruct(type_id, substs) |
|
||||
ty::TyEnum(type_id, substs) => {
|
||||
let type_predicates = self.fcx.tcx().lookup_predicates(type_id);
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
let type_predicates = def.predicates(self.fcx.tcx());
|
||||
let bounds = self.fcx.instantiate_bounds(self.span, substs,
|
||||
&type_predicates);
|
||||
|
||||
|
@ -581,7 +581,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
|
|||
self.fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(self.span,
|
||||
self.fcx.body_id,
|
||||
traits::ItemObligation(type_id)),
|
||||
traits::ItemObligation(def.did)),
|
||||
&bounds);
|
||||
} else {
|
||||
// There are two circumstances in which we ignore
|
||||
|
@ -610,7 +610,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
|
|||
self.fcx.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(self.span,
|
||||
self.fcx.body_id,
|
||||
traits::ItemObligation(type_id)),
|
||||
traits::ItemObligation(def.did)),
|
||||
&bounds);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
|
|||
ty: Ty<'tcx>)
|
||||
-> Option<DefId> {
|
||||
match ty.sty {
|
||||
TyEnum(def_id, _) |
|
||||
TyStruct(def_id, _) => {
|
||||
Some(def_id)
|
||||
TyEnum(def, _) |
|
||||
TyStruct(def, _) => {
|
||||
Some(def.did)
|
||||
}
|
||||
|
||||
TyTrait(ref t) => {
|
||||
|
@ -310,12 +310,11 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
|
||||
let self_type = tcx.lookup_item_type(impl_did);
|
||||
match self_type.ty.sty {
|
||||
ty::TyEnum(type_def_id, _) |
|
||||
ty::TyStruct(type_def_id, _) |
|
||||
ty::TyClosure(type_def_id, _) => {
|
||||
ty::TyEnum(type_def, _) |
|
||||
ty::TyStruct(type_def, _) => {
|
||||
tcx.destructor_for_type
|
||||
.borrow_mut()
|
||||
.insert(type_def_id, method_def_id.def_id());
|
||||
.insert(type_def.did, method_def_id.def_id());
|
||||
tcx.destructors
|
||||
.borrow_mut()
|
||||
.insert(method_def_id.def_id());
|
||||
|
@ -471,10 +470,10 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
|
||||
}
|
||||
|
||||
(&ty::TyStruct(def_id_a, substs_a), &ty::TyStruct(def_id_b, substs_b)) => {
|
||||
if def_id_a != def_id_b {
|
||||
let source_path = tcx.item_path_str(def_id_a);
|
||||
let target_path = tcx.item_path_str(def_id_b);
|
||||
(&ty::TyStruct(def_a, substs_a), &ty::TyStruct(def_b, substs_b)) => {
|
||||
if def_a != def_b {
|
||||
let source_path = tcx.item_path_str(def_a.did);
|
||||
let target_path = tcx.item_path_str(def_b.did);
|
||||
span_err!(tcx.sess, span, E0377,
|
||||
"the trait `CoerceUnsized` may only be implemented \
|
||||
for a coercion between structures with the same \
|
||||
|
@ -484,10 +483,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let origin = infer::Misc(span);
|
||||
let fields = tcx.lookup_struct_fields(def_id_a);
|
||||
let fields = &def_a.struct_variant().fields;
|
||||
let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| {
|
||||
let ty = tcx.lookup_field_type_unsubstituted(def_id_a, f.id);
|
||||
let (a, b) = (ty.subst(tcx, substs_a), ty.subst(tcx, substs_b));
|
||||
let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
|
||||
if infcx.sub_types(false, origin, b, a).is_ok() {
|
||||
None
|
||||
} else {
|
||||
|
|
|
@ -69,9 +69,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
|||
self.tcx.map.node_to_string(item.id));
|
||||
let self_ty = self.tcx.lookup_item_type(def_id).ty;
|
||||
match self_ty.sty {
|
||||
ty::TyEnum(def_id, _) |
|
||||
ty::TyStruct(def_id, _) => {
|
||||
self.check_def_id(item, def_id);
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) => {
|
||||
self.check_def_id(item, def.did);
|
||||
}
|
||||
ty::TyTrait(ref data) => {
|
||||
self.check_def_id(item, data.principal_def_id());
|
||||
|
@ -279,8 +279,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
|||
{
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let opt_self_def_id = match self_ty.sty {
|
||||
ty::TyStruct(self_def_id, _) | ty::TyEnum(self_def_id, _) =>
|
||||
Some(self_def_id),
|
||||
ty::TyStruct(self_def, _) | ty::TyEnum(self_def, _) =>
|
||||
Some(self_def.did),
|
||||
ty::TyBox(..) =>
|
||||
self.tcx.lang_items.owned_box(),
|
||||
_ =>
|
||||
|
|
|
@ -71,9 +71,12 @@ use middle::lang_items::SizedTraitLangItem;
|
|||
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 std::rc::Rc;
|
|||
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,10 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
struct_generics: &ty::Generics<'tcx>,
|
||||
struct_predicates: &ty::GenericPredicates<'tcx>,
|
||||
v: &ast::StructField,
|
||||
origin: ast::DefId)
|
||||
-> ty::FieldTy
|
||||
ty_f: ty::FieldDefMaster<'tcx>)
|
||||
{
|
||||
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 */
|
||||
|
@ -671,25 +634,6 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
});
|
||||
ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
|
||||
struct_predicates.clone());
|
||||
|
||||
match v.node.kind {
|
||||
ast::NamedField(ident, visibility) => {
|
||||
ty::FieldTy {
|
||||
name: ident.name,
|
||||
id: local_def(v.node.id),
|
||||
vis: visibility,
|
||||
origin: origin,
|
||||
}
|
||||
}
|
||||
ast::UnnamedField(visibility) => {
|
||||
ty::FieldTy {
|
||||
name: special_idents::unnamed_field.name,
|
||||
id: local_def(v.node.id),
|
||||
vis: visibility,
|
||||
origin: origin,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
@ -803,7 +747,8 @@ 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,
|
||||
convert_enum_variant_types(ccx,
|
||||
tcx.lookup_adt_def_master(local_def(it.id)),
|
||||
scheme,
|
||||
predicates,
|
||||
&enum_definition.variants);
|
||||
|
@ -1048,10 +993,18 @@ 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_master(local_def(it.id)).struct_variant();
|
||||
|
||||
for (f, ty_f) in struct_def.fields.iter().zip(variant.fields.iter()) {
|
||||
convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
|
||||
}
|
||||
|
||||
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,76 +1021,226 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
struct_def: &ast::StructDef,
|
||||
fn convert_variant_ctor<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
ctor_id: ast::NodeId,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
scheme: ty::TypeScheme<'tcx>,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
id: ast::NodeId) {
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
// 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));
|
||||
|
||||
if result.name != special_idents::unnamed_field.name {
|
||||
let dup = match seen_fields.get(&result.name) {
|
||||
Some(prev_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);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}).collect();
|
||||
|
||||
tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
|
||||
|
||||
let substs = mk_item_substs(ccx, &scheme.generics);
|
||||
let selfty = tcx.mk_struct(local_def(id), tcx.mk_substs(substs));
|
||||
|
||||
// If this struct is enum-like or tuple-like, create the type of its
|
||||
// constructor.
|
||||
match struct_def.ctor_id {
|
||||
None => {}
|
||||
Some(ctor_id) => {
|
||||
if struct_def.fields.is_empty() {
|
||||
// Enum-like.
|
||||
write_ty_to_tcx(tcx, ctor_id, selfty);
|
||||
|
||||
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.
|
||||
predicates: ty::GenericPredicates<'tcx>) {
|
||||
let ctor_ty = match variant.kind() {
|
||||
VariantKind::Unit | VariantKind::Dict => scheme.ty,
|
||||
VariantKind::Tuple => {
|
||||
let inputs: Vec<_> =
|
||||
struct_def.fields
|
||||
variant.fields
|
||||
.iter()
|
||||
.map(|field| tcx.lookup_item_type(
|
||||
local_def(field.node.id)).ty)
|
||||
.map(|field| field.unsubst_ty())
|
||||
.collect();
|
||||
let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
|
||||
tcx.mk_ctor_fn(local_def(ctor_id),
|
||||
&inputs[..],
|
||||
selfty);
|
||||
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
|
||||
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_fn_ty
|
||||
ty: ctor_ty
|
||||
});
|
||||
tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
|
||||
}
|
||||
|
||||
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
def: ty::AdtDefMaster<'tcx>,
|
||||
scheme: ty::TypeScheme<'tcx>,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
variants: &[P<ast::Variant>]) {
|
||||
let tcx = ccx.tcx;
|
||||
let icx = ccx.icx(&predicates);
|
||||
|
||||
// fill the field types
|
||||
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) => {
|
||||
for (f, ty_f) in struct_def.fields.iter().zip(ty_variant.fields.iter()) {
|
||||
convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the ctor, if any. This also registers the variant as
|
||||
// an item.
|
||||
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::VariantDefData<'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",
|
||||
ident.name);
|
||||
span_note!(tcx.sess, prev_span, "previously declared here");
|
||||
} else {
|
||||
seen_fields.insert(ident.name, f.span);
|
||||
}
|
||||
|
||||
ty::FieldDefData::new(fid, ident.name, vis)
|
||||
},
|
||||
ast::UnnamedField(vis) => {
|
||||
ty::FieldDefData::new(fid, special_idents::unnamed_field.name, vis)
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
ty::VariantDefData {
|
||||
did: did,
|
||||
name: name,
|
||||
disr_val: disr_val,
|
||||
fields: fields
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
it: &ast::Item,
|
||||
def: &ast::StructDef)
|
||||
-> ty::AdtDefMaster<'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)]
|
||||
)
|
||||
}
|
||||
|
||||
fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
it: &ast::Item,
|
||||
def: &ast::EnumDef)
|
||||
-> ty::AdtDefMaster<'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_ty.is_signed() {
|
||||
"signed"
|
||||
} else {
|
||||
"unsigned"
|
||||
};
|
||||
span_err!(tcx.sess, e.span, E0079,
|
||||
"expected {} integer constant",
|
||||
sign_desc);
|
||||
None
|
||||
},
|
||||
Err(err) => {
|
||||
span_err!(tcx.sess, err.span, E0080,
|
||||
"constant evaluation error: {}",
|
||||
err.description());
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_discrim_overflow(tcx: &ty::ctxt,
|
||||
variant_span: Span,
|
||||
variant_name: &str,
|
||||
repr_type: attr::IntType,
|
||||
prev_val: ty::Disr) {
|
||||
let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
|
||||
let computed_value = repr_type.disr_string(computed_value);
|
||||
let prev_val = repr_type.disr_string(prev_val);
|
||||
let repr_type = repr_type.to_ty(tcx);
|
||||
span_err!(tcx.sess, variant_span, E0370,
|
||||
"enum discriminant overflowed on value after {}: {}; \
|
||||
set explicitly via {} = {} if that is desired outcome",
|
||||
prev_val, repr_type, variant_name, computed_value);
|
||||
}
|
||||
|
||||
fn next_disr(tcx: &ty::ctxt,
|
||||
v: &ast::Variant,
|
||||
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 {
|
||||
report_discrim_overflow(tcx, 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::VariantDefData<'tcx, 'tcx>
|
||||
{
|
||||
let did = local_def(v.node.id);
|
||||
let name = v.node.name.name;
|
||||
match v.node.kind {
|
||||
ast::TupleVariantKind(ref va) => {
|
||||
ty::VariantDefData {
|
||||
did: did,
|
||||
name: name,
|
||||
disr_val: disr,
|
||||
fields: va.iter().map(|&ast::VariantArg { id, .. }| {
|
||||
ty::FieldDefData::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(tcx, v, 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
|
||||
|
@ -1471,17 +1574,18 @@ 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 t = tcx.mk_enum(local_def(it.id), tcx.mk_substs(substs));
|
||||
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 t = tcx.mk_struct(local_def(it.id), tcx.mk_substs(substs));
|
||||
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 }
|
||||
}
|
||||
ast::ItemDefaultImpl(..) |
|
||||
|
|
|
@ -883,6 +883,64 @@ struct Good(u32, u32, u32); // This will not
|
|||
```
|
||||
"##,
|
||||
|
||||
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
|
||||
"##,
|
||||
|
||||
E0081: r##"
|
||||
Enum discriminants are used to differentiate enum variants stored in memory.
|
||||
This error indicates that the same value was used for two or more variants,
|
||||
|
@ -2510,6 +2568,7 @@ register_diagnostics! {
|
|||
E0366, // dropck forbid specialization to concrete type or region
|
||||
E0367, // dropck forbid specialization to predicate not in struct/enum
|
||||
E0369, // binary operation `<op>` cannot be applied to types
|
||||
E0370, // discriminant overflow
|
||||
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
|
||||
// between structures with one field being coerced, none found
|
||||
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
|
||||
|
|
|
@ -602,7 +602,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
|
|||
debug!("visit_item item={}", tcx.map.node_to_string(item.id));
|
||||
|
||||
match item.node {
|
||||
ast::ItemEnum(ref enum_definition, _) => {
|
||||
ast::ItemEnum(..) | ast::ItemStruct(..) => {
|
||||
let scheme = tcx.lookup_item_type(did);
|
||||
|
||||
// Not entirely obvious: constraints on structs/enums do not
|
||||
|
@ -611,44 +611,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
|
|||
//
|
||||
// self.add_constraints_from_generics(&scheme.generics);
|
||||
|
||||
// Hack: If we directly call `ty::enum_variants`, it
|
||||
// annoyingly takes it upon itself to run off and
|
||||
// evaluate the discriminants eagerly (*grumpy* that's
|
||||
// not the typical pattern). This results in double
|
||||
// error messages because typeck goes off and does
|
||||
// this at a later time. All we really care about is
|
||||
// the types of the variant arguments, so we just call
|
||||
// `ty::VariantInfo::from_ast_variant()` ourselves
|
||||
// here, mainly so as to mask the differences between
|
||||
// struct-like enums and so forth.
|
||||
for ast_variant in &enum_definition.variants {
|
||||
let variant =
|
||||
ty::VariantInfo::from_ast_variant(tcx,
|
||||
&**ast_variant,
|
||||
/*discriminant*/ 0);
|
||||
for arg_ty in &variant.args {
|
||||
self.add_constraints_from_ty(&scheme.generics, *arg_ty, self.covariant);
|
||||
for field in tcx.lookup_adt_def(did).all_fields() {
|
||||
self.add_constraints_from_ty(&scheme.generics,
|
||||
field.unsubst_ty(),
|
||||
self.covariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemStruct(..) => {
|
||||
let scheme = tcx.lookup_item_type(did);
|
||||
|
||||
// Not entirely obvious: constraints on structs/enums do not
|
||||
// affect the variance of their type parameters. See discussion
|
||||
// in comment at top of module.
|
||||
//
|
||||
// self.add_constraints_from_generics(&scheme.generics);
|
||||
|
||||
let struct_fields = tcx.lookup_struct_fields(did);
|
||||
for field_info in &struct_fields {
|
||||
assert_eq!(field_info.id.krate, ast::LOCAL_CRATE);
|
||||
let field_ty = tcx.node_id_to_type(field_info.id.node);
|
||||
self.add_constraints_from_ty(&scheme.generics, field_ty, self.covariant);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemTrait(..) => {
|
||||
let trait_def = tcx.lookup_trait_def(did);
|
||||
self.add_constraints_from_trait_ref(&trait_def.generics,
|
||||
|
@ -902,9 +870,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::TyEnum(def_id, substs) |
|
||||
ty::TyStruct(def_id, substs) => {
|
||||
let item_type = self.tcx().lookup_item_type(def_id);
|
||||
ty::TyEnum(def, substs) |
|
||||
ty::TyStruct(def, substs) => {
|
||||
let item_type = self.tcx().lookup_item_type(def.did);
|
||||
|
||||
// All type parameters on enums and structs should be
|
||||
// in the TypeSpace.
|
||||
|
@ -915,7 +883,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
|
||||
self.add_constraints_from_substs(
|
||||
generics,
|
||||
def_id,
|
||||
def.did,
|
||||
item_type.generics.types.get_slice(subst::TypeSpace),
|
||||
item_type.generics.regions.get_slice(subst::TypeSpace),
|
||||
substs,
|
||||
|
|
|
@ -185,17 +185,17 @@ fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Stru
|
|||
|
||||
let t = tcx.lookup_item_type(did);
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let fields = tcx.lookup_struct_fields(did);
|
||||
let variant = tcx.lookup_adt_def(did).struct_variant();
|
||||
|
||||
clean::Struct {
|
||||
struct_type: match &*fields {
|
||||
struct_type: match &*variant.fields {
|
||||
[] => doctree::Unit,
|
||||
[ref f] if f.name == unnamed_field.name => doctree::Newtype,
|
||||
[ref f, ..] if f.name == unnamed_field.name => doctree::Tuple,
|
||||
_ => doctree::Plain,
|
||||
},
|
||||
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
|
||||
fields: fields.clean(cx),
|
||||
fields: variant.fields.clean(cx),
|
||||
fields_stripped: false,
|
||||
}
|
||||
}
|
||||
|
@ -204,11 +204,11 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
|
|||
let t = tcx.lookup_item_type(did);
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
match t.ty.sty {
|
||||
ty::TyEnum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
|
||||
ty::TyEnum(edef, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
|
||||
return clean::EnumItem(clean::Enum {
|
||||
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
|
||||
variants_stripped: false,
|
||||
variants: tcx.enum_variants(edid).clean(cx),
|
||||
variants: edef.variants.clean(cx),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -1661,8 +1661,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
|
|||
decl: (ast_util::local_def(0), &fty.sig).clean(cx),
|
||||
abi: fty.abi.to_string(),
|
||||
}),
|
||||
ty::TyStruct(did, substs) |
|
||||
ty::TyEnum(did, substs) => {
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
let did = def.did;
|
||||
let fqn = csearch::get_item_path(cx.tcx(), did);
|
||||
let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
|
||||
let kind = match self.sty {
|
||||
|
@ -1732,29 +1733,27 @@ impl Clean<Item> for ast::StructField {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for ty::FieldTy {
|
||||
impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
use syntax::parse::token::special_idents::unnamed_field;
|
||||
use rustc::metadata::csearch;
|
||||
|
||||
let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.id);
|
||||
let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.did);
|
||||
|
||||
let (name, attrs) = if self.name == unnamed_field.name {
|
||||
(None, None)
|
||||
} else {
|
||||
(Some(self.name), Some(attr_map.get(&self.id.node).unwrap()))
|
||||
(Some(self.name), Some(attr_map.get(&self.did.node).unwrap()))
|
||||
};
|
||||
|
||||
let ty = cx.tcx().lookup_item_type(self.id);
|
||||
|
||||
Item {
|
||||
name: name.clean(cx),
|
||||
attrs: attrs.unwrap_or(&Vec::new()).clean(cx),
|
||||
source: Span::empty(),
|
||||
visibility: Some(self.vis),
|
||||
stability: get_stability(cx, self.id),
|
||||
def_id: self.id,
|
||||
inner: StructFieldItem(TypedStructField(ty.ty.clean(cx))),
|
||||
stability: get_stability(cx, self.did),
|
||||
def_id: self.did,
|
||||
inner: StructFieldItem(TypedStructField(self.unsubst_ty().clean(cx))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1860,22 +1859,24 @@ impl Clean<Item> for doctree::Variant {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
|
||||
impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
// use syntax::parse::token::special_idents::unnamed_field;
|
||||
let kind = match self.arg_names.as_ref().map(|s| &**s) {
|
||||
None | Some([]) if self.args.is_empty() => CLikeVariant,
|
||||
None | Some([]) => {
|
||||
TupleVariant(self.args.clean(cx))
|
||||
let kind = match self.kind() {
|
||||
ty::VariantKind::Unit => CLikeVariant,
|
||||
ty::VariantKind::Tuple => {
|
||||
TupleVariant(
|
||||
self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
|
||||
)
|
||||
}
|
||||
Some(s) => {
|
||||
ty::VariantKind::Dict => {
|
||||
StructVariant(VariantStruct {
|
||||
struct_type: doctree::Plain,
|
||||
fields_stripped: false,
|
||||
fields: s.iter().zip(&self.args).map(|(name, ty)| {
|
||||
fields: self.fields.iter().map(|field| {
|
||||
Item {
|
||||
source: Span::empty(),
|
||||
name: Some(name.clean(cx)),
|
||||
name: Some(field.name.clean(cx)),
|
||||
attrs: Vec::new(),
|
||||
visibility: Some(ast::Public),
|
||||
// FIXME: this is not accurate, we need an id for
|
||||
|
@ -1885,10 +1886,10 @@ impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
|
|||
// Struct variants are experimental and need
|
||||
// more infrastructure work before we can get
|
||||
// at the needed information here.
|
||||
def_id: self.id,
|
||||
stability: get_stability(cx, self.id),
|
||||
def_id: self.did,
|
||||
stability: get_stability(cx, self.did),
|
||||
inner: StructFieldItem(
|
||||
TypedStructField(ty.clean(cx))
|
||||
TypedStructField(field.unsubst_ty().clean(cx))
|
||||
)
|
||||
}
|
||||
}).collect()
|
||||
|
@ -1897,12 +1898,12 @@ impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
|
|||
};
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: inline::load_attrs(cx, cx.tcx(), self.id),
|
||||
attrs: inline::load_attrs(cx, cx.tcx(), self.did),
|
||||
source: Span::empty(),
|
||||
visibility: Some(ast::Public),
|
||||
def_id: self.id,
|
||||
def_id: self.did,
|
||||
inner: VariantItem(Variant { kind: kind }),
|
||||
stability: get_stability(cx, self.id),
|
||||
stability: get_stability(cx, self.did),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
|
||||
trait Trait { fn dummy(&self) { } }
|
||||
trait Mirror { type Image; }
|
||||
impl<T> Mirror for T { type Image = T; }
|
||||
struct ParamTypeStruct<T>(T);
|
||||
struct AssocTypeStruct<T>(<T as Mirror>::Image);
|
||||
|
||||
fn main() {
|
||||
// Functions
|
||||
|
@ -66,4 +70,7 @@ fn main() {
|
|||
// Should apply to types that have NonZero transitively
|
||||
assert_eq!(size_of::<String>(), size_of::<Option<String>>());
|
||||
|
||||
// Should apply to types where the pointer is substituted
|
||||
assert_eq!(size_of::<&u8>(), size_of::<Option<ParamTypeStruct<&u8>>>());
|
||||
assert_eq!(size_of::<&u8>(), size_of::<Option<AssocTypeStruct<&u8>>>());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue