about summary refs log tree commit diff
path: root/src/test/compile-fail/reflect-object-param.rs
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-03-27 22:37:36 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-03-27 22:37:36 +0530
commit5b45ede68fb97b23947a054b993be4f4bac6df32 (patch)
treee0dfbf4ce565c87ba37b96b59bc68fd23705beb1 /src/test/compile-fail/reflect-object-param.rs
parente65c6e572acdad4778c430567d5fb8580bddefa2 (diff)
parentdd8cf9238940b7b0dc54cc05d0788d8d7282aa27 (diff)
downloadrust-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/compile-fail/reflect-object-param.rs')
-rw-r--r--src/test/compile-fail/reflect-object-param.rs47
1 files changed, 47 insertions, 0 deletions
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
+}