Move unsized_tuple_coercion behind a feature gate.
This commit is contained in:
parent
b0bf1b4682
commit
03660b6476
@ -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
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
// Attempt to change the type as well as unsizing.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
// Attempt to extend the lifetime as well as unsizing.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
// Attempt to coerce from unsized to sized.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -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;
|
||||
|
14
src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
Normal file
14
src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
Normal 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
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
static mut DROP_RAN: bool = false;
|
||||
|
||||
struct Foo;
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
static mut DROP_RAN: isize = 0;
|
||||
|
||||
struct Foo;
|
||||
|
@ -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() {
|
||||
|
@ -11,6 +11,8 @@
|
||||
// Test DST raw pointers
|
||||
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> isize;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#![allow(unused_features)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (isize, &'static str, T);
|
||||
|
||||
|
@ -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
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (isize, &'static str, T);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user