Skip to content

Commit

Permalink
Move unsized_tuple_coercion behind a feature gate.
Browse files Browse the repository at this point in the history
  • Loading branch information
qnighy committed Jun 24, 2017
1 parent 868f6d0 commit 8722ad7
Show file tree
Hide file tree
Showing 17 changed files with 90 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
- [trace_macros](language-features/trace-macros.md)
- [type_ascription](language-features/type-ascription.md)
- [unboxed_closures](language-features/unboxed-closures.md)
- [unsized_tuple_coercion](language-features/unsized-tuple-coercion.md)
- [untagged_unions](language-features/untagged-unions.md)
- [unwind_attributes](language-features/unwind-attributes.md)
- [use_extern_macros](language-features/use-extern-macros.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
21 changes: 20 additions & 1 deletion src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -520,14 +521,24 @@ 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.
let traits = [coerce_unsized_did, unsize_did];
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;
Expand Down Expand Up @@ -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)
}

Expand Down
6 changes: 6 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ declare_features! (

// rustc internal
(active, abi_thiscall, "1.19.0", None),

// Allows unsized tuple coercion.
(active, unsized_tuple_coercion, "1.20.0", None),
);

declare_features! (
Expand Down Expand Up @@ -1019,6 +1022,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>,
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/dst-bad-assign-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/dst-bad-coerce1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

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

#![feature(unsized_tuple_coercion)]

struct Fat<T: ?Sized> {
ptr: T
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/dst-bad-coerce3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

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

#![feature(unsized_tuple_coercion)]

struct Fat<T: ?Sized> {
ptr: T
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/dst-bad-coerce4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

// Attempt to coerce from unsized to sized.

#![feature(unsized_tuple_coercion)]

struct Fat<T: ?Sized> {
ptr: T
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/dst-bad-deep-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 2 additions & 0 deletions src/test/run-pass-valgrind/dst-dtor-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

// no-prefer-dynamic

#![feature(unsized_tuple_coercion)]

static mut DROP_RAN: bool = false;

struct Foo;
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass-valgrind/dst-dtor-4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

// no-prefer-dynamic

#![feature(unsized_tuple_coercion)]

static mut DROP_RAN: isize = 0;

struct Foo;
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/dst-irrefutable-bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/dst-raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
// Test DST raw pointers


#![feature(unsized_tuple_coercion)]

trait Trait {
fn foo(&self) -> isize;
}
Expand Down
1 change: 1 addition & 0 deletions src/test/run-pass/dst-trait-tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#![allow(unused_features)]
#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]

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

Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/dst-tuple-sole.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/test/run-pass/dst-tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]

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

Expand Down

0 comments on commit 8722ad7

Please sign in to comment.