/// Allows `extern "C-cmse-nonsecure-call" fn()`.
(active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
+
+ /// Lessens the requirements for structs to implement `Unsize`.
+ (active, relaxed_struct_unsize, "1.51.0", Some(1), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
},
};
+ // FIXME(eddyb) cache this (including computing `unsizing_params`)
+ // by putting it in a query; it would only need the `DefId` as it
+ // looks at declared field types, not anything substituted.
+
// The last field of the structure has to exist and contain type/const parameters.
let (tail_field, prefix_fields) =
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
let tail_field_ty = tcx.type_of(tail_field.did);
let mut unsizing_params = GrowableBitSet::new_empty();
- for arg in tail_field_ty.walk() {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.insert(i);
+ if tcx.features().relaxed_struct_unsize {
+ for arg in tail_field_ty.walk() {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ unsizing_params.insert(i);
+ }
}
- }
- // Ensure none of the other fields mention the parameters used
- // in unsizing.
- // FIXME(eddyb) cache this (including computing `unsizing_params`)
- // by putting it in a query; it would only need the `DefId` as it
- // looks at declared field types, not anything substituted.
- for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk() {
+ // Ensure none of the other fields mention the parameters used
+ // in unsizing.
+ for field in prefix_fields {
+ for arg in tcx.type_of(field.did).walk() {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ unsizing_params.remove(i);
+ }
+ }
+ }
+
+ if unsizing_params.is_empty() {
+ return Err(Unimplemented);
+ }
+ } else {
+ let mut found = false;
+ for arg in tail_field_ty.walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.remove(i);
+ unsizing_params.insert(i);
+ found = true;
}
}
- }
+ if !found {
+ return Err(Unimplemented);
+ }
- if unsizing_params.is_empty() {
- return Err(Unimplemented);
+ // Ensure none of the other fields mention the parameters used
+ // in unsizing.
+ // FIXME(eddyb) cache this (including computing `unsizing_params`)
+ // by putting it in a query; it would only need the `DefId` as it
+ // looks at declared field types, not anything substituted.
+ for field in prefix_fields {
+ for arg in tcx.type_of(field.did).walk() {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ if unsizing_params.contains(i) {
+ return Err(Unimplemented);
+ }
+ }
+ }
+ }
}
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
--- /dev/null
+// Test that we allow unsizing even if there is an unchanged param in the
+// field getting unsized.
+struct A<T, U: ?Sized + 'static>(T, B<T, U>);
+struct B<T, U: ?Sized>(T, U);
+
+fn main() {
+ let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
+ let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
+ assert_eq!(y.1.1.len(), 1);
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
+ |
+LL | let y: &A<[u32; 1], [u32]> = &x;
+ | ------------------- ^^ expected slice `[u32]`, found array `[u32; 1]`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&A<[u32; 1], [u32]>`
+ found reference `&A<[u32; 1], [u32; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.