-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Conversation
r? @arielb1 (rust_highfive has picked a reviewer for you, use r? to override) |
Travis failed, but I suppose it is spurious. |
You can close and reopen the PR to restart travis |
@oli-obk Thank you! |
Friendly ping @arielb1 to keep this on your radar! |
Don't we want to feature-gate this somehow? Pinging @rust-lang/lang. |
@@ -2612,6 +2617,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | |||
&[inner_target])); | |||
} | |||
|
|||
// (.., T) -> (.., U). | |||
(&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => { |
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 below mk_adt
/mk_tup
are similar, but I don't think its worth merging...
f: isize | ||
} | ||
|
||
trait ToBar { |
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.
Why these extra methods?
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.
Just because it was copied from dst-bad-assign.rs
.
@@ -28,7 +28,8 @@ struct Fat<T: ?Sized> { | |||
|
|||
pub fn main() { | |||
{ | |||
let _x: Box<Fat<Trait>> = Box::<Fat<Foo>>::new(Fat { f: Foo }); | |||
let _x: Box<(i32, Fat<Trait>)> = |
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.
can you have this in addition to the original test?
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.
Done.
@@ -25,7 +25,8 @@ struct Fat<T: ?Sized> { | |||
|
|||
pub fn main() { | |||
{ | |||
let _x: Box<Fat<[Foo]>> = Box::<Fat<[Foo; 3]>>::new(Fat { f: [Foo, Foo, Foo] }); | |||
let _x: Box<(Fat<[Foo]>,)> = |
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.
can you have this in addition to the original test?
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.
Done.
I'm generally ok with these changes modulo |
Hi @qnighy. We don't want this change to be insta-stable, so we need to add a feature gate and a tracking issue. |
8722ad7
to
818f416
Compare
r+ modulo comment |
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.
r+ modulo comment. Nice PR!
src/librustc/traits/select.rs
Outdated
let b_last = tys_b.last().unwrap(); | ||
|
||
// Check that the source tuple with the target's | ||
// last element is a subtype of the target. |
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.
nit: comment should not say "subtype" but rather "has the same type". Yes I know this is a copy of another comment that says "subtype". Both are wrong. The code does a type equality, and subtyping would be unsound (#40288).
So this comment should be
// Check that the source tuple with the target's
// last element is equal to the target.
And the other one
// Check that the source struct with the target's
// unsized parameters equal to the target.
We should probably be comparing all other type parameters instead of doing this hack. Feel free to do that (in both places), but I'm not going to block this PR on that.
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.
Fixed, thanks!
// 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 comment
The reason will be displayed to describe this comment to others. Learn more.
this is... ok.
☔ The latest upstream changes (presumably #42850) made this pull request unmergeable. Please resolve the merge conflicts. |
1fe43a5
to
0812b33
Compare
☔ The latest upstream changes (presumably #42964) made this pull request unmergeable. Please resolve the merge conflicts. |
0812b33
to
94862c6
Compare
@bors r+ |
📌 Commit 94862c6 has been approved by |
Unsized tuple coercions Part of #18469. Fixes #32702. #37685 and #34451 might also be related. This PR does the following: - Introduce explicit `Sized` constraints on tuple initializers, similar to that of record-struct initializers. Not much relevant to the main contribution but I noticed this when making tests for unsized tuple coercions. - Implement `(.., T): Unsize<(.., U)>` where `T: Unsize<U>`. - Assume `(.., T)` is MaybeUnsizedUnivariant. - Modify `src/librustc/ty/util.rs` and `src/librustc_trans/glue.rs` so that tuples and structs are uniformly traversed when translating.
☀️ Test successful - status-appveyor, status-travis |
Implement Eq/Hash/Debug etc. for unsized tuples. As I mentioned in [the comment in rust-lang#18469](rust-lang#18469 (comment)), the implementations of `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Debug`, `Hash` can be generalized to unsized tuples. This is consistent with the `derive` behavior for unsized structs. ```rust #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] struct MyTuple<X, Y, Z: ?Sized>(X, Y, Z); fn f(x: &MyTuple<i32, i32, [i32]>) { x == x; x < x; println!("{:?}", x); } ``` Questions: - Need an RFC? - Need a feature gate? I don't think it does because the unsized tuple coercion rust-lang#42527 is feature-gated. - I changed `builder.field($name);` into `builder.field(&$name);` in the `Debug` implementation to pass compilation. This won't affect the behavior because `Debug for &'a T` is a mere redirection to `Debug for T`. However, I don't know if it affects code size / performance.
Part of #18469. Fixes #32702.
#37685 and #34451 might also be related.
This PR does the following:
Sized
constraints on tuple initializers, similar to that of record-struct initializers. Not much relevant to the main contribution but I noticed this when making tests for unsized tuple coercions.(.., T): Unsize<(.., U)>
whereT: Unsize<U>
.(.., T)
is MaybeUnsizedUnivariant.src/librustc/ty/util.rs
andsrc/librustc_trans/glue.rs
so that tuples and structs are uniformly traversed when translating.