提交 5f3c1412 编写于 作者: A Ariel Ben-Yehuda 提交者: Ariel Ben-Yehuda

use VariantDef instead of struct_fields

上级 4816e606
......@@ -692,64 +692,6 @@ trait Super<A> {
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 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
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
}
......@@ -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)),
......
......@@ -237,9 +237,9 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
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(edef.did).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 \
......@@ -508,16 +508,10 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
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.did, vid).arg_names.is_some()),
_ =>
(cid.did, !cid.struct_variant().is_tuple_struct())
};
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<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, 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,15 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
})
}
impl<'tcx> ADTDef<'tcx> {
fn variant_of_ctor(&'tcx self, ctor: &Constructor) -> &'tcx VariantDef<'tcx> {
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 +597,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 +606,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(edef, _) =>
cx.tcx.enum_variants(edef.did)
.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 +801,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 +814,9 @@ pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usi
ty::TyStr => 0,
_ => 1
},
ty::TyEnum(edef, _) => {
match *ctor {
Variant(id) => cx.tcx.enum_variant_with_id(edef.did, id).args.len(),
_ => unreachable!()
}
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
adt.variant_of_ctor(ctor).fields.len()
}
ty::TyStruct(cdef, _) => cx.tcx.lookup_struct_fields(cdef.did).len(),
ty::TyArray(_, n) => n,
_ => 0
}
......@@ -902,39 +895,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 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId) {
}
fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) {
match self.tcx.expr_ty_adjusted(lhs).sty {
ty::TyStruct(def, _) => {
let fields = self.tcx.lookup_struct_fields(def.did);
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(def, _) => {
let fields = self.tcx.lookup_struct_fields(def.did);
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,40 +694,36 @@ fn walk_struct_expr(&mut self,
// Select just those fields of the `with`
// expression that will actually be used
let with_fields = match with_cmt.ty.sty {
ty::TyStruct(def, substs) => {
self.tcx().struct_fields(def.did, substs)
}
_ => {
// the base expression should always evaluate to a
// struct; however, when EUV is run during typeck, it
// may not. This will generate an error earlier in typeck,
// so we can just ignore it.
if !self.tcx().sess.has_errors() {
self.tcx().sess.span_bug(
with_expr.span,
"with expression doesn't evaluate to a struct");
if let ty::TyStruct(def, substs) = with_cmt.ty.sty {
// Consume those fields of the with expression that are needed.
for with_field in &def.struct_variant().fields {
if !contains_field_named(with_field, fields) {
let cmt_field = self.mc.cat_field(
&*with_expr,
with_cmt.clone(),
with_field.name,
with_field.ty(self.tcx(), substs)
);
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
}
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);
} else {
// the base expression should always evaluate to a
// struct; however, when EUV is run during typeck, it
// may not. This will generate an error earlier in typeck,
// so we can just ignore it.
if !self.tcx().sess.has_errors() {
self.tcx().sess.span_bug(
with_expr.span,
"with expression doesn't evaluate to a struct");
}
}
};
// 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
{
......@@ -1105,7 +1101,7 @@ fn walk_pat(&mut self,
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;
......
......@@ -1216,7 +1216,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
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(def, _) => {
tcx.lookup_struct_fields(def.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(def, _) => {
tcx.lookup_struct_fields(def.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 \
......@@ -451,19 +434,12 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
let type_ = tcx.expr_ty(e);
match type_.sty {
ty::TyStruct(def, _) => {
let struct_fields = tcx.lookup_struct_fields(def.did);
// 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 def = match tcx.pat_ty_opt(pat) {
Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) => def,
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(def.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);
}
}
......
......@@ -1721,21 +1721,10 @@ fn builtin_bound(&mut self,
ok_if(substs.upvar_tys.clone())
}
ty::TyStruct(def, substs) => {
let types: Vec<Ty> =
self.tcx().struct_fields(def.did, substs).iter()
.map(|f| f.mt.ty)
.collect();
nominal(bound, types)
}
ty::TyEnum(def, substs) => {
let types: Vec<Ty> =
self.tcx().substd_enum_variants(def.did, 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)
}
......@@ -1865,18 +1854,9 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
substs.types.get_slice(TypeSpace).to_vec()
}
ty::TyStruct(def, substs) => {
self.tcx().struct_fields(def.did, substs)
.iter()
.map(|f| f.mt.ty)
.collect()
}
ty::TyEnum(def, substs) => {
self.tcx().substd_enum_variants(def.did, 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()
}
}
......@@ -2522,9 +2502,10 @@ fn confirm_builtin_unsize_candidate(&mut self,
// Struct<T> -> Struct<U>.
(&ty::TyStruct(def, substs_a), &ty::TyStruct(_, substs_b)) => {
let fields = tcx.lookup_struct_fields(def.did).iter().map(|f| {
tcx.lookup_field_type_unsubstituted(def.did, f.id)
}).collect::<Vec<_>>();
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() {
......
此差异已折叠。
......@@ -438,11 +438,10 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
}
}
(&ty::TyStruct(def, ref _substs), None) => {
let fields = tcx.lookup_struct_fields(def.did);
(&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, substs), ref enum_variant_info) => {
let variant_info = {
let mut variants = tcx.substd_enum_variants(enum_def.did, 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(),
None => {
assert_eq!(variants.len(), 1);
variants.pop().unwrap()
}
(&ty::TyEnum(def, _), ref enum_variant_info) => {
let variant = match *enum_variant_info {
Some((vid, ref _lp2)) => def.variant_with_id(vid),
None => {
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;
}
......
......@@ -45,7 +45,6 @@
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;
if variants[0].args.is_empty() {
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 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; }
_ => { }
......@@ -474,16 +478,14 @@ fn check_type_for_ffi(&self,
// We can't completely trust repr(C) markings; make sure the
// fields are actually safe.
let fields = cx.struct_fields(def.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 => {}
......@@ -494,8 +496,7 @@ fn check_type_for_ffi(&self,
FfiSafe
}
ty::TyEnum(def, substs) => {
let variants = cx.substd_enum_variants(def.did, substs);
if variants.is_empty() {
if def.variants.is_empty() {
// Empty enums are okay... although sort of useless.
return FfiSafe
}
......@@ -506,7 +507,7 @@ fn check_type_for_ffi(&self,
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,9 +538,9 @@ fn check_type_for_ffi(&self,
}
// 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 => {}
......
......@@ -34,7 +34,6 @@
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,29 +687,26 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId,
// Checks that a field is in scope.
fn check_field(&mut self,
span: Span,
id: ast::DefId,
def: &'tcx ty::ADTDef<'tcx>,
v: &'tcx ty::VariantDef<'tcx>,
name: FieldName) {
// TODO: refactor to variant API
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",
......@@ -885,12 +881,18 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
match expr.node {
ast::ExprField(ref base, ident) => {
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
self.check_field(expr.span, def.did, NamedField(ident.node.name));
self.check_field(expr.span,
def,
def.struct_variant(),
NamedField(ident.node.name));
}
}
ast::ExprTupField(ref base, idx) => {
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
self.check_field(expr.span, def.did, UnnamedField(idx.node));
self.check_field(expr.span,
def,
def.struct_variant(),
UnnamedField(idx.node));
}
}
ast::ExprMethodCall(ident, _, _) => {
......@@ -899,67 +901,36 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
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_def, _) => {
// 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_def.did);
for field in all_fields {
self.check_field(expr.span, ctor_def.did,
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?!"),
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.
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)
})
"cannot invoke tuple struct constructor \
with private fields");
}
_ => {}
}
}
_ => {}
......@@ -977,31 +948,12 @@ fn visit_pat(&mut self, pattern: &ast::Pat) {
match pattern.node {
ast::PatStruct(_, ref fields, _) => {
match self.tcx.pat_ty(pattern).sty {
ty::TyStruct(def, _) => {
for field in fields {
self.check_field(pattern.span, def.did,
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?!"),
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, adt, variant,
NamedField(field.node.ident.name));
}
}
......@@ -1014,7 +966,10 @@ struct type?!"),
if let ast::PatWild(..) = field.node {
continue
}
self.check_field(field.span, def.did, UnnamedField(i));
self.check_field(field.span,
def,
def.struct_variant(),
UnnamedField(i));
}
}
ty::TyEnum(..) => {
......
......@@ -742,6 +742,7 @@ fn process_struct_lit(&mut self,
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 @@ fn process_struct_lit(&mut self,
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 @@ fn process_struct_lit(&mut self,
}
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,43 +804,24 @@ fn process_pat(&mut self, p:&ast::Pat) {
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),
}
for &Spanned { node: ref field, span } in fields {
if generated_code(span) {
continue;
}
};
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 {
self.fmt.ref_str(recorder::VarRef,
span,
sub_span,
f.id,
self.cur_scope);
break;
}
}
self.visit_pat(&field.pat);
let sub_span = self.span.span_for_first_ident(span);
if let Some(f) = variant.find_field_named(field.ident.name) {
self.fmt.ref_str(recorder::VarRef,
span,
sub_span,
f.did,
self.cur_scope);
}
self.visit_pat(&field.pat);
}
}
_ => visit::walk_pat(self, p)
......@@ -1091,8 +1072,15 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
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) {
......@@ -1120,18 +1108,12 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
let ty = &self.tcx.expr_ty_adjusted(&**sub_ex).sty;
match *ty {
ty::TyStruct(def, _) => {
let fields = self.tcx.lookup_struct_fields(def.did);
for (i, f) in fields.iter().enumerate() {
if i == idx.node {
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,
self.cur_scope);
break;
}
}
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
self.fmt.ref_str(recorder::VarRef,
ex.span,
sub_span,
def.struct_variant().fields[idx.node].did,
self.cur_scope);
}
ty::TyTuple(_) => {}
_ => self.sess.span_bug(ex.span,
......
......@@ -448,22 +448,14 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
let ty = &self.tcx.expr_ty_adjusted(&sub_ex).sty;
match *ty {
ty::TyStruct(def, _) => {
let fields = self.tcx.lookup_struct_fields(def.did);
for f in &fields {
if f.name == 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,
}));
}
}
self.tcx.sess.span_bug(expr.span,
&format!("Couldn't find field {} on {:?}",
ident.node, ty))
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.did,
}));
}
_ => {
debug!("Expected struct type, found {:?}", ty);
......@@ -621,26 +613,18 @@ fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool {
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 {
// 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,
span: sub_span.unwrap(),
scope: parent,
ref_id: f.id,
};
}
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);
VariableRefData {
name: field_ref.ident.node.to_string(),
span: sub_span.unwrap(),
scope: parent,
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 {
......
......@@ -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,
......@@ -1190,10 +1190,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// 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.did);
let unsized_ty = fields.iter().last().map(|field| {
let fty = bcx.tcx().lookup_field_type(def.did, 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| {
for f in fields {
let ix = tcx.field_idx_strict(f.node.ident.name, field_tys);
let fldptr = adt::trans_field_ptr(
bcx,
&*pat_repr,
val.val,
discr,
ix);
bcx = bind_irrefutable_pat(bcx,
&*f.node.pat,
MatchInput::from_val(fldptr),
cleanup_scope);
}
})
let pat_v = VariantInfo::of_node(tcx, pat_ty, pat.id);
for f in fields {
let name = f.node.ident.name;
let fldptr = adt::trans_field_ptr(
bcx,
&*pat_repr,
val.val,
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);
......
......@@ -246,10 +246,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
Univariant(mk_struct(cx, &elems[..], false, t), 0)
}
ty::TyStruct(def, substs) => {
let fields = cx.tcx().lookup_struct_fields(def.did);
let mut ftys = fields.iter().map(|field| {
let fty = cx.tcx().lookup_field_type(def.did, field.id, substs);
monomorphize::normalize_associated_type(cx.tcx(), &fty)
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.did);
let dtor = cx.tcx().ty_dtor(def.did).has_drop_flag();
......@@ -263,7 +261,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
Univariant(mk_struct(cx, &substs.upvar_tys, false, t), 0)
}
ty::TyEnum(def, substs) => {
let cases = get_cases(cx.tcx(), def.did, substs);
let cases = get_cases(cx.tcx(), def, substs);
let hint = *cx.tcx().lookup_repr_hints(def.did).get(0)
.unwrap_or(&attr::ReprAny);
......@@ -444,10 +442,10 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
// Is this the NonZero lang item wrapping a pointer or integer type?
ty::TyStruct(def, substs) if Some(def.did) == tcx.lang_items.non_zero() => {
let nonzero_fields = tcx.lookup_struct_fields(def.did);
let nonzero_fields = &def.struct_variant().fields;
assert_eq!(nonzero_fields.len(), 1);
let nonzero_field = tcx.lookup_field_type(def.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)
......@@ -463,9 +461,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, substs) => {
let fields = tcx.lookup_struct_fields(def.did);
for (j, field) in fields.iter().enumerate() {
let field_ty = tcx.lookup_field_type(def.did, field.id, substs);
for (j, field) in def.struct_variant().fields.iter().enumerate() {
// TODO(#27532)
let field_ty = field.ty(tcx, substs);
if let Some(mut fpath) = find_discr_field_candidate(tcx, field_ty, path.clone()) {
fpath.push(j);
return Some(fpath);
......@@ -530,14 +528,14 @@ fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option<DiscrField> {
}
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::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 @@ fn iter_variant<'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,22 +415,20 @@ fn iter_variant<'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 llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i);
let val = if common::type_is_sized(cx.tcx(), field_ty) {
llfld_a
} else {
let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val
};
cx = f(cx, val, field_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) {
llfld_a
} else {
let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val
};
cx = f(cx, val, field_ty);
}
}
ty::TyClosure(_, ref substs) => {
let repr = adt::represent_type(cx.ccx(), t);
......@@ -460,8 +458,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
let ccx = fcx.ccx;
let repr = adt::represent_type(ccx, t);
let variants = ccx.tcx().enum_variants(en.did);
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 @@ fn iter_variant<'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 @@ fn iter_variant<'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 @@ fn iter_variant<'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);
......@@ -1694,9 +1691,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) {
......@@ -1704,7 +1699,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);
......@@ -1776,7 +1771,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_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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::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;
......@@ -174,11 +175,9 @@ 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, substs) => {
let fields = ccx.tcx().lookup_struct_fields(def.did);
let fields = &def.struct_variant().fields;
fields.len() == 1 && {
let ty = ccx.tcx().lookup_field_type(def.did, 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
......@@ -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)
-> &'tcx 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))
})
}
......@@ -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) {
(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()) {
C_vector(&cs[..])
} else {
adt::trans_const(cx, &*repr, discr, &cs[..])
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()) {
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,14 +802,18 @@ 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 repr = adt::represent_type(cx, ety);
adt::trans_const(cx, &*repr, vinfo.disr_val, &[])
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(_) => {
......@@ -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 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;
......@@ -784,11 +784,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
unique_type_id,
usage_site_span).finalize(cx)
}
ty::TyStruct(def, substs) => {
ty::TyStruct(..) => {
prepare_struct_metadata(cx,
t,
def.did,
substs,
unique_type_id,
usage_site_span).finalize(cx)
}
......@@ -1096,7 +1094,8 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
// Creates MemberDescriptions for the fields of a struct
struct StructMemberDescriptionFactory<'tcx> {
fields: Vec<ty::Field<'tcx>>,
variant: &'tcx ty::VariantDef<'tcx>,
substs: &'tcx subst::Substs<'tcx>,
is_simd: bool,
span: Span,
}
......@@ -1104,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,
}
......@@ -1142,15 +1147,18 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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,
......@@ -1158,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,
......@@ -1173,7 +1173,8 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
struct_metadata_stub,
struct_llvm_type,
StructMDF(StructMemberDescriptionFactory {
fields: fields,
variant: variant,
substs: substs,
is_simd: struct_type.is_simd(cx.tcx()),
span: span,
})
......@@ -1248,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,
......@@ -1258,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()
......@@ -1273,7 +1273,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
describe_enum_variant(cx,
self.enum_type,
struct_def,
&*self.variants[i],
&adt.variants[i],
discriminant_info,
self.containing_scope,
self.span);
......@@ -1295,9 +1295,9 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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,
......@@ -1306,7 +1306,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
describe_enum_variant(cx,
self.enum_type,
struct_def,
&*self.variants[0],
&adt.variants[0],
NoDiscriminant,
self.containing_scope,
self.span);
......@@ -1335,7 +1335,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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
......@@ -1350,9 +1350,12 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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,
......@@ -1381,7 +1384,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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);
......@@ -1406,7 +1409,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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);
......@@ -1422,7 +1425,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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())
......@@ -1486,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)
......@@ -1500,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(
......@@ -1515,18 +1518,20 @@ 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()
let mut arg_names: Vec<_> = match variant.kind() {
ty::VariantKind::Unit => vec![],
ty::VariantKind::Tuple => {
variant.fields
.iter()
.enumerate()
.map(|(i, _)| format!("__{}", i))
.collect()
}
None => {
variant_info.args
.iter()
.enumerate()
.map(|(i, _)| format!("__{}", i))
.collect()
ty::VariantKind::Dict => {
variant.fields
.iter()
.map(|f| f.name.to_string())
.collect()
}
};
......@@ -1569,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()
......@@ -1671,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,
......
......@@ -68,7 +68,6 @@
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,27 +715,26 @@ 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 d = base_datum.get_element(
bcx,
field_tys[ix].mt.ty,
|srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
if type_is_sized(bcx.tcx(), d.ty) {
DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
} else {
let scratch = rvalue_scratch_datum(bcx, d.ty, "");
Store(bcx, d.val, get_dataptr(bcx, scratch.val));
let info = Load(bcx, get_len(bcx, base_datum.val));
Store(bcx, info, get_len(bcx, scratch.val));
let vinfo = VariantInfo::from_ty(bcx.tcx(), bare_ty, None);
// Always generate an lvalue datum, because this pointer doesn't own
// the data and cleanup is scheduled elsewhere.
DatumBlock::new(bcx, Datum::new(scratch.val, scratch.ty, LvalueExpr(d.kind)))
}
})
let ix = get_idx(bcx.tcx(), &vinfo);
let d = base_datum.get_element(
bcx,
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 }
} else {
let scratch = rvalue_scratch_datum(bcx, d.ty, "");
Store(bcx, d.val, get_dataptr(bcx, scratch.val));
let info = Load(bcx, get_len(bcx, base_datum.val));
Store(bcx, info, get_len(bcx, scratch.val));
// Always generate an lvalue datum, because this pointer doesn't own
// 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>`.
......@@ -1249,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),
......@@ -1261,8 +1259,7 @@ 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;
}
}
......@@ -1362,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(def, substs) => {
let fields = tcx.struct_fields(def.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>,
......@@ -1437,52 +1369,42 @@ 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 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")
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 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, vinfo.fields[i].1));
}
};
result
}).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));
}
}
Some(StructBaseInfo {expr: base_expr,
fields: leftovers })
}
None => {
if need_base.iter().any(|b| *b) {
tcx.sess.span_bug(expr_span, "missing fields and no base expr")
}
None
Some(StructBaseInfo {expr: base_expr,
fields: leftovers })
}
None => {
if need_base.iter().any(|b| *b) {
tcx.sess.span_bug(expr_span, "missing fields and no base expr")
}
};
None
}
};
trans_adt(bcx,
ty,
discr,
&numbered_fields,
optbase,
dest,
DebugLoc::At(expr_id, expr_span))
})
trans_adt(bcx,
ty,
vinfo.discr,
&numbered_fields,
optbase,
dest,
DebugLoc::At(expr_id, expr_span))
}
/// Information that `trans_adt` needs in order to fill in the fields
......@@ -2126,8 +2048,8 @@ fn float_cast(bcx: Block,
}
}
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);
......
......@@ -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(def.did, 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;
......
......@@ -100,30 +100,32 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
ccx.external().borrow_mut().insert(parent_id, Some(item.id));
ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
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::ItemStruct(ref struct_def, _) => {
match struct_def.ctor_id {
None => {}
Some(ctor_id) => {
ccx.external().borrow_mut().insert(fn_id, Some(ctor_id));
my_id = ctor_id;
let mut my_id = 0;
match item.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));
}
}
}
}
_ => ccx.sess().bug("instantiate_inline: item has a \
ast::ItemStruct(ref struct_def, _) => {
match struct_def.ctor_id {
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;
}
}
}
_ => ccx.sess().bug("instantiate_inline: item has a \
non-enum, non-struct parent")
}
trans_item(ccx, &**item);
my_id
}
trans_item(ccx, &**item);
my_id
}
csearch::FoundAst::FoundParent(_, _) => {
ccx.sess().bug("maybe_get_item_ast returned a FoundParent \
......
......@@ -29,7 +29,6 @@
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
......
......@@ -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 (adt_def, 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,
......@@ -544,11 +544,10 @@ 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, _) =>
(struct_def, struct_def.did),
(struct_def, struct_def.struct_variant()),
ty::TyEnum(enum_def, _)
// TODO: wut?
if def == def::DefVariant(enum_def.did, def.def_id(), true) =>
(enum_def, def.def_id()),
(enum_def, enum_def.variant_of_def(def)),
_ => {
let name = pprust::path_to_string(path);
span_err!(tcx.sess, pat.span, E0163,
......@@ -582,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>,
......@@ -651,19 +648,23 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
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.did, def.def_id());
(variant.args.iter()
.map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t))
.collect(),
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, expected_substs) => {
let struct_fields = tcx.struct_fields(struct_def.did, expected_substs);
(struct_fields.iter()
.map(|field| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&field.mt.ty))
.collect(),
(struct_def.struct_variant()
.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&f.unsubst_ty()))
.collect(),
"struct")
}
_ => {
......@@ -716,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.
......@@ -732,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",
......@@ -744,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,
......
......@@ -80,9 +80,10 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
ty::TyStruct(def, substs) => {
match fcx.tcx().struct_fields(def.did, substs).pop() {
// 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 @@ fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
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)
......
......@@ -285,26 +285,28 @@ 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 } => {
TypeContext::ADT { def_id, variant, field, field_index } => {
// FIXME (pnkfelix): eventually lookup arg_name
// for the given index on struct variants.
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,
detected_on_typ);
// TODO: be saner
if let ty::ADTKind::Enum = tcx.lookup_adt_def(def_id).adt_kind() {
span_note!(
rcx.tcx().sess,
span,
"overflowed on enum {} variant {} argument {} type: {}",
tcx.item_path_str(def_id),
variant,
field_index,
detected_on_typ);
} else {
span_note!(
rcx.tcx().sess,
span,
"overflowed on struct {} field {} type: {}",
tcx.item_path_str(def_id),
field,
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
}
}
......@@ -437,41 +436,23 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
cx, context, ity, depth+1)
}
ty::TyStruct(def, substs) => {
let did = def.did;
let fields = tcx.lookup_struct_fields(did);
for field in &fields {
let fty = tcx.lookup_field_type(did, field.id, 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 {
def_id: did,
field: field.name,
},
fty,
depth+1))
}
Ok(())
}
ty::TyEnum(def, substs) => {
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
let did = def.did;
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() {
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::EnumVariant {
TypeContext::ADT {
def_id: did,
variant: variant_info.name,
arg_index: i,
field: field.name,
variant: variant.name,
field_index: i
},
fty,
depth+1));
depth+1))
}
}
Ok(())
......
......@@ -66,9 +66,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// If the item has the name of a field, give a help note
if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
let fields = cx.lookup_struct_fields(def.did);
if let Some(field) = fields.iter().find(|f| f.name == item_name) {
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(def.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(|_| {
......
......@@ -1674,34 +1674,19 @@ pub fn add_obligations_for_parameters(&self,
}
}
// Only for fields! Returns <none> for methods>
// Indifferent to privacy flags
pub fn lookup_field_ty(&self,
span: Span,
struct_def: &'tcx ty::ADTDef<'tcx>,
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(struct_def.did, f.id, substs))
.map(|t| self.normalize_associated_types_in(span, &t))
}
pub fn lookup_tup_field_ty(&self,
span: Span,
struct_def: &'tcx ty::ADTDef<'tcx>,
items: &[ty::FieldTy],
idx: usize,
substs: &subst::Substs<'tcx>)
-> Option<Ty<'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>
{
let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
o_field.map(|f| self.tcx().lookup_field_type(struct_def.did, f.id, substs))
.map(|t| self.normalize_associated_types_in(span, &t))
self.normalize_associated_types_in(span,
&field.ty(self.tcx(), substs))
}
// Only for fields! Returns <none> for methods>
// Indifferent to privacy flags
fn check_casts(&self) {
let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
for cast in deferred_cast_checks.drain(..) {
......@@ -2880,9 +2865,9 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
match base_t.sty {
ty::TyStruct(base_def, substs) => {
debug!("struct named {:?}", base_t);
let fields = tcx.lookup_struct_fields(base_def.did);
fcx.lookup_field_ty(expr.span, base_def, &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
}
......@@ -2920,7 +2905,7 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
},
expr_t, None);
if let ty::TyStruct(def, _) = expr_t.sty {
suggest_field_names(def.did, field, tcx, vec![]);
suggest_field_names(def.struct_variant(), field, tcx, vec![]);
}
}
......@@ -2928,23 +2913,22 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
}
// displays hints about the closest matches in field names
fn suggest_field_names<'tcx>(variant_id: ast::DefId,
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(variant_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 variant_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_tup_field<'a,'tcx>(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));
......@@ -2983,9 +2966,10 @@ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
tuple_like = base_def.struct_variant().is_tuple_struct();
if tuple_like {
debug!("tuple struct named {:?}", base_t);
let fields = tcx.lookup_struct_fields(base_def.did);
fcx.lookup_tup_field_ty(expr.span, base_def, &fields[..],
idx.node, &(*substs))
base_def.struct_variant()
.fields
.get(idx.node)
.map(|f| fcx.field_ty(expr.span, f, substs))
} else {
None
}
......@@ -3025,71 +3009,63 @@ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
fcx.write_error(expr.id);
}
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());
}
fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
adt_ty: Ty<'tcx>,
span: Span,
variant_id: ast::DefId,
substitutions: &'tcx subst::Substs<'tcx>,
field_types: &[ty::FieldTy],
ast_fields: &'tcx [ast::Field],
check_completeness: bool) -> Result<(),()> {
let tcx = fcx.ccx.tcx;
let (adt_def, is_enum) = match adt_ty.sty {
ty::TyStruct(def, _) => (def, false),
ty::TyEnum(def, _) => (def, true),
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 class_field_map = FnvHashMap();
let mut fields_found = 0;
for field in field_types {
class_field_map.insert(field.name, (field.id, false));
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 pair = class_field_map.get(&field.ident.node.name).cloned();
match pair {
None => {
fcx.type_error_message(
field.ident.span,
|actual| if is_enum {
let variant_type = tcx.enum_variant_with_id(adt_def.did,
variant_id);
format!("struct variant `{}::{}` has no field named `{}`",
actual, variant_type.name.as_str(),
field.ident.node)
} else {
format!("structure `{}` has no field named `{}`",
actual,
field.ident.node)
},
adt_ty,
None);
// prevent all specified fields from being suggested
let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
suggest_field_names(variant_id, &field.ident, tcx, skip_fields.collect());
error_happened = true;
}
Some((_, true)) => {
let expected_field_type;
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;
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(variant_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);
}
}
......@@ -3098,25 +3074,19 @@ fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
}
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))
}
}
span_err!(tcx.sess, span, E0063,
"missing field{}: {}",
if missing_fields.len() == 1 {""} else {"s"},
missing_fields.join(", "));
}
if check_completeness &&
!error_happened &&
!remaining_fields.is_empty()
{
error_happened = true;
span_err!(tcx.sess, span, E0063,
"missing field{}: {}",
if remaining_fields.len() == 1 {""} else {"s"},
remaining_fields.keys()
.map(|n| format!("`{}`", n))
.collect::<Vec<_>>()
.join(", "));
}
if error_happened { Err(()) } else { Ok(()) }
......@@ -3133,17 +3103,14 @@ fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
// Generate the struct type.
let TypeAndSubsts {
ty: mut struct_type,
substs: struct_substs
substs: _
} = fcx.instantiate_type(span, struct_def.did);
// Look up and check the fields.
let class_fields = tcx.lookup_struct_fields(struct_def.did);
let res = check_struct_or_variant_fields(fcx,
struct_type,
span,
struct_def.did,
fcx.ccx.tcx.mk_substs(struct_substs),
&class_fields[..],
fields,
base_expr.is_none());
if res.is_err() {
......@@ -3168,23 +3135,18 @@ fn check_struct_enum_variant<'a,'tcx>(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);
let _ = check_struct_or_variant_fields(fcx,
enum_type,
span,
variant_id,
fcx.ccx.tcx.mk_substs(substitutions),
&variant_fields[..],
fields,
true);
fcx.write_ty(id, enum_type);
......@@ -4295,14 +4257,13 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
}
match t.sty {
ty::TyStruct(def, substs) => {
let fields = tcx.lookup_struct_fields(def.did);
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(def.did, fields[0].id, substs);
if !fields.iter().all(
|f| tcx.lookup_field_type(def.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;
}
......@@ -4370,10 +4331,7 @@ fn do_check<'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;
......@@ -4382,7 +4340,7 @@ fn do_check<'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 => {}
......
......@@ -483,10 +483,9 @@ fn check_implementations_of_coerce_unsized(&self) {
}
let origin = infer::Misc(span);
let fields = tcx.lookup_struct_fields(def_a.did);
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_a.did, 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 {
......
......@@ -1174,33 +1174,50 @@ fn evaluate_disr_expr<'tcx>(tcx: &ty::ctxt<'tcx>,
Ok(ConstVal::Int(val)) => Some(val as ty::Disr),
Ok(ConstVal::Uint(val)) => Some(val as ty::Disr),
Ok(_) => {
// let sign_desc = if repr_type.is_signed() {
// "signed"
// } else {
// "unsigned"
// };
// span_err!(self.sess, e.span, E0079,
// "expected {} integer constant",
// sign_desc);
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(_) => {
// span_err!(self.sess, err.span, E0080,
// "constant evaluation error: {}",
// err.description());
Err(err) => {
span_err!(tcx.sess, err.span, E0080,
"constant evaluation error: {}",
err.description());
None
}
}
}
fn next_disr(repr_type: attr::IntType,
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 {
// self.report_discrim_overflow(v.span, &v.node.name.name.as_str(),
// repr_type, 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)
......@@ -1240,7 +1257,7 @@ fn convert_enum_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
let variants = def.variants.iter().map(|v| {
let disr = match v.node.disr_expr {
Some(ref e) => evaluate_disr_expr(tcx, repr_type_ty, e),
None => next_disr(repr_type, prev_disr)
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);
......
......@@ -883,6 +883,64 @@ struct Foo { x: Option<Box<Foo>> }
```
"##,
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 @@ struct Foo<'a, T: 'a> {
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 @@ fn visit_item(&mut self, item: &ast::Item) {
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 @@ fn visit_item(&mut self, item: &ast::Item) {
//
// 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,
......
......@@ -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,
}
}
......@@ -208,7 +208,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
return clean::EnumItem(clean::Enum {
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
variants_stripped: false,
variants: tcx.enum_variants(edef.did).clean(cx),
variants: edef.variants.clean(cx),
})
}
_ => {}
......
......@@ -1730,29 +1730,27 @@ fn clean(&self, cx: &DocContext) -> Item {
}
}
impl Clean<Item> for ty::FieldTy {
impl<'tcx> Clean<Item> for ty::FieldDef<'tcx> {
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))),
}
}
}
......@@ -1858,22 +1856,24 @@ fn clean(&self, cx: &DocContext) -> Item {
}
}
impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
impl<'tcx> Clean<Item> for ty::VariantDef<'tcx> {
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
......@@ -1883,10 +1883,10 @@ fn clean(&self, cx: &DocContext) -> Item {
// 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()
......@@ -1895,12 +1895,12 @@ fn clean(&self, cx: &DocContext) -> Item {
};
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),
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册