From 45f03da8198840fb074122027b5aa869d41eecc9 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 8 May 2020 18:06:28 -0300
Subject: [PATCH 1/8] Add unsized_fn_params feature

---
 library/alloc/src/lib.rs                      |  3 +-
 library/core/src/lib.rs                       |  1 +
 src/librustc_feature/active.rs                |  2 ++
 .../borrow_check/type_check/mod.rs            |  2 +-
 .../build/expr/as_operand.rs                  |  2 +-
 src/librustc_span/symbol.rs                   |  1 +
 .../traits/error_reporting/suggestions.rs     |  2 +-
 src/librustc_typeck/check/expr.rs             |  2 +-
 src/librustc_typeck/check/mod.rs              | 28 +++++++++++++++----
 .../long-live-the-unsized-temporary.rs        |  9 ++----
 src/test/ui/error-codes/E0277.stderr          |  7 ++---
 .../feature-gate-unsized_fn_params.rs         | 26 +++++++++++++++++
 .../feature-gate-unsized_fn_params.stderr     | 25 +++++++++++++++++
 .../feature-gate-unsized_locals.stderr        |  8 ++----
 src/test/ui/fn/dyn-fn-alignment.rs            |  2 +-
 src/test/ui/issues/issue-17651.stderr         |  2 +-
 src/test/ui/issues/issue-27078.stderr         |  5 +++-
 src/test/ui/issues/issue-30355.stderr         |  2 +-
 src/test/ui/issues/issue-38954.stderr         |  8 ++----
 src/test/ui/issues/issue-41229-ref-str.stderr |  8 ++----
 src/test/ui/issues/issue-42312.stderr         | 12 ++++----
 src/test/ui/issues/issue-5883.stderr          |  8 ++----
 ...-same-trait-object-with-separate-params.rs |  2 +-
 src/test/ui/resolve/issue-5035-2.stderr       |  8 ++----
 src/test/ui/suggestions/path-by-value.stderr  |  7 ++---
 .../trait-bounds-not-on-bare-trait.stderr     |  8 ++----
 src/test/ui/unsized-locals/autoderef.rs       |  3 +-
 .../ui/unsized-locals/auxiliary/ufuncs.rs     |  2 +-
 .../ui/unsized-locals/borrow-after-move.rs    |  2 +-
 ...y-value-trait-object-safety-withdefault.rs |  3 +-
 src/test/ui/unsized-locals/double-move.rs     |  2 +-
 .../issue-30276-feature-flagged.stderr        |  7 +++--
 src/test/ui/unsized-locals/issue-30276.stderr |  2 +-
 .../issue-50940-with-feature.rs               |  2 +-
 src/test/ui/unsized-locals/issue-50940.stderr |  2 +-
 .../ui/unsized-locals/unsized-exprs-rpass.rs  | 10 ++-----
 src/test/ui/unsized-locals/unsized-exprs.rs   |  2 +-
 src/test/ui/unsized-locals/unsized-exprs2.rs  |  2 +-
 .../ui/unsized-locals/unsized-exprs3.stderr   |  2 +-
 src/test/ui/unsized-locals/unsized-index.rs   | 10 +++++--
 .../ui/unsized-locals/unsized-parameters.rs   |  2 +-
 src/test/ui/unsized6.stderr                   | 18 ++++++------
 42 files changed, 157 insertions(+), 104 deletions(-)
 create mode 100644 src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
 create mode 100644 src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr

diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 6350e38554647..b46e3723c70c2 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -121,7 +121,8 @@
 #![feature(unicode_internals)]
 #![feature(unsafe_block_in_unsafe_fn)]
 #![feature(unsize)]
-#![feature(unsized_locals)]
+#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
+#![cfg_attr(bootstrap, feature(unsized_locals))]
 #![feature(allocator_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice)]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index da402040b93f0..155925a68bac1 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -123,6 +123,7 @@
 #![feature(transparent_unions)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
+#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(variant_count)]
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index d7c310a8b4c8b..120c717919601 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -578,6 +578,8 @@ declare_features! (
 
     /// Alloc calling `transmute` in const fn
     (active, const_fn_transmute, "1.46.0", Some(53605), None),
+    /// Allows unsized fn parameters.
+    (active, unsized_fn_params, "1.45.0", Some(48055), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index bc5c144cd742c..bda5107dd4e1e 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1734,7 +1734,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                 // When `#![feature(unsized_locals)]` is not enabled,
                 // this check is done at `check_local`.
-                if self.tcx().features().unsized_locals {
+                if self.tcx().features().unsized_fn_params {
                     let span = term.source_info.span;
                     self.ensure_place_sized(dest_ty, span);
                 }
diff --git a/src/librustc_mir_build/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs
index 5949fd1e22ce8..8adb836c2bcb3 100644
--- a/src/librustc_mir_build/build/expr/as_operand.rs
+++ b/src/librustc_mir_build/build/expr/as_operand.rs
@@ -165,7 +165,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         let tcx = this.hir.tcx();
 
-        if tcx.features().unsized_locals {
+        if tcx.features().unsized_fn_params {
             let ty = expr.ty;
             let span = expr.span;
             let param_env = this.hir.param_env;
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 98776a0478237..1cbf91ff0c04e 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -1144,6 +1144,7 @@ symbols! {
         unsafe_cell,
         unsafe_no_drop_flag,
         unsize,
+        unsized_fn_params,
         unsized_locals,
         unsized_tuple_coercion,
         unstable,
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 13f8c71a629a9..bf06f37b9e9b8 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1833,7 +1833,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     err.note("all function arguments must have a statically known size");
                 }
                 if tcx.sess.opts.unstable_features.is_nightly_build()
-                    && !self.tcx.features().unsized_locals
+                    && !self.tcx.features().unsized_fn_params
                 {
                     err.help("unsized locals are gated as an unstable feature");
                 }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index e7eaca62bdd8e..ee44a4dfc7e9b 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -464,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let ty::FnDef(..) = ty.kind {
             let fn_sig = ty.fn_sig(tcx);
-            if !tcx.features().unsized_locals {
+            if !tcx.features().unsized_fn_params {
                 // We want to remove some Sized bounds from std functions,
                 // but don't want to expose the removal to stable Rust.
                 // i.e., we don't want to allow
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6cefc99f7b171..4f32003889d65 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1051,7 +1051,8 @@ fn typeck_with_fallback<'tcx>(
             };
 
             // Gather locals in statics (because of block expressions).
-            GatherLocalsVisitor { fcx: &fcx, parent_id: id }.visit_body(body);
+            GatherLocalsVisitor { fcx: &fcx, parent_id: id, within_fn_param: false }
+                .visit_body(body);
 
             fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
 
@@ -1154,6 +1155,10 @@ fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
 struct GatherLocalsVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     parent_id: hir::HirId,
+    // params are special cases of pats, but we want to handle them as
+    // *distinct* cases. so track when we are hitting a pat *within* an fn
+    // param.
+    within_fn_param: bool,
 }
 
 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
@@ -1228,13 +1233,25 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
         intravisit::walk_local(self, local);
     }
 
+    fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+        self.within_fn_param = true;
+        intravisit::walk_param(self, param);
+        self.within_fn_param = false;
+    }
+
     // Add pattern bindings.
     fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
         if let PatKind::Binding(_, _, ident, _) = p.kind {
             let var_ty = self.assign(p.span, p.hir_id, None);
 
-            if !self.fcx.tcx.features().unsized_locals {
-                self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
+            if self.within_fn_param {
+                if !self.fcx.tcx.features().unsized_fn_params {
+                    self.fcx.require_type_is_sized(var_ty, p.span, traits::SizedArgumentType);
+                }
+            } else {
+                if !self.fcx.tcx.features().unsized_locals {
+                    self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
+                }
             }
 
             debug!(
@@ -1334,7 +1351,8 @@ fn check_fn<'a, 'tcx>(
 
     let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
     let outer_hir_id = hir.as_local_hir_id(outer_def_id);
-    GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
+    GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id, within_fn_param: false }
+        .visit_body(body);
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
     // (as it's created inside the body itself, not passed in from outside).
@@ -1360,7 +1378,7 @@ fn check_fn<'a, 'tcx>(
         // The check for a non-trivial pattern is a hack to avoid duplicate warnings
         // for simple cases like `fn foo(x: Trait)`,
         // where we would error once on the parameter as a whole, and once on the binding `x`.
-        if param.pat.simple_ident().is_none() && !tcx.features().unsized_locals {
+        if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
             fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
         }
 
diff --git a/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs b/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs
index 2f275f88d963e..a7b9052617f0c 100644
--- a/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs
+++ b/src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs
@@ -1,4 +1,5 @@
-#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 use std::fmt;
 
@@ -45,11 +46,7 @@ fn main() {
 
     {
         let x: fmt::Display = *gen_foo();
-        let x = if true {
-            x
-        } else {
-            *gen_foo()
-        };
+        let x = if true { x } else { *gen_foo() };
         foo(x);
     }
 }
diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
index 203fc18915647..30b2bc09efa83 100644
--- a/src/test/ui/error-codes/E0277.stderr
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -6,11 +6,8 @@ LL | fn f(p: Path) { }
    |
    = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `std::path::Path`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn f(p: &Path) { }
-   |         ^
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/E0277.rs:17:15
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
new file mode 100644
index 0000000000000..45bde37a3ac5e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
@@ -0,0 +1,26 @@
+#[repr(align(256))]
+#[allow(dead_code)]
+struct A {
+    v: u8,
+}
+
+trait Foo {
+    fn foo(&self);
+}
+
+impl Foo for A {
+    fn foo(&self) {
+        assert_eq!(self as *const A as usize % 256, 0);
+    }
+}
+
+fn foo(x: dyn Foo) {
+    //~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time [E0277]
+    x.foo()
+}
+
+fn main() {
+    let x: Box<dyn Foo> = Box::new(A { v: 22 });
+    foo(*x);
+    //~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time [E0277]
+}
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
new file mode 100644
index 0000000000000..f6dd6790251d7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:17:8
+   |
+LL | fn foo(x: dyn Foo) {
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:5
+   |
+LL |     foo(*x);
+   |     ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
index 0195cc1481e74..285a0771f6d4f 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
@@ -5,11 +5,9 @@ LL | fn f(f: dyn FnOnce()) {}
    |      ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn f(f: &dyn FnOnce()) {}
-   |         ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/fn/dyn-fn-alignment.rs b/src/test/ui/fn/dyn-fn-alignment.rs
index 125f44bbf0093..ecd7c1744a008 100644
--- a/src/test/ui/fn/dyn-fn-alignment.rs
+++ b/src/test/ui/fn/dyn-fn-alignment.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![feature(unsized_fn_params)]
 #![allow(dead_code)]
 #[repr(align(256))]
 struct A {
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
index 812778911a865..94360c3fd4e7e 100644
--- a/src/test/ui/issues/issue-17651.stderr
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -15,7 +15,7 @@ LL |     (|| Box::new(*(&[0][..])))();
    |
    = help: the trait `std::marker::Sized` is not implemented for `[{integer}]`
    = note: all function arguments must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr
index de1810e99aac6..378b614cf18ae 100644
--- a/src/test/ui/issues/issue-27078.stderr
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -4,7 +4,10 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
 LL |     fn foo(self) -> &'static i32 {
    |            ^^^^ doesn't have a size known at compile-time
    |
-   = help: unsized locals are gated as an unstable feature
+   = help: the trait `std::marker::Sized` is not implemented for `Self`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 help: consider further restricting `Self`
    |
 LL |     fn foo(self) -> &'static i32 where Self: std::marker::Sized {
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
index 98de768a5a819..40bd49d7de478 100644
--- a/src/test/ui/issues/issue-30355.stderr
+++ b/src/test/ui/issues/issue-30355.stderr
@@ -6,7 +6,7 @@ LL |     &X(*Y)
    |
    = help: the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: all function arguments must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-38954.stderr b/src/test/ui/issues/issue-38954.stderr
index e96bbe1a99312..bdae4990569f1 100644
--- a/src/test/ui/issues/issue-38954.stderr
+++ b/src/test/ui/issues/issue-38954.stderr
@@ -5,11 +5,9 @@ LL | fn _test(ref _p: str) {}
    |          ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn _test(ref _p: &str) {}
-   |                  ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-41229-ref-str.stderr b/src/test/ui/issues/issue-41229-ref-str.stderr
index 35aa1acdc1c9b..e8967071a0663 100644
--- a/src/test/ui/issues/issue-41229-ref-str.stderr
+++ b/src/test/ui/issues/issue-41229-ref-str.stderr
@@ -5,11 +5,9 @@ LL | pub fn example(ref s: str) {}
    |                ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | pub fn example(ref s: &str) {}
-   |                       ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr
index fbe87aa2dbee5..4a92e63550c02 100644
--- a/src/test/ui/issues/issue-42312.stderr
+++ b/src/test/ui/issues/issue-42312.stderr
@@ -5,7 +5,9 @@ LL |     fn baz(_: Self::Target) where Self: Deref {}
    |            ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `<Self as std::ops::Deref>::Target`
-   = help: unsized locals are gated as an unstable feature
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 help: consider further restricting the associated type
    |
 LL |     fn baz(_: Self::Target) where Self: Deref, <Self as std::ops::Deref>::Target: std::marker::Sized {}
@@ -22,11 +24,9 @@ LL | pub fn f(_: dyn ToString) {}
    |          ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn std::string::ToString + 'static)`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | pub fn f(_: &dyn ToString) {}
-   |             ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index 897984d0ae410..636428d557afa 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -5,11 +5,9 @@ LL | fn new_struct(r: dyn A + 'static)
    |               ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn new_struct(r: &dyn A + 'static)
-   |                  ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
   --> $DIR/issue-5883.rs:8:8
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
index 5ceba64678410..abd2faa7dc659 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -1,4 +1,4 @@
-#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals)]
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals, unsized_fn_params)]
 
 // This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
 // it checks that the `ObjectCandidate` you get from method matching can't
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index 4ed93ad3279ad..82fec52a573e4 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -5,11 +5,9 @@ LL | fn foo(_x: K) {}
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn foo(_x: &K) {}
-   |            ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr
index 2b7c29e20cd31..a3cb6ffd4d5e3 100644
--- a/src/test/ui/suggestions/path-by-value.stderr
+++ b/src/test/ui/suggestions/path-by-value.stderr
@@ -6,11 +6,8 @@ LL | fn f(p: Path) { }
    |
    = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `std::path::Path`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn f(p: &Path) { }
-   |         ^
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
index daca91abff843..14a9e4343f9d9 100644
--- a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
+++ b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
@@ -13,11 +13,9 @@ LL | fn foo(_x: Foo + Send) {
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + std::marker::Send + 'static)`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn foo(_x: &Foo + Send) {
-   |            ^
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/unsized-locals/autoderef.rs b/src/test/ui/unsized-locals/autoderef.rs
index 7f2d2f9c7ef3b..63d9ce6d3c3e5 100644
--- a/src/test/ui/unsized-locals/autoderef.rs
+++ b/src/test/ui/unsized-locals/autoderef.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String;
@@ -24,7 +24,6 @@ impl Foo for dyn FnMut() -> String {
     }
 }
 
-
 fn main() {
     let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>);
     assert_eq!(&x.foo() as &str, "hello");
diff --git a/src/test/ui/unsized-locals/auxiliary/ufuncs.rs b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
index 065563d45a472..5954abf3a1fc5 100644
--- a/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
+++ b/src/test/ui/unsized-locals/auxiliary/ufuncs.rs
@@ -1,3 +1,3 @@
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub fn udrop<T: ?Sized>(_x: T) {}
diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs
index 3299fdf3a9ce8..4e02ea6a4f49f 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.rs
+++ b/src/test/ui/unsized-locals/borrow-after-move.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
index 8b39a99da582e..b05504fbe820d 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String {
@@ -12,7 +12,6 @@ struct A;
 
 impl Foo for A {}
 
-
 fn main() {
     let x = *(Box::new(A) as Box<dyn Foo>);
     assert_eq!(x.foo(), format!("hello"));
diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs
index c3a50341bc962..5c430a0c388e3 100644
--- a/src/test/ui/unsized-locals/double-move.rs
+++ b/src/test/ui/unsized-locals/double-move.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
index 2ed35dc0e2c12..40646139a6d73 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -4,9 +4,10 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
 LL |     let _x: fn(_) -> Test = Test;
    |                             ^^^^ doesn't have a size known at compile-time
    |
-   = help: within `Test`, the trait `std::marker::Sized` is not implemented for `[i32]`
-   = note: required because it appears within the type `Test`
-   = note: the return type of a function must have a statically known size
+   = help: the trait `std::marker::Sized` is not implemented for `[i32]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized-locals/issue-30276.stderr b/src/test/ui/unsized-locals/issue-30276.stderr
index 461efcf3dbf29..0df7924a946d3 100644
--- a/src/test/ui/unsized-locals/issue-30276.stderr
+++ b/src/test/ui/unsized-locals/issue-30276.stderr
@@ -6,7 +6,7 @@ LL |     let _x: fn(_) -> Test = Test;
    |
    = help: the trait `std::marker::Sized` is not implemented for `[i32]`
    = note: all function arguments must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
index 3e5d39ab31150..310dfc9b62326 100644
--- a/src/test/ui/unsized-locals/issue-50940-with-feature.rs
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 fn main() {
     struct A<X: ?Sized>(X);
diff --git a/src/test/ui/unsized-locals/issue-50940.stderr b/src/test/ui/unsized-locals/issue-50940.stderr
index 8e5f753082734..2dcea9eca9e8c 100644
--- a/src/test/ui/unsized-locals/issue-50940.stderr
+++ b/src/test/ui/unsized-locals/issue-50940.stderr
@@ -6,7 +6,7 @@ LL |     A as fn(str) -> A<str>;
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: all function arguments must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
index 24c2758a0a255..fc564d16ddb68 100644
--- a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(unused_braces, unused_parens)]
-#![feature(unsized_tuple_coercion, unsized_locals)]
+#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
@@ -24,12 +24,8 @@ fn main() {
     udrop::<[u8]>(loop {
         break *foo();
     });
-    udrop::<[u8]>(if true {
-        *foo()
-    } else {
-        *foo()
-    });
-    udrop::<[u8]>({*foo()});
+    udrop::<[u8]>(if true { *foo() } else { *foo() });
+    udrop::<[u8]>({ *foo() });
     udrop::<[u8]>((*foo()));
     udrop::<[u8]>((*tfoo()).1);
     *afoo() + 42;
diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
index 8ca88edcb6add..be3140db86b72 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_locals)]
+#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
index 534439aa6c41c..495316c276e8d 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -1,4 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_locals)]
+#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs3.stderr b/src/test/ui/unsized-locals/unsized-exprs3.stderr
index 11435ec0353bc..4fbade89d5736 100644
--- a/src/test/ui/unsized-locals/unsized-exprs3.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs3.stderr
@@ -6,7 +6,7 @@ LL |     udrop as fn([u8]);
    |
    = help: the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: all function arguments must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsized-locals/unsized-index.rs b/src/test/ui/unsized-locals/unsized-index.rs
index 19ad97a853e83..470e0e2f12ea5 100644
--- a/src/test/ui/unsized-locals/unsized-index.rs
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -5,7 +5,7 @@
 // Tightening the bound now could be a breaking change. Although no crater
 // regression were observed (https://github.com/rust-lang/rust/pull/59527),
 // let's be conservative and just add a test for this.
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 use std::ops;
 
@@ -13,11 +13,15 @@ pub struct A;
 
 impl ops::Index<str> for A {
     type Output = ();
-    fn index(&self, _: str) -> &Self::Output { panic!() }
+    fn index(&self, _: str) -> &Self::Output {
+        panic!()
+    }
 }
 
 impl ops::IndexMut<str> for A {
-    fn index_mut(&mut self, _: str) -> &mut Self::Output { panic!() }
+    fn index_mut(&mut self, _: str) -> &mut Self::Output {
+        panic!()
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/unsized-locals/unsized-parameters.rs b/src/test/ui/unsized-locals/unsized-parameters.rs
index 3624154d5c44c..6d87f07f43b18 100644
--- a/src/test/ui/unsized-locals/unsized-parameters.rs
+++ b/src/test/ui/unsized-locals/unsized-parameters.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub fn f0(_f: dyn FnOnce()) {}
 pub fn f1(_s: str) {}
diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr
index f045bfe2444bc..d86221b3273f8 100644
--- a/src/test/ui/unsized6.stderr
+++ b/src/test/ui/unsized6.stderr
@@ -132,11 +132,10 @@ LL | fn g1<X: ?Sized>(x: X) {}
    |       |
    |       this type parameter needs to be `std::marker::Sized`
    |
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn g1<X: ?Sized>(x: &X) {}
-   |                     ^
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized6.rs:40:22
@@ -146,11 +145,10 @@ LL | fn g2<X: ?Sized + T>(x: X) {}
    |       |
    |       this type parameter needs to be `std::marker::Sized`
    |
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL | fn g2<X: ?Sized + T>(x: &X) {}
-   |                         ^
+   = help: the trait `std::marker::Sized` is not implemented for `X`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to 13 previous errors
 

From 53922491afe06cb0d611a0bd3be1b4c8a5a6ee16 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Wed, 22 Apr 2020 17:10:39 -0300
Subject: [PATCH 2/8] Add unsized_locals to INCOMPLETE_FEATURES list

---
 src/librustc_feature/active.rs                |  1 +
 src/test/ui/error-codes/E0161.rs              |  2 +-
 ...-same-trait-object-with-separate-params.rs |  1 +
 ...e-trait-object-with-separate-params.stderr | 29 ++++++++++++-------
 src/test/ui/moves/move-out-of-slice-2.rs      |  9 +++---
 src/test/ui/moves/move-out-of-slice-2.stderr  | 27 +++++++++++------
 src/test/ui/unsized-locals/autoderef.rs       |  1 +
 .../ui/unsized-locals/borrow-after-move.rs    |  1 +
 .../unsized-locals/borrow-after-move.stderr   | 21 ++++++++++----
 .../by-value-trait-object-safety-rpass.rs     |  2 +-
 ...y-value-trait-object-safety-withdefault.rs |  1 +
 .../by-value-trait-object-safety.rs           |  6 ++--
 .../by-value-trait-object-safety.stderr       | 17 ++++++++---
 src/test/ui/unsized-locals/double-move.rs     |  1 +
 src/test/ui/unsized-locals/double-move.stderr | 23 ++++++++++-----
 .../issue-30276-feature-flagged.rs            |  1 +
 .../issue-30276-feature-flagged.stderr        | 13 +++++++--
 .../issue-50940-with-feature.rs               |  1 +
 .../issue-50940-with-feature.stderr           | 13 +++++++--
 .../reference-unsized-locals.rs               |  1 +
 .../unsized-locals/simple-unsized-locals.rs   |  1 +
 .../ui/unsized-locals/unsized-exprs-rpass.rs  |  2 +-
 src/test/ui/unsized-locals/unsized-exprs.rs   |  1 +
 .../ui/unsized-locals/unsized-exprs.stderr    | 17 ++++++++---
 src/test/ui/unsized-locals/unsized-exprs2.rs  |  1 +
 .../ui/unsized-locals/unsized-exprs2.stderr   | 13 +++++++--
 src/test/ui/unsized-locals/unsized-index.rs   |  1 +
 .../ui/unsized-locals/unsized-parameters.rs   |  1 +
 28 files changed, 153 insertions(+), 55 deletions(-)

diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 120c717919601..b8061bfbf5bc0 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -599,4 +599,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::const_trait_bound_opt_out,
     sym::lazy_normalization_consts,
     sym::specialization,
+    sym::unsized_locals,
 ];
diff --git a/src/test/ui/error-codes/E0161.rs b/src/test/ui/error-codes/E0161.rs
index 58217ff74b8d6..e0f5776424e09 100644
--- a/src/test/ui/error-codes/E0161.rs
+++ b/src/test/ui/error-codes/E0161.rs
@@ -9,13 +9,13 @@
 //[zflagsul]compile-flags: -Z borrowck=migrate
 //[editionul]edition:2018
 
+#![allow(incomplete_features)]
 #![cfg_attr(nll, feature(nll))]
 #![cfg_attr(nllul, feature(nll))]
 #![cfg_attr(migrateul, feature(unsized_locals))]
 #![cfg_attr(zflagsul, feature(unsized_locals))]
 #![cfg_attr(nllul, feature(unsized_locals))]
 #![cfg_attr(editionul, feature(unsized_locals))]
-
 #![feature(box_syntax)]
 
 fn foo(x: Box<[i32]>) {
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
index abd2faa7dc659..4ea0a609af4c4 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -1,4 +1,5 @@
 #![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 // This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
 // it checks that the `ObjectCandidate` you get from method matching can't
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 1bc7f30d04d0d..5487aa826f667 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:1:77
+   |
+LL | #![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals, unsized_fn_params)]
+   |                                                                             ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:85:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:86:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
@@ -7,7 +16,7 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:102:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:103:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u64`
@@ -15,23 +24,23 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:120:15
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:121:15
    |
 LL |     let z = x.foo();
    |               ^^^ multiple `foo` found
    |
 note: candidate #1 is defined in an impl of the trait `internal::X` for the type `T`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:43:9
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:44:9
    |
 LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `T`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:71:9
    |
 LL |         fn foo(self) {}
    |         ^^^^^^^^^^^^
 note: candidate #3 is defined in the trait `FinalFoo`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:58:5
    |
 LL |     fn foo(&self) -> u8;
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +58,7 @@ LL |     let z = FinalFoo::foo(x);
    |             ^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:137:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:138:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u8`
@@ -57,7 +66,7 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:155:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:156:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
@@ -65,14 +74,14 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:172:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:173:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
    |                   |
    |                   expected due to this
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0034, E0308.
 For more information about an error, try `rustc --explain E0034`.
diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs
index 5c1a61eb375a4..d91be023ed794 100644
--- a/src/test/ui/moves/move-out-of-slice-2.rs
+++ b/src/test/ui/moves/move-out-of-slice-2.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_locals)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 struct A;
 #[derive(Clone, Copy)]
@@ -8,13 +9,13 @@ fn main() {
     let a: Box<[A]> = Box::new([A]);
     match *a {
         //~^ ERROR cannot move out of type `[A]`, a non-copy slice
-        [a @ ..] => {},
+        [a @ ..] => {}
         _ => {}
     }
     let b: Box<[A]> = Box::new([A, A, A]);
     match *b {
         //~^ ERROR cannot move out of type `[A]`, a non-copy slice
-        [_, _, b @ .., _] => {},
+        [_, _, b @ .., _] => {}
         _ => {}
     }
 
@@ -22,13 +23,13 @@ fn main() {
     let c: Box<[C]> = Box::new([C]);
     match *c {
         //~^ ERROR cannot move out of type `[C]`, a non-copy slice
-        [c @ ..] => {},
+        [c @ ..] => {}
         _ => {}
     }
     let d: Box<[C]> = Box::new([C, C, C]);
     match *d {
         //~^ ERROR cannot move out of type `[C]`, a non-copy slice
-        [_, _, d @ .., _] => {},
+        [_, _, d @ .., _] => {}
         _ => {}
     }
 }
diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr
index 058f34b24a3b6..9a863bf31a7fb 100644
--- a/src/test/ui/moves/move-out-of-slice-2.stderr
+++ b/src/test/ui/moves/move-out-of-slice-2.stderr
@@ -1,51 +1,60 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/move-out-of-slice-2.rs:1:12
+   |
+LL | #![feature(unsized_locals)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:9:11
+  --> $DIR/move-out-of-slice-2.rs:10:11
    |
 LL |     match *a {
    |           ^^ cannot move out of here
 LL |
-LL |         [a @ ..] => {},
+LL |         [a @ ..] => {}
    |          ------
    |          |
    |          data moved here
    |          move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:15:11
+  --> $DIR/move-out-of-slice-2.rs:16:11
    |
 LL |     match *b {
    |           ^^ cannot move out of here
 LL |
-LL |         [_, _, b @ .., _] => {},
+LL |         [_, _, b @ .., _] => {}
    |                ------
    |                |
    |                data moved here
    |                move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:23:11
+  --> $DIR/move-out-of-slice-2.rs:24:11
    |
 LL |     match *c {
    |           ^^ cannot move out of here
 LL |
-LL |         [c @ ..] => {},
+LL |         [c @ ..] => {}
    |          ------
    |          |
    |          data moved here
    |          move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:29:11
+  --> $DIR/move-out-of-slice-2.rs:30:11
    |
 LL |     match *d {
    |           ^^ cannot move out of here
 LL |
-LL |         [_, _, d @ .., _] => {},
+LL |         [_, _, d @ .., _] => {}
    |                ------
    |                |
    |                data moved here
    |                move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/unsized-locals/autoderef.rs b/src/test/ui/unsized-locals/autoderef.rs
index 63d9ce6d3c3e5..5dd5898c12e5c 100644
--- a/src/test/ui/unsized-locals/autoderef.rs
+++ b/src/test/ui/unsized-locals/autoderef.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs
index 4e02ea6a4f49f..bf305a318d842 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.rs
+++ b/src/test/ui/unsized-locals/borrow-after-move.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 906b543e42122..9478852a7fb16 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/borrow-after-move.rs:1:12
+   |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrow-after-move.rs:20:24
+  --> $DIR/borrow-after-move.rs:21:24
    |
 LL |         let y = *x;
    |                 -- value moved here
@@ -10,7 +19,7 @@ LL |         println!("{}", &x);
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `y`
-  --> $DIR/borrow-after-move.rs:22:24
+  --> $DIR/borrow-after-move.rs:23:24
    |
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
@@ -21,7 +30,7 @@ LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrow-after-move.rs:30:24
+  --> $DIR/borrow-after-move.rs:31:24
    |
 LL |         let y = *x;
    |                 -- value moved here
@@ -32,7 +41,7 @@ LL |         println!("{}", &x);
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `y`
-  --> $DIR/borrow-after-move.rs:32:24
+  --> $DIR/borrow-after-move.rs:33:24
    |
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
@@ -49,7 +58,7 @@ LL |     fn foo(self) -> String;
    |            ^^^^
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrow-after-move.rs:39:24
+  --> $DIR/borrow-after-move.rs:40:24
    |
 LL |         let x = "hello".to_owned().into_boxed_str();
    |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
@@ -58,6 +67,6 @@ LL |         x.foo();
 LL |         println!("{}", &x);
    |                        ^^ value borrowed here after move
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs
index b07d1a571b212..b9881defac39a 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals)]
 
 pub trait Foo {
@@ -14,7 +15,6 @@ impl Foo for A {
     }
 }
 
-
 fn main() {
     let x = *(Box::new(A) as Box<dyn Foo>);
     assert_eq!(x.foo(), format!("hello"));
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
index b05504fbe820d..957991f853b2d 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
index 8b24328bd3854..d298542541748 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
@@ -1,7 +1,10 @@
 #![feature(unsized_locals)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub trait Foo {
-    fn foo(self) -> String where Self: Sized;
+    fn foo(self) -> String
+    where
+        Self: Sized;
 }
 
 struct A;
@@ -12,7 +15,6 @@ impl Foo for A {
     }
 }
 
-
 fn main() {
     let x = *(Box::new(A) as Box<dyn Foo>);
     x.foo();
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
index 4cd2098eef256..59d91bc0cfd3d 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
@@ -1,11 +1,20 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/by-value-trait-object-safety.rs:1:12
+   |
+LL | #![feature(unsized_locals)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error: the `foo` method cannot be invoked on a trait object
-  --> $DIR/by-value-trait-object-safety.rs:18:7
+  --> $DIR/by-value-trait-object-safety.rs:20:7
    |
-LL |     fn foo(self) -> String where Self: Sized;
-   |                                        ----- this has a `Sized` requirement
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
 ...
 LL |     x.foo();
    |       ^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs
index 5c430a0c388e3..35d95232f346f 100644
--- a/src/test/ui/unsized-locals/double-move.rs
+++ b/src/test/ui/unsized-locals/double-move.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index 49b2031c6b9d9..08deda43efb57 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/double-move.rs:1:12
+   |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0382]: use of moved value: `y`
-  --> $DIR/double-move.rs:20:22
+  --> $DIR/double-move.rs:21:22
    |
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
@@ -9,7 +18,7 @@ LL |         drop_unsized(y);
    |                      ^ value used here after move
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/double-move.rs:26:22
+  --> $DIR/double-move.rs:27:22
    |
 LL |         let _y = *x;
    |                  -- value moved here
@@ -19,7 +28,7 @@ LL |         drop_unsized(x);
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `*x`
-  --> $DIR/double-move.rs:32:18
+  --> $DIR/double-move.rs:33:18
    |
 LL |         let x = "hello".to_owned().into_boxed_str();
    |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
@@ -29,7 +38,7 @@ LL |         let _y = *x;
    |                  ^^ value used here after move
 
 error[E0382]: use of moved value: `y`
-  --> $DIR/double-move.rs:39:9
+  --> $DIR/double-move.rs:40:9
    |
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
@@ -45,7 +54,7 @@ LL |     fn foo(self) -> String;
    |            ^^^^
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/double-move.rs:45:9
+  --> $DIR/double-move.rs:46:9
    |
 LL |         let _y = *x;
    |                  -- value moved here
@@ -55,7 +64,7 @@ LL |         x.foo();
    = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `*x`
-  --> $DIR/double-move.rs:51:18
+  --> $DIR/double-move.rs:52:18
    |
 LL |         let x = "hello".to_owned().into_boxed_str();
    |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait
@@ -64,6 +73,6 @@ LL |         x.foo();
 LL |         let _y = *x;
    |                  ^^ value used here after move
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
index 4193210b8bd3b..3b08225c880ae 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_locals)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 struct Test([i32]);
 
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
index 40646139a6d73..3a1ffd56aae1d 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-30276-feature-flagged.rs:1:12
+   |
+LL | #![feature(unsized_locals)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/issue-30276-feature-flagged.rs:6:29
+  --> $DIR/issue-30276-feature-flagged.rs:7:29
    |
 LL |     let _x: fn(_) -> Test = Test;
    |                             ^^^^ doesn't have a size known at compile-time
@@ -9,6 +18,6 @@ LL |     let _x: fn(_) -> Test = Test;
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
index 310dfc9b62326..c8b78c4ac556f 100644
--- a/src/test/ui/unsized-locals/issue-50940-with-feature.rs
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 fn main() {
     struct A<X: ?Sized>(X);
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
index 04a8de1b5dc5b..c48ff46649863 100644
--- a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-50940-with-feature.rs:1:12
+   |
+LL | #![feature(unsized_locals, unsized_fn_params)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/issue-50940-with-feature.rs:5:5
+  --> $DIR/issue-50940-with-feature.rs:6:5
    |
 LL |     A as fn(str) -> A<str>;
    |     ^ doesn't have a size known at compile-time
@@ -8,6 +17,6 @@ LL |     A as fn(str) -> A<str>;
    = note: required because it appears within the type `main::A<str>`
    = note: the return type of a function must have a statically known size
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/reference-unsized-locals.rs b/src/test/ui/unsized-locals/reference-unsized-locals.rs
index 1560d25d4b0de..4e887f32753f1 100644
--- a/src/test/ui/unsized-locals/reference-unsized-locals.rs
+++ b/src/test/ui/unsized-locals/reference-unsized-locals.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals)]
 
 fn main() {
diff --git a/src/test/ui/unsized-locals/simple-unsized-locals.rs b/src/test/ui/unsized-locals/simple-unsized-locals.rs
index 059559192456d..02b7c299aa40a 100644
--- a/src/test/ui/unsized-locals/simple-unsized-locals.rs
+++ b/src/test/ui/unsized-locals/simple-unsized-locals.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals)]
 
 fn main() {
diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
index fc564d16ddb68..8fcb6d93d391c 100644
--- a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![allow(unused_braces, unused_parens)]
+#![allow(incomplete_features, unused_braces, unused_parens)]
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
index be3140db86b72..348629c0ff367 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
index 0a9b43dac3344..53c08be7ddbbd 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unsized-exprs.rs:1:36
+   |
+LL | #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+   |                                    ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:22:26
+  --> $DIR/unsized-exprs.rs:23:26
    |
 LL |     udrop::<(i32, [u8])>((42, *foo()));
    |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +18,7 @@ LL |     udrop::<(i32, [u8])>((42, *foo()));
    = note: tuples must have a statically known size to be initialized
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:24:22
+  --> $DIR/unsized-exprs.rs:25:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -19,7 +28,7 @@ LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    = note: structs must have a statically known size to be initialized
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:26:22
+  --> $DIR/unsized-exprs.rs:27:22
    |
 LL |     udrop::<A<[u8]>>(A(*foo()));
    |                      ^ doesn't have a size known at compile-time
@@ -28,6 +37,6 @@ LL |     udrop::<A<[u8]>>(A(*foo()));
    = note: required because it appears within the type `A<[u8]>`
    = note: the return type of a function must have a statically known size
 
-error: aborting due to 3 previous errors
+error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
index 495316c276e8d..1d0f39881b700 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -1,4 +1,5 @@
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr
index 88269f237afb7..fac16b8e07ee2 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr
@@ -1,5 +1,14 @@
+warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unsized-exprs2.rs:1:36
+   |
+LL | #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
+   |                                    ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+
 error[E0508]: cannot move out of type `[u8]`, a non-copy slice
-  --> $DIR/unsized-exprs2.rs:22:5
+  --> $DIR/unsized-exprs2.rs:23:5
    |
 LL |     udrop::<[u8]>(foo()[..]);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,6 +16,6 @@ LL |     udrop::<[u8]>(foo()[..]);
    |     cannot move out of here
    |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/unsized-locals/unsized-index.rs b/src/test/ui/unsized-locals/unsized-index.rs
index 470e0e2f12ea5..c8b502b271d98 100644
--- a/src/test/ui/unsized-locals/unsized-index.rs
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -5,6 +5,7 @@
 // Tightening the bound now could be a breaking change. Although no crater
 // regression were observed (https://github.com/rust-lang/rust/pull/59527),
 // let's be conservative and just add a test for this.
+#![allow(incomplete_features)]
 #![feature(unsized_locals, unsized_fn_params)]
 
 use std::ops;
diff --git a/src/test/ui/unsized-locals/unsized-parameters.rs b/src/test/ui/unsized-locals/unsized-parameters.rs
index 6d87f07f43b18..15eeeb9303339 100644
--- a/src/test/ui/unsized-locals/unsized-parameters.rs
+++ b/src/test/ui/unsized-locals/unsized-parameters.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(incomplete_features)]
 #![feature(unsized_locals, unsized_fn_params)]
 
 pub fn f0(_f: dyn FnOnce()) {}

From 116357c214964bdf229a06eb894cab93c7f947df Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 8 May 2020 21:14:46 -0300
Subject: [PATCH 3/8] This flag is not really needed in the test

---
 src/test/ui/fn/dyn-fn-alignment.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/test/ui/fn/dyn-fn-alignment.rs b/src/test/ui/fn/dyn-fn-alignment.rs
index ecd7c1744a008..cedfd1cf2dcc9 100644
--- a/src/test/ui/fn/dyn-fn-alignment.rs
+++ b/src/test/ui/fn/dyn-fn-alignment.rs
@@ -1,6 +1,5 @@
 // run-pass
 
-#![feature(unsized_fn_params)]
 #![allow(dead_code)]
 #[repr(align(256))]
 struct A {

From 7cf3ac962751541f39dced23f9bce419b3238784 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Sat, 23 May 2020 09:35:22 -0300
Subject: [PATCH 4/8] Make tidy happy

---
 .../feature-gate-unsized_fn_params.rs         |  4 ++--
 ...-same-trait-object-with-separate-params.rs |  5 ++--
 ...e-trait-object-with-separate-params.stderr | 24 +++++++++----------
 src/test/ui/moves/move-out-of-slice-2.rs      |  2 +-
 .../ui/unsized-locals/borrow-after-move.rs    |  2 +-
 .../by-value-trait-object-safety.rs           |  2 +-
 src/test/ui/unsized-locals/double-move.rs     |  2 +-
 .../issue-30276-feature-flagged.rs            |  2 +-
 .../issue-50940-with-feature.rs               |  2 +-
 src/test/ui/unsized-locals/unsized-exprs.rs   |  2 +-
 src/test/ui/unsized-locals/unsized-exprs2.rs  |  2 +-
 11 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
index 45bde37a3ac5e..9b868ed7a9e93 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
@@ -15,12 +15,12 @@ impl Foo for A {
 }
 
 fn foo(x: dyn Foo) {
-    //~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time [E0277]
+    //~^ ERROR [E0277]
     x.foo()
 }
 
 fn main() {
     let x: Box<dyn Foo> = Box::new(A { v: 22 });
     foo(*x);
-    //~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time [E0277]
+    //~^ ERROR [E0277]
 }
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
index 4ea0a609af4c4..9e53ff0791728 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -1,5 +1,6 @@
-#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 // This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
 // it checks that the `ObjectCandidate` you get from method matching can't
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 5487aa826f667..c4a67818882ce 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -1,14 +1,14 @@
 warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:1:77
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:2:12
    |
-LL | #![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals, unsized_fn_params)]
-   |                                                                             ^^^^^^^^^^^^^^
+LL | #![feature(unsized_locals, unsized_fn_params)]
+   |            ^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:86:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
@@ -16,7 +16,7 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:103:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:104:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u64`
@@ -24,23 +24,23 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0034]: multiple applicable items in scope
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:121:15
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:122:15
    |
 LL |     let z = x.foo();
    |               ^^^ multiple `foo` found
    |
 note: candidate #1 is defined in an impl of the trait `internal::X` for the type `T`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:44:9
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:45:9
    |
 LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `T`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:71:9
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:72:9
    |
 LL |         fn foo(self) {}
    |         ^^^^^^^^^^^^
 note: candidate #3 is defined in the trait `FinalFoo`
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:58:5
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59:5
    |
 LL |     fn foo(&self) -> u8;
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -58,7 +58,7 @@ LL |     let z = FinalFoo::foo(x);
    |             ^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:138:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u8`
@@ -66,7 +66,7 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:156:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:157:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
@@ -74,7 +74,7 @@ LL |     let _seetype: () = z;
    |                   expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:173:24
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:174:24
    |
 LL |     let _seetype: () = z;
    |                   --   ^ expected `()`, found `u32`
diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs
index d91be023ed794..59c02d42bf17e 100644
--- a/src/test/ui/moves/move-out-of-slice-2.rs
+++ b/src/test/ui/moves/move-out-of-slice-2.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 struct A;
 #[derive(Clone, Copy)]
diff --git a/src/test/ui/unsized-locals/borrow-after-move.rs b/src/test/ui/unsized-locals/borrow-after-move.rs
index bf305a318d842..ad73b720fa39d 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.rs
+++ b/src/test/ui/unsized-locals/borrow-after-move.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
index d298542541748..d0ba6944a1e81 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 pub trait Foo {
     fn foo(self) -> String
diff --git a/src/test/ui/unsized-locals/double-move.rs b/src/test/ui/unsized-locals/double-move.rs
index 35d95232f346f..9e46ef9be487c 100644
--- a/src/test/ui/unsized-locals/double-move.rs
+++ b/src/test/ui/unsized-locals/double-move.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 pub trait Foo {
     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
index 3b08225c880ae..635d34f822914 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 struct Test([i32]);
 
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.rs b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
index c8b78c4ac556f..63b0e830be4ed 100644
--- a/src/test/ui/unsized-locals/issue-50940-with-feature.rs
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 fn main() {
     struct A<X: ?Sized>(X);
diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
index 348629c0ff367..17fcdf7ea27ea 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
index 1d0f39881b700..8b0232e5b0f90 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -1,5 +1,5 @@
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 struct A<X: ?Sized>(X);
 

From 6f6db0798091a2f5abe8a1361aaef923d69fb867 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Sat, 23 May 2020 16:26:20 -0300
Subject: [PATCH 5/8] Using unsized_local feature is not needed in these tests

---
 src/test/ui/unsized-locals/unsized-exprs.rs     |  3 +--
 src/test/ui/unsized-locals/unsized-exprs.stderr | 17 ++++-------------
 src/test/ui/unsized-locals/unsized-exprs2.rs    |  3 +--
 .../ui/unsized-locals/unsized-exprs2.stderr     | 13 ++-----------
 src/test/ui/unsized-locals/unsized-index.rs     |  3 +--
 5 files changed, 9 insertions(+), 30 deletions(-)

diff --git a/src/test/ui/unsized-locals/unsized-exprs.rs b/src/test/ui/unsized-locals/unsized-exprs.rs
index 17fcdf7ea27ea..1729b9ffa8670 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs.rs
@@ -1,5 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete
+#![feature(unsized_tuple_coercion, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
index 53c08be7ddbbd..0a9b43dac3344 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsized-exprs.rs:1:36
-   |
-LL | #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-   |                                    ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
-
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:23:26
+  --> $DIR/unsized-exprs.rs:22:26
    |
 LL |     udrop::<(i32, [u8])>((42, *foo()));
    |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -18,7 +9,7 @@ LL |     udrop::<(i32, [u8])>((42, *foo()));
    = note: tuples must have a statically known size to be initialized
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:25:22
+  --> $DIR/unsized-exprs.rs:24:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -28,7 +19,7 @@ LL |     udrop::<A<[u8]>>(A { 0: *foo() });
    = note: structs must have a statically known size to be initialized
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-exprs.rs:27:22
+  --> $DIR/unsized-exprs.rs:26:22
    |
 LL |     udrop::<A<[u8]>>(A(*foo()));
    |                      ^ doesn't have a size known at compile-time
@@ -37,6 +28,6 @@ LL |     udrop::<A<[u8]>>(A(*foo()));
    = note: required because it appears within the type `A<[u8]>`
    = note: the return type of a function must have a statically known size
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.rs b/src/test/ui/unsized-locals/unsized-exprs2.rs
index 8b0232e5b0f90..127d8717e5806 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs2.rs
@@ -1,5 +1,4 @@
-#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-//~^ WARN the feature `unsized_locals` is incomplete
+#![feature(unsized_tuple_coercion, unsized_fn_params)]
 
 struct A<X: ?Sized>(X);
 
diff --git a/src/test/ui/unsized-locals/unsized-exprs2.stderr b/src/test/ui/unsized-locals/unsized-exprs2.stderr
index fac16b8e07ee2..88269f237afb7 100644
--- a/src/test/ui/unsized-locals/unsized-exprs2.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs2.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsized-exprs2.rs:1:36
-   |
-LL | #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
-   |                                    ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
-
 error[E0508]: cannot move out of type `[u8]`, a non-copy slice
-  --> $DIR/unsized-exprs2.rs:23:5
+  --> $DIR/unsized-exprs2.rs:22:5
    |
 LL |     udrop::<[u8]>(foo()[..]);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,6 +7,6 @@ LL |     udrop::<[u8]>(foo()[..]);
    |     cannot move out of here
    |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/unsized-locals/unsized-index.rs b/src/test/ui/unsized-locals/unsized-index.rs
index c8b502b271d98..2c31ade7a3873 100644
--- a/src/test/ui/unsized-locals/unsized-index.rs
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -5,8 +5,7 @@
 // Tightening the bound now could be a breaking change. Although no crater
 // regression were observed (https://github.com/rust-lang/rust/pull/59527),
 // let's be conservative and just add a test for this.
-#![allow(incomplete_features)]
-#![feature(unsized_locals, unsized_fn_params)]
+#![feature(unsized_fn_params)]
 
 use std::ops;
 

From 659db8ec79fb1d0eef93a6f662f25831bd95a1ca Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Sun, 24 May 2020 17:22:41 -0300
Subject: [PATCH 6/8] Fix unstable-book doc tests

---
 .../unstable-book/src/language-features/unsized-locals.md  | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md
index 343084b7db501..d716b1d51dcf7 100644
--- a/src/doc/unstable-book/src/language-features/unsized-locals.md
+++ b/src/doc/unstable-book/src/language-features/unsized-locals.md
@@ -11,7 +11,8 @@ This implements [RFC1909]. When turned on, you can have unsized arguments and lo
 [RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md
 
 ```rust
-#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 use std::any::Any;
 
@@ -85,7 +86,7 @@ fn main() {
 With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
 
 ```rust
-#![feature(unsized_locals)]
+#![feature(unsized_fn_params)]
 
 trait Foo {
     fn foo(self) {}
@@ -102,7 +103,7 @@ fn main() {
 And `Foo` will also be object-safe.
 
 ```rust
-#![feature(unsized_locals)]
+#![feature(unsized_fn_params)]
 
 trait Foo {
     fn foo(self) {}

From 39716f1a3080a92554138d3a1ef3ebd20076e7c7 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <huyuumi.dev@gmail.com>
Date: Fri, 31 Jul 2020 14:14:04 +0900
Subject: [PATCH 7/8] Fix rebase-fallout and bless tests

---
 src/librustc_feature/active.rs                            | 1 +
 .../traits/error_reporting/suggestions.rs                 | 2 +-
 src/librustc_typeck/check/mod.rs                          | 2 +-
 .../ui/async-await/issue-72590-type-error-sized.stderr    | 7 ++-----
 .../feature-gates/feature-gate-unsized_fn_params.stderr   | 2 --
 .../ui/feature-gates/feature-gate-unsized_locals.stderr   | 1 -
 src/test/ui/issues/issue-27078.stderr                     | 6 ------
 src/test/ui/issues/issue-38954.stderr                     | 6 ++++--
 src/test/ui/issues/issue-41229-ref-str.stderr             | 6 ++++--
 src/test/ui/issues/issue-42312.stderr                     | 8 ++++----
 src/test/ui/issues/issue-5883.stderr                      | 1 -
 src/test/ui/resolve/issue-5035-2.stderr                   | 1 -
 src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr  | 1 -
 src/test/ui/unsized-locals/borrow-after-move.stderr       | 2 +-
 src/test/ui/unsized-locals/double-move.stderr             | 2 +-
 .../ui/unsized-locals/issue-30276-feature-flagged.stderr  | 1 -
 src/test/ui/unsized6.stderr                               | 4 ----
 17 files changed, 19 insertions(+), 34 deletions(-)

diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index b8061bfbf5bc0..94a2275790758 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -578,6 +578,7 @@ declare_features! (
 
     /// Alloc calling `transmute` in const fn
     (active, const_fn_transmute, "1.46.0", Some(53605), None),
+
     /// Allows unsized fn parameters.
     (active, unsized_fn_params, "1.45.0", Some(48055), None),
 
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index bf06f37b9e9b8..a14e5f10938fb 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1835,7 +1835,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if tcx.sess.opts.unstable_features.is_nightly_build()
                     && !self.tcx.features().unsized_fn_params
                 {
-                    err.help("unsized locals are gated as an unstable feature");
+                    err.help("unsized fn params are gated as an unstable feature");
                 }
             }
             ObligationCauseCode::SizedReturnType => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4f32003889d65..9e6615afd3aaa 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1246,7 +1246,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
 
             if self.within_fn_param {
                 if !self.fcx.tcx.features().unsized_fn_params {
-                    self.fcx.require_type_is_sized(var_ty, p.span, traits::SizedArgumentType);
+                    self.fcx.require_type_is_sized(var_ty, p.span, traits::SizedArgumentType(None));
                 }
             } else {
                 if !self.fcx.tcx.features().unsized_locals {
diff --git a/src/test/ui/async-await/issue-72590-type-error-sized.stderr b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
index 762afa6450a95..5f10549710539 100644
--- a/src/test/ui/async-await/issue-72590-type-error-sized.stderr
+++ b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
@@ -18,11 +18,8 @@ LL |     async fn frob(self) {}
    |
    = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `str`
    = note: required because it appears within the type `Foo`
-   = help: unsized locals are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     async fn frob(&self) {}
-   |                   ^
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index f6dd6790251d7..0f31f30a1812a 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -5,7 +5,6 @@ LL | fn foo(x: dyn Foo) {
    |        ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
@@ -16,7 +15,6 @@ LL |     foo(*x);
    |     ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
index 285a0771f6d4f..a6d3982e4ebb2 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
@@ -5,7 +5,6 @@ LL | fn f(f: dyn FnOnce()) {}
    |      ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr
index 378b614cf18ae..ef2e098b38908 100644
--- a/src/test/ui/issues/issue-27078.stderr
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -4,18 +4,12 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
 LL |     fn foo(self) -> &'static i32 {
    |            ^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `std::marker::Sized` is not implemented for `Self`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 help: consider further restricting `Self`
    |
 LL |     fn foo(self) -> &'static i32 where Self: std::marker::Sized {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     fn foo(&self) -> &'static i32 {
-   |            ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-38954.stderr b/src/test/ui/issues/issue-38954.stderr
index bdae4990569f1..30c2821c6f7e4 100644
--- a/src/test/ui/issues/issue-38954.stderr
+++ b/src/test/ui/issues/issue-38954.stderr
@@ -5,9 +5,11 @@ LL | fn _test(ref _p: str) {}
    |          ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn _test(ref _p: &str) {}
+   |                  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-41229-ref-str.stderr b/src/test/ui/issues/issue-41229-ref-str.stderr
index e8967071a0663..b3e14f0d1d91a 100644
--- a/src/test/ui/issues/issue-41229-ref-str.stderr
+++ b/src/test/ui/issues/issue-41229-ref-str.stderr
@@ -5,9 +5,11 @@ LL | pub fn example(ref s: str) {}
    |                ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `str`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | pub fn example(ref s: &str) {}
+   |                       ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr
index 4a92e63550c02..8eea138cbd175 100644
--- a/src/test/ui/issues/issue-42312.stderr
+++ b/src/test/ui/issues/issue-42312.stderr
@@ -5,8 +5,6 @@ LL |     fn baz(_: Self::Target) where Self: Deref {}
    |            ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `<Self as std::ops::Deref>::Target`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 help: consider further restricting the associated type
    |
@@ -24,9 +22,11 @@ LL | pub fn f(_: dyn ToString) {}
    |          ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn std::string::ToString + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | pub fn f(_: &dyn ToString) {}
+   |             ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index 636428d557afa..0e6ee11348315 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -5,7 +5,6 @@ LL | fn new_struct(r: dyn A + 'static)
    |               ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index 82fec52a573e4..24cd32212a626 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -5,7 +5,6 @@ LL | fn foo(_x: K) {}
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
index 14a9e4343f9d9..e672044dd8bc4 100644
--- a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
+++ b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
@@ -13,7 +13,6 @@ LL | fn foo(_x: Foo + Send) {
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + std::marker::Send + 'static)`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 9478852a7fb16..d5d89bcfc94cf 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -52,7 +52,7 @@ LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
 note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
-  --> $DIR/borrow-after-move.rs:4:12
+  --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
    |            ^^^^
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index 08deda43efb57..6d9913a849c06 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -48,7 +48,7 @@ LL |         y.foo();
    |         ^ value used here after move
    |
 note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
-  --> $DIR/double-move.rs:4:12
+  --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
    |            ^^^^
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
index 3a1ffd56aae1d..3f3f7d108e03b 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -14,7 +14,6 @@ LL |     let _x: fn(_) -> Test = Test;
    |                             ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `[i32]`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr
index d86221b3273f8..8fb054efecbe6 100644
--- a/src/test/ui/unsized6.stderr
+++ b/src/test/ui/unsized6.stderr
@@ -132,8 +132,6 @@ LL | fn g1<X: ?Sized>(x: X) {}
    |       |
    |       this type parameter needs to be `std::marker::Sized`
    |
-   = help: the trait `std::marker::Sized` is not implemented for `X`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
@@ -145,8 +143,6 @@ LL | fn g2<X: ?Sized + T>(x: X) {}
    |       |
    |       this type parameter needs to be `std::marker::Sized`
    |
-   = help: the trait `std::marker::Sized` is not implemented for `X`
-   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 

From 93b5a7ee8b9ec22617c4943aeea922ca6109d7ac Mon Sep 17 00:00:00 2001
From: Yuki Okushi <huyuumi.dev@gmail.com>
Date: Fri, 31 Jul 2020 15:51:30 +0900
Subject: [PATCH 8/8] Do not depend on `unsized_locals` except for bootstrap

---
 library/core/src/lib.rs                          |  2 +-
 src/librustc_feature/active.rs                   |  2 +-
 src/librustc_mir/borrow_check/type_check/mod.rs  | 14 ++++++++------
 src/test/ui/unsized-locals/unsized-parameters.rs |  2 +-
 4 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 155925a68bac1..c05389eeab807 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -122,8 +122,8 @@
 #![feature(stmt_expr_attributes)]
 #![feature(transparent_unions)]
 #![feature(unboxed_closures)]
-#![feature(unsized_locals)]
 #![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
+#![cfg_attr(bootstrap, feature(unsized_locals))]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(variant_count)]
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 94a2275790758..432383423b0aa 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -580,7 +580,7 @@ declare_features! (
     (active, const_fn_transmute, "1.46.0", Some(53605), None),
 
     /// Allows unsized fn parameters.
-    (active, unsized_fn_params, "1.45.0", Some(48055), None),
+    (active, unsized_fn_params, "1.47.0", Some(48055), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index bda5107dd4e1e..df58e26a894e5 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1472,7 +1472,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
 
                 self.check_rvalue(body, rv, location);
-                if !self.tcx().features().unsized_locals {
+                if !(self.tcx().features().unsized_locals
+                    || self.tcx().features().unsized_fn_params)
+                {
                     let trait_ref = ty::TraitRef {
                         def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)),
                         substs: tcx.mk_substs_trait(place_ty, &[]),
@@ -1732,9 +1734,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
 
-                // When `#![feature(unsized_locals)]` is not enabled,
+                // When `unsized_fn_params` or `unsized_locals` is not enabled,
                 // this check is done at `check_local`.
-                if self.tcx().features().unsized_fn_params {
+                if self.tcx().features().unsized_locals || self.tcx().features().unsized_fn_params {
                     let span = term.source_info.span;
                     self.ensure_place_sized(dest_ty, span);
                 }
@@ -1895,9 +1897,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             LocalKind::Var | LocalKind::Temp => {}
         }
 
-        // When `#![feature(unsized_locals)]` is enabled, only function calls
+        // When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
         // and nullary ops are checked in `check_call_dest`.
-        if !self.tcx().features().unsized_locals {
+        if !(self.tcx().features().unsized_locals || self.tcx().features().unsized_fn_params) {
             let span = local_decl.source_info.span;
             let ty = local_decl.ty;
             self.ensure_place_sized(ty, span);
@@ -2043,7 +2045,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
             Rvalue::NullaryOp(_, ty) => {
                 // Even with unsized locals cannot box an unsized value.
-                if self.tcx().features().unsized_locals {
+                if self.tcx().features().unsized_locals || self.tcx().features().unsized_fn_params {
                     let span = body.source_info(location).span;
                     self.ensure_place_sized(ty, span);
                 }
diff --git a/src/test/ui/unsized-locals/unsized-parameters.rs b/src/test/ui/unsized-locals/unsized-parameters.rs
index 15eeeb9303339..2d31b9e4046a3 100644
--- a/src/test/ui/unsized-locals/unsized-parameters.rs
+++ b/src/test/ui/unsized-locals/unsized-parameters.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![allow(incomplete_features)]
-#![feature(unsized_locals, unsized_fn_params)]
+#![feature(unsized_fn_params)]
 
 pub fn f0(_f: dyn FnOnce()) {}
 pub fn f1(_s: str) {}