-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unsized tuple coercions #42527
Unsized tuple coercions #42527
Changes from all commits
17fca8b
23d1521
b0bf1b4
03660b6
141265d
94862c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# `unsized_tuple_coercion` | ||
|
||
The tracking issue for this feature is: [#42877] | ||
|
||
[#42877]: https://github.com/rust-lang/rust/issues/42877 | ||
|
||
------------------------ | ||
|
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,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()) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is... ok. |
||
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) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2014 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. | ||
|
||
// 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 | ||
|
||
#[derive(PartialEq,Eq)] | ||
struct Bar; | ||
|
||
#[derive(PartialEq,Eq)] | ||
struct Bar1 { | ||
f: isize | ||
} | ||
|
||
trait ToBar { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why these extra methods? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just because it was copied from |
||
fn to_bar(&self) -> Bar; | ||
fn to_val(&self) -> isize; | ||
} | ||
|
||
impl ToBar for Bar1 { | ||
fn to_bar(&self) -> Bar { | ||
Bar | ||
} | ||
fn to_val(&self) -> isize { | ||
self.f | ||
} | ||
} | ||
|
||
pub fn main() { | ||
// Assignment. | ||
let f5: &mut Fat<ToBar> = &mut (5, "some str", Bar1 {f :42}); | ||
let z: Box<ToBar> = Box::new(Bar1 {f: 36}); | ||
f5.2 = Bar1 {f: 36}; | ||
//~^ ERROR mismatched types | ||
//~| expected type `ToBar` | ||
//~| found type `Bar1` | ||
//~| expected trait ToBar, found struct `Bar1` | ||
//~| ERROR `ToBar: std::marker::Sized` is not satisfied | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll prefer to merge this with the ADT code somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've thought before that we should have an "infinite family" of tuple ADTs. One complication is that ADTs have def-ids...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code above
mk_adt
largely depends on def-ids and type parameters, so I doubt I can merge this part with tuple's. The codes belowmk_adt
/mk_tup
are similar, but I don't think its worth merging...