Skip to content

Commit

Permalink
Review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
nrc committed Apr 23, 2014
1 parent 0540a59 commit 5729d9b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 51 deletions.
25 changes: 1 addition & 24 deletions src/librustc/middle/ty.rs
Expand Up @@ -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
Expand Down
39 changes: 27 additions & 12 deletions src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -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(_) => {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)));
}
}
Expand Down
14 changes: 6 additions & 8 deletions src/librustc/middle/typeck/collect.rs
Expand Up @@ -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
});
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax/print/pprust.rs
Expand Up @@ -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, ":"));
Expand Down
8 changes: 4 additions & 4 deletions src/test/compile-fail/unsized5.rs
Expand Up @@ -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() {
Expand Down
6 changes: 4 additions & 2 deletions src/test/run-pass/unsized2.rs
Expand Up @@ -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>);
}

Expand All @@ -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>);
}

Expand Down

5 comments on commit 5729d9b

@bors
Copy link
Contributor

@bors bors commented on 5729d9b Apr 23, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at nrc@5729d9b

@bors
Copy link
Contributor

@bors bors commented on 5729d9b Apr 23, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging nick29581/rust/unsized-enum = 5729d9b into auto

@bors
Copy link
Contributor

@bors bors commented on 5729d9b Apr 23, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nick29581/rust/unsized-enum = 5729d9b merged ok, testing candidate = 696f16e

@bors
Copy link
Contributor

@bors bors commented on 5729d9b Apr 23, 2014

@bors
Copy link
Contributor

@bors bors commented on 5729d9b Apr 23, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 696f16e

Please sign in to comment.