auto merge of #13398 : nick29581/rust/unsized-enum, r=nikomatsakis

Now with proper checking of enums and allows unsized fields as the last field in a struct or variant. This PR only checks passing of unsized types and distinguishing them from sized ones. To be safe we also need to control storage.

Closes issues #12969 and #13121, supersedes #13375 (all the discussion there is valid here too).
This commit is contained in:
bors 2014-04-22 20:51:31 -07:00
commit 696f16ec2e
40 changed files with 643 additions and 84 deletions

View file

@ -12,6 +12,9 @@
#![no_std]
#[lang="sized"]
pub trait Sized {}
struct S<T> {
contents: T,
}

View file

@ -13,6 +13,9 @@
#![no_std]
#[lang="sized"]
pub trait Sized {}
struct S {
x : ~int
}

View file

@ -17,6 +17,10 @@
#![crate_type="lib"]
pub use foo2::Bar2;
#[lang="sized"]
pub trait Sized {}
mod foo {
pub struct Bar; //~ ERROR: code is never used
}

View file

@ -11,6 +11,9 @@
#![feature(globs)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
#[lang="sized"]
pub trait Sized {}
mod bar {
// shouln't bring in too much
pub use self::glob::*;

View file

@ -10,5 +10,5 @@
// error-pattern: instantiating a type parameter with an incompatible type
fn bar<T: Sized>() { }
fn foo<T>() { bar::<T>() }
fn foo<type T>() { bar::<T>() }
fn main() { }

View file

@ -10,5 +10,5 @@
// error-pattern: instantiating a type parameter with an incompatible type
fn bar<T: Sized>() { }
fn foo<T>() { bar::<Option<T>>() }
fn foo<type T>() { bar::<Option<T>>() }
fn main() { }

View file

@ -13,5 +13,5 @@
struct Foo<T> { data: T }
fn bar<T: Sized>() { }
fn foo<T>() { bar::<Foo<T>>() }
fn foo<type T>() { bar::<Foo<T>>() }
fn main() { }

View file

@ -0,0 +1,16 @@
// 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 syntax checks for `type` keyword.
struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name but found `for`
pub fn main() {
}

View file

@ -0,0 +1,17 @@
// 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 syntax checks for `type` keyword.
fn f<X>() {}
pub fn main() {
f<type>(); //~ ERROR found `type` in ident position
}

View file

@ -0,0 +1,80 @@
// 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 sized-ness checking in substitution.
// Unbounded.
fn f1<type X>(x: &X) {
f2::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
}
fn f2<X>(x: &X) {
}
// Bounded.
trait T for type {}
fn f3<type X: T>(x: &X) {
f4::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
}
fn f4<X: T>(x: &X) {
}
// Test with unsized enum.
enum E<type X> {
V(X),
}
fn f5<Y>(x: &Y) {}
fn f6<type X>(x: &X) {}
fn f7<type X>(x1: &E<X>, x2: &E<X>) {
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `E<X>`, which does not
f6(x2); // ok
}
// Test with unsized struct.
struct S<type X> {
x: X,
}
fn f8<type X>(x1: &S<X>, x2: &S<X>) {
f5(x1); //~ERROR instantiating a type parameter with an incompatible type `S<X>`, which does not
f6(x2); // ok
}
// Test some tuples.
fn f9<type X>(x1: ~S<X>, x2: ~E<X>) {
f5(&(*x1, 34)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
f5(&(32, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
}
// I would like these to fail eventually.
/*
// impl - bounded
trait T1<Z: T> {
}
struct S3<type Y>;
impl<type X: T> T1<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type
}
// impl - unbounded
trait T2<Z> {
}
impl<type X> T2<X> for S3<X> { //ERROR instantiating a type parameter with an incompatible type `X`
// impl - struct
trait T3<type Z> {
}
struct S4<Y>;
impl<type X> T3<X> for S4<X> { //ERROR instantiating a type parameter with an incompatible type `X`
}
*/
pub fn main() {
}

View file

@ -0,0 +1,19 @@
// 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 that bounds are sized-compatible.
trait T {}
fn f<type Y: T>() {
//~^ERROR incompatible bounds on type parameter Y, bound T does not allow unsized type
}
pub fn main() {
}

View file

@ -0,0 +1,41 @@
// 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.
#![feature(struct_variant)]
// Test `type` types not allowed in fields or local variables.
/*trait T for type {}
fn f5<type X>(x: &X) {
let _: X; // ERROR local variable with dynamically sized type X
let _: (int, (X, int)); // ERROR local variable with dynamically sized type (int,(X,int))
}
fn f6<type X: T>(x: &X) {
let _: X; // ERROR local variable with dynamically sized type X
let _: (int, (X, int)); // ERROR local variable with dynamically sized type (int,(X,int))
}*/
struct S1<type X> {
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 `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. 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() {
}

View file

@ -0,0 +1,27 @@
// 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 syntax checks for `type` keyword.
trait T1 for type {}
pub trait T2 for type {}
trait T3<X: T1> for type: T2 {}
trait T4<type X> {}
trait T5<type X, Y> {}
trait T6<Y, type X> {}
trait T7<type X, type Y> {}
trait T8<type X: T2> {}
struct S1<type X>;
enum E<type X> {}
impl <type X> T1 for S1<X> {}
fn f<type X>() {}
pub fn main() {
}

View file

@ -0,0 +1,100 @@
// 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.
#![feature(struct_variant)]
// Test sized-ness checking in substitution.
// Unbounded.
fn f1<type X>(x: &X) {
f1::<X>(x);
}
fn f2<X>(x: &X) {
f1::<X>(x);
f2::<X>(x);
}
// Bounded.
trait T for type {}
fn f3<type X: T>(x: &X) {
f3::<X>(x);
}
fn f4<X: T>(x: &X) {
f3::<X>(x);
f4::<X>(x);
}
// Self type.
trait T2 for type {
fn f() -> ~Self;
}
struct S;
impl T2 for S {
fn f() -> ~S {
~S
}
}
fn f5<type X: T2>(x: &X) {
let _: ~X = T2::f();
}
fn f6<X: T2>(x: &X) {
let _: ~X = T2::f();
}
trait T3 for type {
fn f() -> ~Self;
}
impl T3 for S {
fn f() -> ~S {
~S
}
}
fn f7<type X: T3>(x: &X) {
// This is valid, but the unsized bound on X is irrelevant because any type
// which implements T3 must have statically known size.
let _: ~X = T3::f();
}
trait T4<X> {
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
trait T5<type X> {
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
trait T6<X: T> {
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
trait T7<type X: T> {
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
// The last field in a struct or variant may be unsized
struct S2<type X> {
f: X,
}
struct S3<type X> {
f1: int,
f2: X,
}
enum E<type X> {
V1(X),
V2{x: X},
V3(int, X),
V4{u: int, x: X},
}
pub fn main() {
}