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:
commit
696f16ec2e
40 changed files with 643 additions and 84 deletions
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#![no_std]
|
||||
|
||||
#[lang="sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
struct S<T> {
|
||||
contents: T,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#![no_std]
|
||||
|
||||
#[lang="sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
struct S {
|
||||
x : ~int
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
16
src/test/compile-fail/unsized.rs
Normal file
16
src/test/compile-fail/unsized.rs
Normal 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() {
|
||||
}
|
||||
17
src/test/compile-fail/unsized2.rs
Normal file
17
src/test/compile-fail/unsized2.rs
Normal 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
|
||||
}
|
||||
80
src/test/compile-fail/unsized3.rs
Normal file
80
src/test/compile-fail/unsized3.rs
Normal 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() {
|
||||
}
|
||||
19
src/test/compile-fail/unsized4.rs
Normal file
19
src/test/compile-fail/unsized4.rs
Normal 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() {
|
||||
}
|
||||
41
src/test/compile-fail/unsized5.rs
Normal file
41
src/test/compile-fail/unsized5.rs
Normal 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() {
|
||||
}
|
||||
27
src/test/run-pass/unsized.rs
Normal file
27
src/test/run-pass/unsized.rs
Normal 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() {
|
||||
}
|
||||
100
src/test/run-pass/unsized2.rs
Normal file
100
src/test/run-pass/unsized2.rs
Normal 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() {
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue