Move unsized_tuple_coercion behind a feature gate.

This commit is contained in:
Masaki Hara 2017-06-24 16:20:27 +09:00
parent b0bf1b4682
commit 03660b6476
No known key found for this signature in database
GPG Key ID: 7CA7A85E049A82E8
16 changed files with 89 additions and 1 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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>,
}

View File

@ -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

View File

@ -10,6 +10,8 @@
// Attempt to change the type as well as unsizing.
#![feature(unsized_tuple_coercion)]
struct Fat<T: ?Sized> {
ptr: T
}

View File

@ -10,6 +10,8 @@
// Attempt to extend the lifetime as well as unsizing.
#![feature(unsized_tuple_coercion)]
struct Fat<T: ?Sized> {
ptr: T
}

View File

@ -10,6 +10,8 @@
// Attempt to coerce from unsized to sized.
#![feature(unsized_tuple_coercion)]
struct Fat<T: ?Sized> {
ptr: T
}

View File

@ -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;

View File

@ -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
}

View File

@ -10,6 +10,8 @@
// no-prefer-dynamic
#![feature(unsized_tuple_coercion)]
static mut DROP_RAN: bool = false;
struct Foo;

View File

@ -10,6 +10,8 @@
// no-prefer-dynamic
#![feature(unsized_tuple_coercion)]
static mut DROP_RAN: isize = 0;
struct Foo;

View File

@ -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() {

View File

@ -11,6 +11,8 @@
// Test DST raw pointers
#![feature(unsized_tuple_coercion)]
trait Trait {
fn foo(&self) -> isize;
}

View File

@ -11,6 +11,7 @@
#![allow(unused_features)]
#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]
type Fat<T: ?Sized> = (isize, &'static str, T);

View File

@ -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

View File

@ -11,6 +11,7 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]
type Fat<T: ?Sized> = (isize, &'static str, T);