about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMasaki Hara <ackie.h.gmai@gmail.com>2017-06-24 16:20:27 +0900
committerMasaki Hara <ackie.h.gmai@gmail.com>2017-06-29 21:25:35 +0900
commit03660b647690c3dea12a20468f9f798bacd14d82 (patch)
treed132feb401ad434efda260612205aaff4ce1d84a
parentb0bf1b46820d74c30a725a7ea332305098bf3def (diff)
downloadrust-03660b647690c3dea12a20468f9f798bacd14d82.tar.gz
rust-03660b647690c3dea12a20468f9f798bacd14d82.zip
Move unsized_tuple_coercion behind a feature gate.
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md27
-rw-r--r--src/librustc_typeck/check/coercion.rs21
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/test/compile-fail/dst-bad-assign-3.rs2
-rw-r--r--src/test/compile-fail/dst-bad-coerce1.rs2
-rw-r--r--src/test/compile-fail/dst-bad-coerce3.rs2
-rw-r--r--src/test/compile-fail/dst-bad-coerce4.rs2
-rw-r--r--src/test/compile-fail/dst-bad-deep-2.rs2
-rw-r--r--src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs14
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-3.rs2
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-4.rs2
-rw-r--r--src/test/run-pass/dst-irrefutable-bind.rs2
-rw-r--r--src/test/run-pass/dst-raw.rs2
-rw-r--r--src/test/run-pass/dst-trait-tuple.rs1
-rw-r--r--src/test/run-pass/dst-tuple-sole.rs2
-rw-r--r--src/test/run-pass/dst-tuple.rs1
16 files changed, 89 insertions, 1 deletions
diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
new file mode 100644
index 00000000000..c243737e1be
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
@@ -0,0 +1,27 @@
+# `unsized_tuple_coercion`
+
+The tracking issue for this feature is: [#XXXXX]
+
+[#XXXXX]: https://github.com/rust-lang/rust/issues/XXXXX
+
+------------------------
+
+This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
+
+```rust
+impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
+```
+
+This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
+
+```rust
+#![feature(unsized_tuple_coercion)]
+
+fn main() {
+    let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
+    let y : &([i32; 3], [i32]) = &x;
+    assert_eq!(y.1[0], 4);
+}
+```
+
+[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 81aa59e956a..968e893b9a0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::Subst;
 use errors::DiagnosticBuilder;
 use syntax::abi;
+use syntax::feature_gate;
 use syntax::ptr::P;
 use syntax_pos;
 
@@ -520,6 +521,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                                                          coerce_source,
                                                          &[coerce_target]));
 
+        let mut has_unsized_tuple_coercion = false;
+
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
         // inference might unify those two inner type variables later.
@@ -527,7 +530,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         while let Some(obligation) = queue.pop_front() {
             debug!("coerce_unsized resolve step: {:?}", obligation);
             let trait_ref = match obligation.predicate {
-                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
+                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
+                    if unsize_did == tr.def_id() {
+                        if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty {
+                            debug!("coerce_unsized: found unsized tuple coercion");
+                            has_unsized_tuple_coercion = true;
+                        }
+                    }
+                    tr.clone()
+                }
                 _ => {
                     coercion.obligations.push(obligation);
                     continue;
@@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             }
         }
 
+        if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion {
+            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
+                                           "unsized_tuple_coercion",
+                                           self.cause.span,
+                                           feature_gate::GateIssue::Language,
+                                           feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION);
+        }
+
         Ok(coercion)
     }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 74bf19b841e..5de9062de74 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -357,6 +357,9 @@ declare_features! (
 
     // Allows a test to fail without failing the whole suite
     (active, allow_fail, "1.19.0", Some(42219)),
+
+    // Allows unsized tuple coercion.
+    (active, unsized_tuple_coercion, "1.20.0", None),
 );
 
 declare_features! (
@@ -1041,6 +1044,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str =
 pub const EXPLAIN_PLACEMENT_IN: &'static str =
     "placement-in expression syntax is experimental and subject to change.";
 
+pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
+    "Unsized tuple coercion is not stable enough for use and is subject to change";
+
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }
diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs
index 3c089edf001..1c3bad5ba56 100644
--- a/src/test/compile-fail/dst-bad-assign-3.rs
+++ b/src/test/compile-fail/dst-bad-assign-3.rs
@@ -10,6 +10,8 @@
 
 // Forbid assignment into a dynamically sized type.
 
+#![feature(unsized_tuple_coercion)]
+
 type Fat<T: ?Sized> = (isize, &'static str, T);
 //~^ WARNING trait bounds are not (yet) enforced
 
diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs
index 722ff8f25d6..b0de84a5300 100644
--- a/src/test/compile-fail/dst-bad-coerce1.rs
+++ b/src/test/compile-fail/dst-bad-coerce1.rs
@@ -10,6 +10,8 @@
 
 // Attempt to change the type as well as unsizing.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs
index 4dedae9331b..35a147c15bb 100644
--- a/src/test/compile-fail/dst-bad-coerce3.rs
+++ b/src/test/compile-fail/dst-bad-coerce3.rs
@@ -10,6 +10,8 @@
 
 // Attempt to extend the lifetime as well as unsizing.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs
index 2e78108a8de..874b7588ff9 100644
--- a/src/test/compile-fail/dst-bad-coerce4.rs
+++ b/src/test/compile-fail/dst-bad-coerce4.rs
@@ -10,6 +10,8 @@
 
 // Attempt to coerce from unsized to sized.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs
index 831afd27153..0c812b1d815 100644
--- a/src/test/compile-fail/dst-bad-deep-2.rs
+++ b/src/test/compile-fail/dst-bad-deep-2.rs
@@ -13,6 +13,8 @@
 // because it would require stack allocation of an unsized temporary (*g in the
 // test).
 
+#![feature(unsized_tuple_coercion)]
+
 pub fn main() {
     let f: ([isize; 3],) = ([5, 6, 7],);
     let g: &([isize],) = &f;
diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
new file mode 100644
index 00000000000..4ddde011263
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 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.
+
+fn main() {
+    let _ : &(Send,) = &((),);
+    //~^ ERROR Unsized tuple coercion is not stable enough
+}
diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs
index b21f6434b54..1ae66a28a84 100644
--- a/src/test/run-pass-valgrind/dst-dtor-3.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-3.rs
@@ -10,6 +10,8 @@
 
 // no-prefer-dynamic
 
+#![feature(unsized_tuple_coercion)]
+
 static mut DROP_RAN: bool = false;
 
 struct Foo;
diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs
index 810589de770..e416f25bc03 100644
--- a/src/test/run-pass-valgrind/dst-dtor-4.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-4.rs
@@ -10,6 +10,8 @@
 
 // no-prefer-dynamic
 
+#![feature(unsized_tuple_coercion)]
+
 static mut DROP_RAN: isize = 0;
 
 struct Foo;
diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs
index bd6ad9207ad..b1d6c732e7f 100644
--- a/src/test/run-pass/dst-irrefutable-bind.rs
+++ b/src/test/run-pass/dst-irrefutable-bind.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Test<T: ?Sized>(T);
 
 fn main() {
diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs
index c82cbd75044..9ebfbee8a33 100644
--- a/src/test/run-pass/dst-raw.rs
+++ b/src/test/run-pass/dst-raw.rs
@@ -11,6 +11,8 @@
 // Test DST raw pointers
 
 
+#![feature(unsized_tuple_coercion)]
+
 trait Trait {
     fn foo(&self) -> isize;
 }
diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs
index ab60e95c74e..9803e26f5f8 100644
--- a/src/test/run-pass/dst-trait-tuple.rs
+++ b/src/test/run-pass/dst-trait-tuple.rs
@@ -11,6 +11,7 @@
 
 #![allow(unused_features)]
 #![feature(box_syntax)]
+#![feature(unsized_tuple_coercion)]
 
 type Fat<T: ?Sized> = (isize, &'static str, T);
 
diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs
index d3901a7555f..a788e25218e 100644
--- a/src/test/run-pass/dst-tuple-sole.rs
+++ b/src/test/run-pass/dst-tuple-sole.rs
@@ -11,6 +11,8 @@
 // As dst-tuple.rs, but the unsized field is the only field in the tuple.
 
 
+#![feature(unsized_tuple_coercion)]
+
 type Fat<T: ?Sized> = (T,);
 
 // x is a fat pointer
diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs
index 130294feb6c..2f5b28495b8 100644
--- a/src/test/run-pass/dst-tuple.rs
+++ b/src/test/run-pass/dst-tuple.rs
@@ -11,6 +11,7 @@
 
 #![allow(unknown_features)]
 #![feature(box_syntax)]
+#![feature(unsized_tuple_coercion)]
 
 type Fat<T: ?Sized> = (isize, &'static str, T);