Skip to content

Handle always-unsized structs #17112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2992,14 +2992,13 @@ pub fn lltype_is_sized(cx: &ctxt, ty: t) -> bool {
pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
match get(ty).sty {
ty_str | ty_trait(..) | ty_vec(..) => ty,
ty_struct(_, ref substs) => {
// Exactly one of the type parameters must be unsized.
for tp in substs.types.get_slice(subst::TypeSpace).iter() {
if !type_is_sized(cx, *tp) {
return unsized_part_of_type(cx, *tp);
}
}
fail!("Unsized struct type with no unsized type params? {}", ty_to_string(cx, ty));
ty_struct(def_id, ref substs) => {
let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
.map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
// Exactly one of the fields must be unsized.
assert!(unsized_fields.len() == 1)

unsized_part_of_type(cx, unsized_fields[0])
}
_ => {
assert!(type_is_sized(cx, ty),
Expand Down
11 changes: 9 additions & 2 deletions src/test/compile-fail/unsized5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.
#![feature(struct_variant)]

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

struct S1<Sized? X> {
f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the
Expand All @@ -20,7 +20,14 @@ struct S2<Sized? X> {
g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty
h: int,
}

struct S3 {
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
g: [uint]
}
struct S4 {
f: str, //~ ERROR type `f` is dynamically sized. dynamically sized types may only appear
g: uint
}
enum E<Sized? X> {
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
Expand Down
101 changes: 101 additions & 0 deletions src/test/run-pass/unsized3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test structs with always-unsized fields.

use std::mem;
use std::raw;

struct Foo<T> {
f: [T],
}

struct Bar {
f1: uint,
f2: [uint],
}

struct Baz {
f1: uint,
f2: str,
}

trait Tr {
fn foo(&self) -> uint;
}

struct St {
f: uint
}

impl Tr for St {
fn foo(&self) -> uint {
self.f
}
}

struct Qux<'a> {
f: Tr+'a
}

pub fn main() {
let _: &Foo<f64>;
let _: &Bar;
let _: &Baz;

let _: Box<Foo<i32>>;
let _: Box<Bar>;
let _: Box<Baz>;

let _ = mem::size_of::<Box<Foo<u8>>>();
let _ = mem::size_of::<Box<Bar>>();
let _ = mem::size_of::<Box<Baz>>();

unsafe {
struct Foo_<T> {
f: [T, ..3]
}

let data = box Foo_{f: [1i32, 2, 3] };
let x: &Foo<i32> = mem::transmute(raw::Slice { len: 3, data: &*data });
assert!(x.f.len() == 3);
assert!(x.f[0] == 1);
assert!(x.f[1] == 2);
assert!(x.f[2] == 3);

struct Baz_ {
f1: uint,
f2: [u8, ..5],
}

let data = box Baz_{ f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
let x: &Baz = mem::transmute( raw::Slice { len: 5, data: &*data } );
assert!(x.f1 == 42);
let chs: Vec<char> = x.f2.chars().collect();
assert!(chs.len() == 5);
assert!(chs[0] == 'a');
assert!(chs[1] == 'b');
assert!(chs[2] == 'c');
assert!(chs[3] == 'd');
assert!(chs[4] == 'e');

struct Qux_ {
f: St
}

let obj: Box<St> = box St { f: 42 };
let obj: &Tr = &*obj;
let obj: raw::TraitObject = mem::transmute(&*obj);
let data = box Qux_{ f: St { f: 234 } };
let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable,
data: mem::transmute(&*data) });
assert!(x.f.foo() == 234);
}
}