Skip to content

Commit 805cf81

Browse files
committed
auto merge of #17112 : nick29581/rust/unsized-fields, r=nikomatsakis
closes #16977 r? @nikomatsakis
2 parents 4727381 + 4028ebc commit 805cf81

File tree

3 files changed

+117
-10
lines changed

3 files changed

+117
-10
lines changed

src/librustc/middle/ty.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -2992,14 +2992,13 @@ pub fn lltype_is_sized(cx: &ctxt, ty: t) -> bool {
29922992
pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
29932993
match get(ty).sty {
29942994
ty_str | ty_trait(..) | ty_vec(..) => ty,
2995-
ty_struct(_, ref substs) => {
2996-
// Exactly one of the type parameters must be unsized.
2997-
for tp in substs.types.get_slice(subst::TypeSpace).iter() {
2998-
if !type_is_sized(cx, *tp) {
2999-
return unsized_part_of_type(cx, *tp);
3000-
}
3001-
}
3002-
fail!("Unsized struct type with no unsized type params? {}", ty_to_string(cx, ty));
2995+
ty_struct(def_id, ref substs) => {
2996+
let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
2997+
.map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
2998+
// Exactly one of the fields must be unsized.
2999+
assert!(unsized_fields.len() == 1)
3000+
3001+
unsized_part_of_type(cx, unsized_fields[0])
30033002
}
30043003
_ => {
30053004
assert!(type_is_sized(cx, ty),

src/test/compile-fail/unsized5.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010
#![feature(struct_variant)]
1111

12-
// Test `Sized?` types not allowed in fields.
12+
// Test `Sized?` types not allowed in fields (except the last one).
1313

1414
struct S1<Sized? X> {
1515
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
@@ -20,7 +20,14 @@ struct S2<Sized? X> {
2020
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
2121
h: int,
2222
}
23-
23+
struct S3 {
24+
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
25+
g: [uint]
26+
}
27+
struct S4 {
28+
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
29+
g: uint
30+
}
2431
enum E<Sized? X> {
2532
V1(X, int), //~ERROR type `X` is dynamically sized. dynamically sized types may only appear as t
2633
V2{f1: X, f: int}, //~ERROR type `f1` is dynamically sized. dynamically sized types may only app

src/test/run-pass/unsized3.rs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test structs with always-unsized fields.
12+
13+
use std::mem;
14+
use std::raw;
15+
16+
struct Foo<T> {
17+
f: [T],
18+
}
19+
20+
struct Bar {
21+
f1: uint,
22+
f2: [uint],
23+
}
24+
25+
struct Baz {
26+
f1: uint,
27+
f2: str,
28+
}
29+
30+
trait Tr {
31+
fn foo(&self) -> uint;
32+
}
33+
34+
struct St {
35+
f: uint
36+
}
37+
38+
impl Tr for St {
39+
fn foo(&self) -> uint {
40+
self.f
41+
}
42+
}
43+
44+
struct Qux<'a> {
45+
f: Tr+'a
46+
}
47+
48+
pub fn main() {
49+
let _: &Foo<f64>;
50+
let _: &Bar;
51+
let _: &Baz;
52+
53+
let _: Box<Foo<i32>>;
54+
let _: Box<Bar>;
55+
let _: Box<Baz>;
56+
57+
let _ = mem::size_of::<Box<Foo<u8>>>();
58+
let _ = mem::size_of::<Box<Bar>>();
59+
let _ = mem::size_of::<Box<Baz>>();
60+
61+
unsafe {
62+
struct Foo_<T> {
63+
f: [T, ..3]
64+
}
65+
66+
let data = box Foo_{f: [1i32, 2, 3] };
67+
let x: &Foo<i32> = mem::transmute(raw::Slice { len: 3, data: &*data });
68+
assert!(x.f.len() == 3);
69+
assert!(x.f[0] == 1);
70+
assert!(x.f[1] == 2);
71+
assert!(x.f[2] == 3);
72+
73+
struct Baz_ {
74+
f1: uint,
75+
f2: [u8, ..5],
76+
}
77+
78+
let data = box Baz_{ f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
79+
let x: &Baz = mem::transmute( raw::Slice { len: 5, data: &*data } );
80+
assert!(x.f1 == 42);
81+
let chs: Vec<char> = x.f2.chars().collect();
82+
assert!(chs.len() == 5);
83+
assert!(chs[0] == 'a');
84+
assert!(chs[1] == 'b');
85+
assert!(chs[2] == 'c');
86+
assert!(chs[3] == 'd');
87+
assert!(chs[4] == 'e');
88+
89+
struct Qux_ {
90+
f: St
91+
}
92+
93+
let obj: Box<St> = box St { f: 42 };
94+
let obj: &Tr = &*obj;
95+
let obj: raw::TraitObject = mem::transmute(&*obj);
96+
let data = box Qux_{ f: St { f: 234 } };
97+
let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable,
98+
data: mem::transmute(&*data) });
99+
assert!(x.f.foo() == 234);
100+
}
101+
}

0 commit comments

Comments
 (0)