Change:
cc
This should be a compiler error, not an ICE. The error is (or should be) that is unsized, but is not a bare .
Why would this be an error? Isn't enabling this kind of code part of the goal of DST?
Not quite. We want to allow struct's last field to be potentially unsized, but it must be possible to have a sized version too. This is because only sized types can be instantiated. Since there is no possible sized version of , it cannot be instantiated and should be an error.
Hm, I see. This is kinda unfortunate though, because you can't hide away the actual slice type from your wrapper. Eg, you could do But that widens your wrapper to possibly be instantiated with more than and . Maybe allow a struct definition like but to use it you need to transmute something like ? As an aside, the example in this issue would probably not work anyway, as the stride should presumably be stored per pointer, and not once in the target matrices backing memory. But this is till relevant for newtype wrappers around , eg a hypothetical

Discussion:
pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t { match get(ty).sty { ty_str | ty_trait(..) | ty_vec(..) => ty, <del> 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)); </del> <ins> 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]) </ins> } _ => { assert!(type_is_sized(cx, ty),

// except according to those terms. #![feature(struct_variant)] <del> // Test `Sized?` types not allowed in fields. </del> <ins> // Test `Sized?` types not allowed in fields (except the last one). </ins> struct S1<Sized? X> { f1: X, //~ ERROR type `f1` is dynamically sized. dynamically sized types may only appear as the

g: X, //~ ERROR type `g` is dynamically sized. dynamically sized types may only appear as the ty h: int, } <ins> 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 } </ins> 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

<ins> // 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); } } </ins>