diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2015-03-27 22:37:36 +0530 |
|---|---|---|
| committer | Manish Goregaokar <manishsmail@gmail.com> | 2015-03-27 22:37:36 +0530 |
| commit | 5b45ede68fb97b23947a054b993be4f4bac6df32 (patch) | |
| tree | e0dfbf4ce565c87ba37b96b59bc68fd23705beb1 /src/test | |
| parent | e65c6e572acdad4778c430567d5fb8580bddefa2 (diff) | |
| parent | dd8cf9238940b7b0dc54cc05d0788d8d7282aa27 (diff) | |
| download | rust-5b45ede68fb97b23947a054b993be4f4bac6df32.tar.gz rust-5b45ede68fb97b23947a054b993be4f4bac6df32.zip | |
Rollup merge of #23712 - nikomatsakis:reflect-trait, r=FlaPer87
This PR introduces a `Reflect` marker trait which is a supertrait of `Any`. The idea is that `Reflect` is defined for all concrete types, but is not defined for type parameters unless there is a `T:Reflect` bound. This is intended to preserve the parametricity property. This allows the `Any` interface to be stabilized without committing us to unbounded reflection that is not easily detectable by the caller. The implementation of `Reflect` relies on an experimental variant of OIBIT. This variant behaves differently for objects, since it requires that all types exposed as part of the object's *interface* are `Reflect`, but isn't concerned about other types that may be closed over. In other words, you don't have to write `Foo+Reflect` in order for `Foo: Reflect` to hold (where `Foo` is a trait). Given that `Any` is slated to stabilization and hence that we are committed to some form of reflection, the goal of this PR is to leave our options open with respect to parametricity. I see the options for full stabilization as follows (I think an RFC would be an appropriate way to confirm whichever of these three routes we take): 1. We make `Reflect` a lang-item. 2. We stabilize some version of the OIBIT variation I implemented as a general mechanism that may be appropriate for other use cases. 3. We give up on preserving parametricity here and just have `impl<T> Reflect for T` instead. In that case, `Reflect` is a harmless but not especially useful trait going forward. cc @aturon cc @alexcrichton cc @glaebhoerl (this is more-or-less your proposal, as I understood it) cc @reem (this is more-or-less what we discussed on IRC at some point) cc @FlaPer87 (vaguely pertains to OIBIT)
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/auxiliary/typeid-intrinsic.rs | 4 | ||||
| -rw-r--r-- | src/test/auxiliary/typeid-intrinsic2.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/reflect-assoc.rs | 35 | ||||
| -rw-r--r-- | src/test/compile-fail/reflect-object-param.rs | 47 | ||||
| -rw-r--r-- | src/test/compile-fail/reflect.rs | 39 | ||||
| -rw-r--r-- | src/test/compile-fail/variance-region-bounds.rs | 25 | ||||
| -rw-r--r-- | src/test/run-pass/object-one-type-two-traits.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/type-id-higher-rank.rs | 4 |
8 files changed, 153 insertions, 7 deletions
diff --git a/src/test/auxiliary/typeid-intrinsic.rs b/src/test/auxiliary/typeid-intrinsic.rs index 82d07a9df4e..bd47054f093 100644 --- a/src/test/auxiliary/typeid-intrinsic.rs +++ b/src/test/auxiliary/typeid-intrinsic.rs @@ -10,7 +10,7 @@ #![feature(core)] -use std::any::TypeId; +use std::any::{Any, TypeId}; pub struct A; pub struct B(Option<A>); @@ -31,4 +31,4 @@ pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() } pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() } pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() } -pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() } +pub unsafe fn foo<T: Any>() -> TypeId { TypeId::of::<T>() } diff --git a/src/test/auxiliary/typeid-intrinsic2.rs b/src/test/auxiliary/typeid-intrinsic2.rs index 82d07a9df4e..5e81bf50ae4 100644 --- a/src/test/auxiliary/typeid-intrinsic2.rs +++ b/src/test/auxiliary/typeid-intrinsic2.rs @@ -10,7 +10,7 @@ #![feature(core)] -use std::any::TypeId; +use std::any::{Any, TypeId}; pub struct A; pub struct B(Option<A>); @@ -31,4 +31,4 @@ pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() } pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() } pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() } -pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() } +pub unsafe fn foo<T:Any>() -> TypeId { TypeId::of::<T>() } diff --git a/src/test/compile-fail/reflect-assoc.rs b/src/test/compile-fail/reflect-assoc.rs new file mode 100644 index 00000000000..9cf0d252c2d --- /dev/null +++ b/src/test/compile-fail/reflect-assoc.rs @@ -0,0 +1,35 @@ +// Copyright 2015 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 types that appear in assoc bindings in an object +// type are subject to the reflect check. + +use std::marker::Reflect; +use std::io::Write; + +trait Get { + type Output; + fn get(self) -> Self::Output; +} + +struct Struct<T>(T); + +fn is_reflect<T:Reflect>() { } + +fn a<T>() { + is_reflect::<Box<Get<Output=T>>>(); //~ ERROR not implemented +} + +fn ok_a<T: Reflect>() { + is_reflect::<Box<Get<Output=T>>>(); // OK +} + +fn main() { +} diff --git a/src/test/compile-fail/reflect-object-param.rs b/src/test/compile-fail/reflect-object-param.rs new file mode 100644 index 00000000000..9f074667feb --- /dev/null +++ b/src/test/compile-fail/reflect-object-param.rs @@ -0,0 +1,47 @@ +// Copyright 2015 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 types that appear in input types in an object type are +// subject to the reflect check. + +use std::marker::Reflect; +use std::io::Write; + +trait Get<T> { + fn get(self) -> T; +} + +struct Struct<T>(T); + +fn is_reflect<T:Reflect>() { } + +fn a<T>() { + is_reflect::<T>(); //~ ERROR not implemented +} + +fn ok_a<T: Reflect>() { + is_reflect::<T>(); // OK +} + +fn b<T>() { + is_reflect::<Box<Get<T>>>(); //~ ERROR not implemented +} + +fn ok_b<T: Reflect>() { + is_reflect::<Box<Get<T>>>(); // OK +} + +fn c<T>() { + is_reflect::<Box<Get<Struct<T>>>>(); //~ ERROR not implemented +} + +fn main() { + is_reflect::<Box<Get<Struct<()>>>>(); // OK +} diff --git a/src/test/compile-fail/reflect.rs b/src/test/compile-fail/reflect.rs new file mode 100644 index 00000000000..701aa5b40bc --- /dev/null +++ b/src/test/compile-fail/reflect.rs @@ -0,0 +1,39 @@ +// Copyright 2015 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 there is no way to get a generic type `T` to be +// considered as `Reflect` (or accessible via something that is +// considered `Reflect`) without a reflect bound, but that any +// concrete type works fine. Note that object types are tested +// separately. + +use std::marker::Reflect; +use std::io::Write; + +struct Struct<T>(T); + +fn is_reflect<T:Reflect>() { } + +fn c<T>() { + is_reflect::<Struct<T>>(); //~ ERROR not implemented +} + +fn ok_c<T: Reflect>() { + is_reflect::<Struct<T>>(); // OK +} + +fn d<T>() { + is_reflect::<(i32, T)>(); //~ ERROR not implemented +} + +fn main() { + is_reflect::<&i32>(); // OK + is_reflect::<Box<Write>>(); // OK +} diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs new file mode 100644 index 00000000000..96ae201f6ae --- /dev/null +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -0,0 +1,25 @@ +// 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. + +// Check that `T:'a` is contravariant in T. + +#![feature(rustc_attrs)] + +#[rustc_variance] +trait Foo: 'static { //~ ERROR types=[[];[-];[]] +} + +#[rustc_variance] +trait Bar<T> { //~ ERROR types=[[+];[-];[]] + fn do_it(&self) + where T: 'static; +} + +fn main() { } diff --git a/src/test/run-pass/object-one-type-two-traits.rs b/src/test/run-pass/object-one-type-two-traits.rs index baf8c6e4c97..f4e056b3f21 100644 --- a/src/test/run-pass/object-one-type-two-traits.rs +++ b/src/test/run-pass/object-one-type-two-traits.rs @@ -30,7 +30,7 @@ impl Wrap for int { } } -fn is<T:'static>(x: &Any) -> bool { +fn is<T:Any>(x: &Any) -> bool { x.is::<T>() } diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs index 5670c45b68a..a40989d4e37 100644 --- a/src/test/run-pass/type-id-higher-rank.rs +++ b/src/test/run-pass/type-id-higher-rank.rs @@ -15,7 +15,7 @@ #![feature(unboxed_closures, core)] -use std::any::TypeId; +use std::any::{Any, TypeId}; fn main() { // Bare fns @@ -63,7 +63,7 @@ fn main() { assert!(a != b); } - fn id<T:'static>(_: T) -> TypeId { + fn id<T:Any>(_: T) -> TypeId { TypeId::of::<T>() } } |
