add relaxed_struct_unsize
feature gate
This commit is contained in:
parent
50e394a05e
commit
031cce8cfc
6 changed files with 75 additions and 17 deletions
|
@ -631,6 +631,9 @@ declare_features! (
|
||||||
|
|
||||||
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
|
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
|
||||||
(active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
|
(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
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -907,6 +907,7 @@ symbols! {
|
||||||
register_attr,
|
register_attr,
|
||||||
register_tool,
|
register_tool,
|
||||||
relaxed_adts,
|
relaxed_adts,
|
||||||
|
relaxed_struct_unsize,
|
||||||
rem,
|
rem,
|
||||||
rem_assign,
|
rem_assign,
|
||||||
repr,
|
repr,
|
||||||
|
|
|
@ -823,33 +823,62 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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.
|
// The last field of the structure has to exist and contain type/const parameters.
|
||||||
let (tail_field, prefix_fields) =
|
let (tail_field, prefix_fields) =
|
||||||
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
|
def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
|
||||||
let tail_field_ty = tcx.type_of(tail_field.did);
|
let tail_field_ty = tcx.type_of(tail_field.did);
|
||||||
|
|
||||||
let mut unsizing_params = GrowableBitSet::new_empty();
|
let mut unsizing_params = GrowableBitSet::new_empty();
|
||||||
for arg in tail_field_ty.walk() {
|
if tcx.features().relaxed_struct_unsize {
|
||||||
if let Some(i) = maybe_unsizing_param_idx(arg) {
|
for arg in tail_field_ty.walk() {
|
||||||
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() {
|
|
||||||
if let Some(i) = maybe_unsizing_param_idx(arg) {
|
if let Some(i) = maybe_unsizing_param_idx(arg) {
|
||||||
unsizing_params.remove(i);
|
unsizing_params.insert(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if unsizing_params.is_empty() {
|
// Ensure none of the other fields mention the parameters used
|
||||||
return Err(Unimplemented);
|
// 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.insert(i);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
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>`.
|
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
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`.
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(relaxed_struct_unsize)]
|
||||||
// run-pass
|
// run-pass
|
||||||
// Test that we allow unsizing even if there is an unchanged param in the
|
// Test that we allow unsizing even if there is an unchanged param in the
|
||||||
// field getting unsized.
|
// field getting unsized.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue