Review changes
This commit is contained in:
parent
0540a59382
commit
5729d9b413
@ -2590,30 +2590,7 @@ pub fn type_is_machine(ty: t) -> bool {
|
||||
// Is the type's representation size known at compile time?
|
||||
#[allow(dead_code)] // leaving in for DST
|
||||
pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_param(tp) => {
|
||||
assert_eq!(tp.def_id.krate, ast::LOCAL_CRATE);
|
||||
|
||||
let ty_param_defs = cx.ty_param_defs.borrow();
|
||||
let param_def = ty_param_defs.get(&tp.def_id.node);
|
||||
param_def.bounds.builtin_bounds.contains_elem(BoundSized)
|
||||
},
|
||||
ty_self(def_id) => {
|
||||
let trait_def = lookup_trait_def(cx, def_id);
|
||||
trait_def.bounds.contains_elem(BoundSized)
|
||||
},
|
||||
ty_struct(def_id, ref substs) => {
|
||||
let flds = lookup_struct_fields(cx, def_id);
|
||||
let mut tps = flds.iter().map(|f| lookup_field_type(cx, def_id, f.id, substs));
|
||||
!tps.any(|ty| !type_is_sized(cx, ty))
|
||||
}
|
||||
ty_tup(ref ts) => !ts.iter().any(|t| !type_is_sized(cx, *t)),
|
||||
ty_enum(did, ref substs) => {
|
||||
let variants = substd_enum_variants(cx, did, substs);
|
||||
!variants.iter().any(|v| v.args.iter().any(|t| !type_is_sized(cx, *t)))
|
||||
}
|
||||
_ => true
|
||||
}
|
||||
type_contents(cx, ty).is_sized(cx)
|
||||
}
|
||||
|
||||
// Whether a type is enum like, that is an enum type with only nullary
|
||||
|
@ -576,15 +576,20 @@ fn check_for_field_shadowing(tcx: &ty::ctxt,
|
||||
}
|
||||
|
||||
fn check_fields_sized(tcx: &ty::ctxt,
|
||||
struct_def: @ast::StructDef) {
|
||||
struct_def: &ast::StructDef) {
|
||||
let len = struct_def.fields.len();
|
||||
for i in range(0, len) {
|
||||
let f = struct_def.fields.get(i);
|
||||
if len == 0 {
|
||||
return;
|
||||
}
|
||||
for f in struct_def.fields.slice_to(len - 1).iter() {
|
||||
let t = ty::node_id_to_type(tcx, f.node.id);
|
||||
if !ty::type_is_sized(tcx, t) && i < (len - 1) {
|
||||
if !ty::type_is_sized(tcx, t) {
|
||||
match f.node.kind {
|
||||
ast::NamedField(ident, _) => {
|
||||
tcx.sess.span_err(f.span, format!("type of field {} is dynamically sized",
|
||||
tcx.sess.span_err(f.span, format!("type `{}` is dynamically sized. \
|
||||
dynamically sized types may only \
|
||||
appear as the type of the final \
|
||||
field in a struct",
|
||||
token::get_ident(ident)));
|
||||
}
|
||||
ast::UnnamedField(_) => {
|
||||
@ -3519,16 +3524,18 @@ pub fn check_representable(tcx: &ty::ctxt,
|
||||
/// is representable, but not instantiable.
|
||||
pub fn check_instantiable(tcx: &ty::ctxt,
|
||||
sp: Span,
|
||||
item_id: ast::NodeId) -> bool {
|
||||
item_id: ast::NodeId)
|
||||
-> bool {
|
||||
let item_ty = ty::node_id_to_type(tcx, item_id);
|
||||
if !ty::is_instantiable(tcx, item_ty) {
|
||||
tcx.sess.span_err(sp, format!("this type cannot be instantiated \
|
||||
without an instance of itself; \
|
||||
consider using `Option<{}>`",
|
||||
ppaux::ty_to_str(tcx, item_ty)));
|
||||
return false
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
|
||||
@ -3567,12 +3574,20 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
|
||||
ast::TupleVariantKind(ref args) if args.len() > 0 => {
|
||||
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
|
||||
let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
|
||||
for i in range(0, args.len()) {
|
||||
let t = arg_tys.get(i);
|
||||
let len = arg_tys.len();
|
||||
if len == 0 {
|
||||
return;
|
||||
}
|
||||
for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
|
||||
// Allow the last field in an enum to be unsized.
|
||||
if !ty::type_is_sized(ccx.tcx, *t) && i < args.len() -1 {
|
||||
// We want to do this so that we can support smart pointers.
|
||||
// A struct value with an unsized final field is itself
|
||||
// unsized and we must track this in the type system.
|
||||
if !ty::type_is_sized(ccx.tcx, *t) {
|
||||
ccx.tcx.sess.span_err(args.get(i).ty.span,
|
||||
format!("type {} is dynamically sized",
|
||||
format!("type `{}` is dynamically sized. \
|
||||
dynamically sized types may only \
|
||||
appear as the final type in a variant",
|
||||
ppaux::ty_to_str(ccx.tcx, *t)));
|
||||
}
|
||||
}
|
||||
|
@ -1141,14 +1141,12 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||
param_bounds.trait_bounds.as_slice(),
|
||||
|trait_ref| {
|
||||
let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
|
||||
for bound in trait_def.bounds.iter() {
|
||||
if bound == ty::BoundSized {
|
||||
tcx.sess.span_err(span,
|
||||
format!("incompatible bounds on type parameter {}, \
|
||||
bound {} does not allow unsized type",
|
||||
token::get_ident(ident),
|
||||
ppaux::trait_ref_to_str(tcx, trait_ref)));
|
||||
}
|
||||
if trait_def.bounds.contains_elem(ty::BoundSized) {
|
||||
tcx.sess.span_err(span,
|
||||
format!("incompatible bounds on type parameter {}, \
|
||||
bound {} does not allow unsized type",
|
||||
token::get_ident(ident),
|
||||
ppaux::trait_ref_to_str(tcx, &*trait_ref)));
|
||||
}
|
||||
true
|
||||
});
|
||||
|
@ -678,7 +678,8 @@ impl<'a> State<'a> {
|
||||
try!(self.print_ident(item.ident));
|
||||
try!(self.print_generics(generics));
|
||||
if *sized == ast::DynSize {
|
||||
try!(self.word_space("for type"));
|
||||
try!(space(&mut self.s));
|
||||
try!(word(&mut self.s, "for type"));
|
||||
}
|
||||
if traits.len() != 0u {
|
||||
try!(word(&mut self.s, ":"));
|
||||
|
@ -23,18 +23,18 @@ fn f6<type X: T>(x: &X) {
|
||||
}*/
|
||||
|
||||
struct S1<type X> {
|
||||
f1: X, //~ ERROR type of field f1 is dynamically sized
|
||||
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
|
||||
f2: int,
|
||||
}
|
||||
struct S2<type X> {
|
||||
f: int,
|
||||
g: X, //~ ERROR type of field g is dynamically sized
|
||||
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
|
||||
h: int,
|
||||
}
|
||||
|
||||
enum E<type X> {
|
||||
V1(X, int), //~ERROR type X is dynamically sized
|
||||
V2{f1: X, f: int}, //~ERROR type of field f1 is dynamically sized
|
||||
V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
|
||||
V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -66,7 +66,8 @@ trait T4<X> {
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
trait T5<type X> {
|
||||
fn m1(x: &T4<X>); // not an error (for now)
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
|
||||
@ -75,7 +76,8 @@ trait T6<X: T> {
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
trait T7<type X: T> {
|
||||
fn m1(x: &T4<X>); // not an error (for now)
|
||||
// not an error (for now)
|
||||
fn m1(x: &T4<X>);
|
||||
fn m2(x: &T5<X>);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user