Skip to content

Commit 031cce8

Browse files
committedFeb 3, 2021
add relaxed_struct_unsize feature gate
1 parent 50e394a commit 031cce8

File tree

6 files changed

+73
-15
lines changed

6 files changed

+73
-15
lines changed
 

‎compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,9 @@ declare_features! (
631631

632632
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
633633
(active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
634+
635+
/// Lessens the requirements for structs to implement `Unsize`.
636+
(active, relaxed_struct_unsize, "1.51.0", Some(1), None),
634637
// -------------------------------------------------------------------------
635638
// feature-group-end: actual feature gates
636639
// -------------------------------------------------------------------------

‎compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ symbols! {
907907
register_attr,
908908
register_tool,
909909
relaxed_adts,
910+
relaxed_struct_unsize,
910911
rem,
911912
rem_assign,
912913
repr,

‎compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+44-15
Original file line numberDiff line numberDiff line change
@@ -823,33 +823,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
823823
},
824824
};
825825

826+
// FIXME(eddyb) cache this (including computing `unsizing_params`)
827+
// by putting it in a query; it would only need the `DefId` as it
828+
// looks at declared field types, not anything substituted.
829+
826830
// The last field of the structure has to exist and contain type/const parameters.
827831
let (tail_field, prefix_fields) =
828832
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
829833
let tail_field_ty = tcx.type_of(tail_field.did);
830834

831835
let mut unsizing_params = GrowableBitSet::new_empty();
832-
for arg in tail_field_ty.walk() {
833-
if let Some(i) = maybe_unsizing_param_idx(arg) {
834-
unsizing_params.insert(i);
836+
if tcx.features().relaxed_struct_unsize {
837+
for arg in tail_field_ty.walk() {
838+
if let Some(i) = maybe_unsizing_param_idx(arg) {
839+
unsizing_params.insert(i);
840+
}
835841
}
836-
}
837842

838-
// Ensure none of the other fields mention the parameters used
839-
// in unsizing.
840-
// FIXME(eddyb) cache this (including computing `unsizing_params`)
841-
// by putting it in a query; it would only need the `DefId` as it
842-
// looks at declared field types, not anything substituted.
843-
for field in prefix_fields {
844-
for arg in tcx.type_of(field.did).walk() {
843+
// Ensure none of the other fields mention the parameters used
844+
// in unsizing.
845+
for field in prefix_fields {
846+
for arg in tcx.type_of(field.did).walk() {
847+
if let Some(i) = maybe_unsizing_param_idx(arg) {
848+
unsizing_params.remove(i);
849+
}
850+
}
851+
}
852+
853+
if unsizing_params.is_empty() {
854+
return Err(Unimplemented);
855+
}
856+
} else {
857+
let mut found = false;
858+
for arg in tail_field_ty.walk() {
845859
if let Some(i) = maybe_unsizing_param_idx(arg) {
846-
unsizing_params.remove(i);
860+
unsizing_params.insert(i);
861+
found = true;
847862
}
848863
}
849-
}
864+
if !found {
865+
return Err(Unimplemented);
866+
}
850867

851-
if unsizing_params.is_empty() {
852-
return Err(Unimplemented);
868+
// Ensure none of the other fields mention the parameters used
869+
// in unsizing.
870+
// FIXME(eddyb) cache this (including computing `unsizing_params`)
871+
// by putting it in a query; it would only need the `DefId` as it
872+
// looks at declared field types, not anything substituted.
873+
for field in prefix_fields {
874+
for arg in tcx.type_of(field.did).walk() {
875+
if let Some(i) = maybe_unsizing_param_idx(arg) {
876+
if unsizing_params.contains(i) {
877+
return Err(Unimplemented);
878+
}
879+
}
880+
}
881+
}
853882
}
854883

855884
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Test that we allow unsizing even if there is an unchanged param in the
2+
// field getting unsized.
3+
struct A<T, U: ?Sized + 'static>(T, B<T, U>);
4+
struct B<T, U: ?Sized>(T, U);
5+
6+
fn main() {
7+
let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
8+
let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
9+
assert_eq!(y.1.1.len(), 1);
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
3+
|
4+
LL | let y: &A<[u32; 1], [u32]> = &x;
5+
| ------------------- ^^ expected slice `[u32]`, found array `[u32; 1]`
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected reference `&A<[u32; 1], [u32]>`
10+
found reference `&A<[u32; 1], [u32; 1]>`
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0308`.

‎src/test/ui/unsized/unchanged-param.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(relaxed_struct_unsize)]
12
// run-pass
23
// Test that we allow unsizing even if there is an unchanged param in the
34
// field getting unsized.

0 commit comments

Comments
 (0)
Please sign in to comment.