Skip to content

Commit 8722ad7

Browse files
committed
Move unsized_tuple_coercion behind a feature gate.
1 parent 868f6d0 commit 8722ad7

17 files changed

+90
-1
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
- [trace_macros](language-features/trace-macros.md)
9393
- [type_ascription](language-features/type-ascription.md)
9494
- [unboxed_closures](language-features/unboxed-closures.md)
95+
- [unsized_tuple_coercion](language-features/unsized-tuple-coercion.md)
9596
- [untagged_unions](language-features/untagged-unions.md)
9697
- [unwind_attributes](language-features/unwind-attributes.md)
9798
- [use_extern_macros](language-features/use-extern-macros.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# `unsized_tuple_coercion`
2+
3+
The tracking issue for this feature is: [#XXXXX]
4+
5+
[#XXXXX]: https://github.com/rust-lang/rust/issues/XXXXX
6+
7+
------------------------
8+
9+
This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
10+
11+
```rust
12+
impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
13+
```
14+
15+
This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
16+
17+
```rust
18+
#![feature(unsized_tuple_coercion)]
19+
20+
fn main() {
21+
let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
22+
let y : &([i32; 3], [i32]) = &x;
23+
assert_eq!(y.1[0], 4);
24+
}
25+
```
26+
27+
[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md

src/librustc_typeck/check/coercion.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult;
7676
use rustc::ty::subst::Subst;
7777
use errors::DiagnosticBuilder;
7878
use syntax::abi;
79+
use syntax::feature_gate;
7980
use syntax::ptr::P;
8081
use syntax_pos;
8182

@@ -520,14 +521,24 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
520521
coerce_source,
521522
&[coerce_target]));
522523

524+
let mut has_unsized_tuple_coercion = false;
525+
523526
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
524527
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
525528
// inference might unify those two inner type variables later.
526529
let traits = [coerce_unsized_did, unsize_did];
527530
while let Some(obligation) = queue.pop_front() {
528531
debug!("coerce_unsized resolve step: {:?}", obligation);
529532
let trait_ref = match obligation.predicate {
530-
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
533+
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
534+
if unsize_did == tr.def_id() {
535+
if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty {
536+
debug!("coerce_unsized: found unsized tuple coercion");
537+
has_unsized_tuple_coercion = true;
538+
}
539+
}
540+
tr.clone()
541+
}
531542
_ => {
532543
coercion.obligations.push(obligation);
533544
continue;
@@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
557568
}
558569
}
559570

571+
if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion {
572+
feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
573+
"unsized_tuple_coercion",
574+
self.cause.span,
575+
feature_gate::GateIssue::Language,
576+
feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION);
577+
}
578+
560579
Ok(coercion)
561580
}
562581

src/libsyntax/feature_gate.rs

+6
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,9 @@ declare_features! (
352352

353353
// rustc internal
354354
(active, abi_thiscall, "1.19.0", None),
355+
356+
// Allows unsized tuple coercion.
357+
(active, unsized_tuple_coercion, "1.20.0", None),
355358
);
356359

357360
declare_features! (
@@ -1019,6 +1022,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str =
10191022
pub const EXPLAIN_PLACEMENT_IN: &'static str =
10201023
"placement-in expression syntax is experimental and subject to change.";
10211024

1025+
pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1026+
"Unsized tuple coercion is not stable enough for use and is subject to change";
1027+
10221028
struct PostExpansionVisitor<'a> {
10231029
context: &'a Context<'a>,
10241030
}

src/test/compile-fail/dst-bad-assign-3.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// Forbid assignment into a dynamically sized type.
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
type Fat<T: ?Sized> = (isize, &'static str, T);
1416
//~^ WARNING trait bounds are not (yet) enforced
1517

src/test/compile-fail/dst-bad-coerce1.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// Attempt to change the type as well as unsizing.
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
struct Fat<T: ?Sized> {
1416
ptr: T
1517
}

src/test/compile-fail/dst-bad-coerce3.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// Attempt to extend the lifetime as well as unsizing.
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
struct Fat<T: ?Sized> {
1416
ptr: T
1517
}

src/test/compile-fail/dst-bad-coerce4.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// Attempt to coerce from unsized to sized.
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
struct Fat<T: ?Sized> {
1416
ptr: T
1517
}

src/test/compile-fail/dst-bad-deep-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
// because it would require stack allocation of an unsized temporary (*g in the
1414
// test).
1515

16+
#![feature(unsized_tuple_coercion)]
17+
1618
pub fn main() {
1719
let f: ([isize; 3],) = ([5, 6, 7],);
1820
let g: &([isize],) = &f;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
let _ : &(Send,) = &((),);
13+
//~^ ERROR Unsized tuple coercion is not stable enough
14+
}

src/test/run-pass-valgrind/dst-dtor-3.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// no-prefer-dynamic
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
static mut DROP_RAN: bool = false;
1416

1517
struct Foo;

src/test/run-pass-valgrind/dst-dtor-4.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
// no-prefer-dynamic
1212

13+
#![feature(unsized_tuple_coercion)]
14+
1315
static mut DROP_RAN: isize = 0;
1416

1517
struct Foo;

src/test/run-pass/dst-irrefutable-bind.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![feature(unsized_tuple_coercion)]
12+
1113
struct Test<T: ?Sized>(T);
1214

1315
fn main() {

src/test/run-pass/dst-raw.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// Test DST raw pointers
1212

1313

14+
#![feature(unsized_tuple_coercion)]
15+
1416
trait Trait {
1517
fn foo(&self) -> isize;
1618
}

src/test/run-pass/dst-trait-tuple.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#![allow(unused_features)]
1313
#![feature(box_syntax)]
14+
#![feature(unsized_tuple_coercion)]
1415

1516
type Fat<T: ?Sized> = (isize, &'static str, T);
1617

src/test/run-pass/dst-tuple-sole.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// As dst-tuple.rs, but the unsized field is the only field in the tuple.
1212

1313

14+
#![feature(unsized_tuple_coercion)]
15+
1416
type Fat<T: ?Sized> = (T,);
1517

1618
// x is a fat pointer

src/test/run-pass/dst-tuple.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#![allow(unknown_features)]
1313
#![feature(box_syntax)]
14+
#![feature(unsized_tuple_coercion)]
1415

1516
type Fat<T: ?Sized> = (isize, &'static str, T);
1617

0 commit comments

Comments
 (0)