]> git.lizzy.rs Git - rust.git/commitdiff
add `relaxed_struct_unsize` feature gate
authorBastian Kauschke <bastian_kauschke@hotmail.de>
Wed, 3 Feb 2021 22:56:47 +0000 (23:56 +0100)
committerBastian Kauschke <bastian_kauschke@hotmail.de>
Wed, 3 Feb 2021 23:00:41 +0000 (00:00 +0100)
compiler/rustc_feature/src/active.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr [new file with mode: 0644]
src/test/ui/unsized/unchanged-param.rs

index 818f6c70de01eef911166e9d9cea437711cc36b3..4f38e060023675fcb922cc3d151497732c1537e6 100644 (file)
@@ -631,6 +631,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
 
     /// 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
     // -------------------------------------------------------------------------
index df23b4006b347e5a5fcd69f67aa2654c7f049410..86f8061a24affe52ee2ebc076bf261df108b82e9 100644 (file)
         register_attr,
         register_tool,
         relaxed_adts,
+        relaxed_struct_unsize,
         rem,
         rem_assign,
         repr,
index 3e3e945f654b7a495934932ed74d80b1b2594010..ed3e117fcfabbbb841243ddf86e5eb868862e95e 100644 (file)
@@ -823,33 +823,62 @@ fn confirm_builtin_unsize_candidate(
                     },
                 };
 
+                // 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>`.
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
new file mode 100644 (file)
index 0000000..0cfd0a0
--- /dev/null
@@ -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);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
new file mode 100644 (file)
index 0000000..f62def4
--- /dev/null
@@ -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`.
index 93c7af68ac388e145714fe11c473d29eb0b5b16b..83199e8112e71d2ad12245d61793e49d91e142bc 100644 (file)
@@ -1,3 +1,4 @@
+#![feature(relaxed_struct_unsize)]
 // run-pass
 // Test that we allow unsizing even if there is an unchanged param in the
 // field getting unsized.