about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_typeck/src/check/check.rs2
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
-rw-r--r--compiler/rustc_typeck/src/check/gather_locals.rs29
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-locals.md7
-rw-r--r--src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs9
-rw-r--r--src/test/ui/async-await/issue-72590-type-error-sized.stderr2
-rw-r--r--src/test/ui/closures/issue-41366.stderr2
-rw-r--r--src/test/ui/error-codes/E0161.rs2
-rw-r--r--src/test/ui/error-codes/E0277.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs26
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr26
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_locals.stderr6
-rw-r--r--src/test/ui/fn/dyn-fn-alignment.rs1
-rw-r--r--src/test/ui/issues/issue-17651.stderr2
-rw-r--r--src/test/ui/issues/issue-27078.stderr2
-rw-r--r--src/test/ui/issues/issue-30355.stderr2
-rw-r--r--src/test/ui/issues/issue-38954.stderr2
-rw-r--r--src/test/ui/issues/issue-41229-ref-str.stderr2
-rw-r--r--src/test/ui/issues/issue-42312.stderr4
-rw-r--r--src/test/ui/issues/issue-5883.stderr6
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs4
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr29
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.rs9
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.stderr27
-rw-r--r--src/test/ui/resolve/issue-5035-2.stderr6
-rw-r--r--src/test/ui/suggestions/path-by-value.stderr6
-rw-r--r--src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr6
-rw-r--r--src/test/ui/unboxed-closures/issue-53448.stderr2
-rw-r--r--src/test/ui/unsized-locals/autoderef.rs4
-rw-r--r--src/test/ui/unsized-locals/auxiliary/ufuncs.rs2
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.rs3
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr23
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety-rpass.rs2
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs4
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety.rs6
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety.stderr17
-rw-r--r--src/test/ui/unsized-locals/double-move.rs3
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr25
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.rs1
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr19
-rw-r--r--src/test/ui/unsized-locals/issue-30276.stderr2
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.rs3
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.stderr13
-rw-r--r--src/test/ui/unsized-locals/issue-50940.stderr2
-rw-r--r--src/test/ui/unsized-locals/reference-unsized-locals.rs1
-rw-r--r--src/test/ui/unsized-locals/simple-unsized-locals.rs1
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs-rpass.rs12
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs.rs2
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs2.rs2
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs3.stderr2
-rw-r--r--src/test/ui/unsized-locals/unsized-index.rs24
-rw-r--r--src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs15
-rw-r--r--src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr33
-rw-r--r--src/test/ui/unsized-locals/unsized-parameters.rs5
-rw-r--r--src/test/ui/unsized6.stderr12
62 files changed, 354 insertions, 147 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index f5c530c192a..ad926a810e6 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -607,6 +607,9 @@ declare_features! (
     /// Allow anonymous constants from an inline `const` block
     (active, inline_const, "1.49.0", Some(76001), None),
 
+    /// Allows unsized fn parameters.
+    (active, unsized_fn_params, "1.49.0", Some(48055), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -629,6 +632,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::specialization,
     sym::inline_const,
     sym::repr128,
+    sym::unsized_locals,
 ];
 
 /// Some features are not allowed to be used together at the same time, if
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 4fc1c570e46..409399094e8 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -974,6 +974,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         checker
     }
 
+    fn unsized_feature_enabled(&self) -> bool {
+        let features = self.tcx().features();
+        features.unsized_locals || features.unsized_fn_params
+    }
+
     /// Equate the inferred type and the annotated type for user type annotations
     fn check_user_type_annotations(&mut self) {
         debug!(
@@ -1456,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
 
                 self.check_rvalue(body, rv, location);
-                if !self.tcx().features().unsized_locals {
+                if !self.unsized_feature_enabled() {
                     let trait_ref = ty::TraitRef {
                         def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                         substs: tcx.mk_substs_trait(place_ty, &[]),
@@ -1717,9 +1722,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
 
-                // When `#![feature(unsized_locals)]` is not enabled,
+                // When `unsized_fn_params` and `unsized_locals` are both not enabled,
                 // this check is done at `check_local`.
-                if self.tcx().features().unsized_locals {
+                if self.unsized_feature_enabled() {
                     let span = term.source_info.span;
                     self.ensure_place_sized(dest_ty, span);
                 }
@@ -1880,9 +1885,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.unsized_feature_enabled() {
             let span = local_decl.source_info.span;
             let ty = local_decl.ty;
             self.ensure_place_sized(ty, span);
@@ -2024,7 +2029,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.unsized_feature_enabled() {
                     let span = body.source_info(location).span;
                     self.ensure_place_sized(ty, span);
                 }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index aac93f313f4..cf075abc94b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ef0f09ae818..b8f2b57a046 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1163,6 +1163,7 @@ symbols! {
         unsafe_cell,
         unsafe_no_drop_flag,
         unsize,
+        unsized_fn_params,
         unsized_locals,
         unsized_tuple_coercion,
         unstable,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fa837e04db3..c0881befe24 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1845,9 +1845,9 @@ 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");
+                    err.help("unsized fn params are gated as an unstable feature");
                 }
             }
             ObligationCauseCode::SizedReturnType => {
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 8f2537404c5..6dd8a143ec0 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -131,7 +131,7 @@ pub(super) 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/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index b0417fca253..5eba7be3b02 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -476,7 +476,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/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs
index 1d505cfa698..af552389de0 100644
--- a/compiler/rustc_typeck/src/check/gather_locals.rs
+++ b/compiler/rustc_typeck/src/check/gather_locals.rs
@@ -6,15 +6,20 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
+use std::mem;
 
 pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     parent_id: hir::HirId,
+    // parameters are special cases of patterns, but we want to handle them as
+    // *distinct* cases. so track when we are hitting a pattern *within* an fn
+    // parameter.
+    outermost_fn_param_pat: bool,
 }
 
 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
     pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
-        Self { fcx, parent_id }
+        Self { fcx, parent_id, outermost_fn_param_pat: false }
     }
 
     fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
@@ -88,13 +93,29 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
         intravisit::walk_local(self, local);
     }
 
+    fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+        let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, true);
+        intravisit::walk_param(self, param);
+        self.outermost_fn_param_pat = old_outermost_fn_param_pat;
+    }
+
     // 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.outermost_fn_param_pat {
+                if !self.fcx.tcx.features().unsized_fn_params {
+                    self.fcx.require_type_is_sized(
+                        var_ty,
+                        p.span,
+                        traits::SizedArgumentType(Some(p.span)),
+                    );
+                }
+            } else {
+                if !self.fcx.tcx.features().unsized_locals {
+                    self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
+                }
             }
 
             debug!(
@@ -104,7 +125,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                 var_ty
             );
         }
+        let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, false);
         intravisit::walk_pat(self, p);
+        self.outermost_fn_param_pat = old_outermost_fn_param_pat;
     }
 
     // Don't descend into the bodies of nested closures.
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 0fe15958076..405667e0b2a 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -130,7 +130,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, maybe_uninit_uninit_array)]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 6cb240d1730..b89ec93834f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -132,7 +132,8 @@
 #![feature(transparent_unions)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
-#![feature(unsized_locals)]
+#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
+#![cfg_attr(bootstrap, feature(unsized_locals))]
 #![cfg_attr(bootstrap, feature(untagged_unions))]
 #![feature(unwind_attributes)]
 #![feature(variant_count)]
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 343084b7db5..d716b1d51dc 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) {}
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 2f275f88d96..a7b9052617f 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/async-await/issue-72590-type-error-sized.stderr b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
index 785fe21dd31..0f90a4c336c 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,7 +18,7 @@ LL |     async fn frob(self) {}
    |
    = help: within `Foo`, the trait `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: 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 |     async fn frob(&self) {}
diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr
index 200d411b511..72ef5b3b962 100644
--- a/src/test/ui/closures/issue-41366.stderr
+++ b/src/test/ui/closures/issue-41366.stderr
@@ -16,7 +16,7 @@ LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
    |        ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `<u32 as T<'_>>::V`
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 help: consider further restricting the associated type
    |
 LL | fn main() where <u32 as T<'_>>::V: Sized {
diff --git a/src/test/ui/error-codes/E0161.rs b/src/test/ui/error-codes/E0161.rs
index 58217ff74b8..e0f5776424e 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/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
index c2e15007cf9..647e0c7d76f 100644
--- a/src/test/ui/error-codes/E0277.stderr
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -6,11 +6,11 @@ LL | fn f(p: Path) { }
    |
    = help: within `Path`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `Path`
-   = help: unsized locals are gated as an unstable feature
+   = 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 f(p: &Path) { }
-   |         ^
+LL | fn f(&p: Path) { }
+   |      ^
 
 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 00000000000..9b868ed7a9e
--- /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 [E0277]
+    x.foo()
+}
+
+fn main() {
+    let x: Box<dyn Foo> = Box::new(A { v: 22 });
+    foo(*x);
+    //~^ ERROR [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 00000000000..71acbb174ac
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -0,0 +1,26 @@
+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 `Sized` is not implemented for `(dyn Foo + 'static)`
+   = 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 foo(&x: dyn Foo) {
+   |        ^
+
+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 `Sized` is not implemented for `(dyn Foo + 'static)`
+   = 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 29595c92376..52254220872 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,11 @@ LL | fn f(f: dyn FnOnce()) {}
    |      ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
-   = help: unsized locals are gated as an unstable feature
+   = 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 f(f: &dyn FnOnce()) {}
-   |         ^
+LL | fn f(&f: dyn FnOnce()) {}
+   |      ^
 
 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 125f44bbf00..cedfd1cf2dc 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_locals)]
 #![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 987f4e97f36..69817f10c9f 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 `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 006389f7537..021a08696de 100644
--- a/src/test/ui/issues/issue-27078.stderr
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -4,7 +4,7 @@ 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: unsized fn params are gated as an unstable feature
 help: consider further restricting `Self`
    |
 LL |     fn foo(self) -> &'static i32 where Self: Sized {
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
index db7a5a7f6dc..79f5db650d9 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 `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 bc40fd07c5a..f76063fc558 100644
--- a/src/test/ui/issues/issue-38954.stderr
+++ b/src/test/ui/issues/issue-38954.stderr
@@ -5,7 +5,7 @@ LL | fn _test(ref _p: str) {}
    |          ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = help: unsized locals are gated as an unstable feature
+   = 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) {}
diff --git a/src/test/ui/issues/issue-41229-ref-str.stderr b/src/test/ui/issues/issue-41229-ref-str.stderr
index c5c848e63e6..8b37e5e9774 100644
--- a/src/test/ui/issues/issue-41229-ref-str.stderr
+++ b/src/test/ui/issues/issue-41229-ref-str.stderr
@@ -5,7 +5,7 @@ LL | pub fn example(ref s: str) {}
    |                ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = help: unsized locals are gated as an unstable feature
+   = 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) {}
diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr
index b55a724c0db..f69c2a9925d 100644
--- a/src/test/ui/issues/issue-42312.stderr
+++ b/src/test/ui/issues/issue-42312.stderr
@@ -5,7 +5,7 @@ LL |     fn baz(_: Self::Target) where Self: Deref {}
    |            ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `<Self as Deref>::Target`
-   = help: unsized locals are gated as an unstable feature
+   = 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 Deref>::Target: Sized {}
@@ -22,7 +22,7 @@ LL | pub fn f(_: dyn ToString) {}
    |          ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn ToString + 'static)`
-   = help: unsized locals are gated as an unstable feature
+   = 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) {}
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index 8d639304ab6..5798733e04b 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -5,11 +5,11 @@ LL | fn new_struct(r: dyn A + 'static)
    |               ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn A + 'static)`
-   = help: unsized locals are gated as an unstable feature
+   = 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 new_struct(r: &dyn A + 'static)
-   |                  ^
+LL | fn new_struct(&r: dyn A + 'static)
+   |               ^
 
 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 5ceba646784..9e53ff07917 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,6 @@
-#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals)]
+#![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 08be7ee155e..0a516c89a8b 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:2: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[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:87: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:104: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:122:15
    |
 LL |     let z = x.foo();
    |               ^^^ multiple `foo` found
    |
 note: candidate #1 is defined in an impl of the trait `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:45:9
    |
 LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `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: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:57:5
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59: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:139: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:157: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:174: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 5c1a61eb375..59c02d42bf1 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
 
 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 058f34b24a3..9a863bf31a7 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/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index 5078ffbec73..b2084a7a426 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -5,11 +5,11 @@ LL | fn foo(_x: K) {}
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn I + 'static)`
-   = help: unsized locals are gated as an unstable feature
+   = 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 foo(_x: &K) {}
-   |            ^
+LL | fn foo(&_x: K) {}
+   |        ^
 
 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 ea0c63ac257..19fc3406ccf 100644
--- a/src/test/ui/suggestions/path-by-value.stderr
+++ b/src/test/ui/suggestions/path-by-value.stderr
@@ -6,11 +6,11 @@ LL | fn f(p: Path) { }
    |
    = help: within `Path`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `Path`
-   = help: unsized locals are gated as an unstable feature
+   = 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 f(p: &Path) { }
-   |         ^
+LL | fn f(&p: Path) { }
+   |      ^
 
 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 b403fb4184d..48eedc0b0ea 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,11 @@ LL | fn foo(_x: Foo + Send) {
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
-   = help: unsized locals are gated as an unstable feature
+   = 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 foo(_x: &Foo + Send) {
-   |            ^
+LL | fn foo(&_x: Foo + Send) {
+   |        ^
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/unboxed-closures/issue-53448.stderr b/src/test/ui/unboxed-closures/issue-53448.stderr
index bece9eedc7f..29273a5babe 100644
--- a/src/test/ui/unboxed-closures/issue-53448.stderr
+++ b/src/test/ui/unboxed-closures/issue-53448.stderr
@@ -5,7 +5,7 @@ LL |     let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T|
    |                                                      ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `<() as Lt<'_>>::T`
-   = help: unsized locals are gated as an unstable feature
+   = help: unsized fn params are gated as an unstable feature
 help: consider further restricting the associated type
    |
 LL | fn main() where <() as Lt<'_>>::T: Sized {
diff --git a/src/test/ui/unsized-locals/autoderef.rs b/src/test/ui/unsized-locals/autoderef.rs
index 7f2d2f9c7ef..5dd5898c12e 100644
--- a/src/test/ui/unsized-locals/autoderef.rs
+++ b/src/test/ui/unsized-locals/autoderef.rs
@@ -1,6 +1,7 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String;
@@ -24,7 +25,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 065563d45a4..5954abf3a1f 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 3299fdf3a9c..ad73b720fa3 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)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 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 b49c32f5f80..5934276cc1d 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
@@ -43,13 +52,13 @@ 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;
    |            ^^^^
 
 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 `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 b07d1a571b2..b9881defac3 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 8b39a99da58..957991f853b 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,7 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
 
 pub trait Foo {
     fn foo(self) -> String {
@@ -12,7 +13,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/by-value-trait-object-safety.rs b/src/test/ui/unsized-locals/by-value-trait-object-safety.rs
index 8b24328bd38..d0ba6944a1e 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
 
 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 4cd2098eef2..59d91bc0cfd 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 c3a50341bc9..9e46ef9be48 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)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 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 36fb32ae09c..b897dbbc9a3 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 `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
@@ -39,13 +48,13 @@ 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;
    |            ^^^^
 
 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 `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 4193210b8bd..635d34f8229 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
 
 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 46e381611a1..0f0ff579377 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -1,13 +1,22 @@
+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
    |
-   = help: within `Test`, the trait `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 `Sized` is not implemented for `[i32]`
+   = 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-30276.stderr b/src/test/ui/unsized-locals/issue-30276.stderr
index e9258a61c32..8cccbd792da 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 `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 3e5d39ab311..63b0e830be4 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)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
 
 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 dc20b92b423..1b1a584a01f 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 `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/issue-50940.stderr b/src/test/ui/unsized-locals/issue-50940.stderr
index c602fae883c..8f09b460e00 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 `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/reference-unsized-locals.rs b/src/test/ui/unsized-locals/reference-unsized-locals.rs
index 1560d25d4b0..4e887f32753 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 05955919245..02b7c299aa4 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 24c2758a0a2..8fcb6d93d39 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)]
+#![allow(incomplete_features, unused_braces, unused_parens)]
+#![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 8ca88edcb6a..1729b9ffa86 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_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 534439aa6c4..127d8717e58 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_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 426262e82b7..57d9978225a 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 `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 19ad97a853e..e8782e89481 100644
--- a/src/test/ui/unsized-locals/unsized-index.rs
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -1,23 +1,27 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// run-pass
 
-// `std::ops::Index` has an `: ?Sized` bound on the `Idx` type param. This is
-// an accidental left-over from the times when it `Index` was by-reference.
-// 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_fn_params)]
 
 use std::ops;
+use std::ops::Index;
 
 pub struct A;
 
 impl ops::Index<str> for A {
     type Output = ();
-    fn index(&self, _: str) -> &Self::Output { panic!() }
+    fn index(&self, _: str) -> &Self::Output {
+        &()
+    }
 }
 
 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() {}
+fn main() {
+    let a = A {};
+    let s = String::new().into_boxed_str();
+    assert_eq!(&(), a.index(*s));
+}
diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs
new file mode 100644
index 00000000000..15263954ced
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs
@@ -0,0 +1,15 @@
+#![feature(box_patterns)]
+#![feature(unsized_fn_params)]
+
+#[allow(dead_code)]
+fn f1(box box _b: Box<Box<[u8]>>) {}
+//~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277]
+
+fn f2((_x, _y): (i32, [i32])) {}
+//~^ ERROR: the size for values of type `[i32]` cannot be known at compilation time [E0277]
+
+fn main() {
+    let foo: Box<[u8]> = Box::new(*b"foo");
+    let _foo: [u8] = *foo;
+    //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277]
+}
diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr
new file mode 100644
index 00000000000..da77026673d
--- /dev/null
+++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-locals-using-unsized-fn-params.rs:5:15
+   |
+LL | fn f1(box box _b: Box<Box<[u8]>>) {}
+   |               ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/unsized-locals-using-unsized-fn-params.rs:8:12
+   |
+LL | fn f2((_x, _y): (i32, [i32])) {}
+   |            ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/unsized-locals-using-unsized-fn-params.rs:13:9
+   |
+LL |     let _foo: [u8] = *foo;
+   |         ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+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-parameters.rs b/src/test/ui/unsized-locals/unsized-parameters.rs
index 3624154d5c4..a1b772a7eb6 100644
--- a/src/test/ui/unsized-locals/unsized-parameters.rs
+++ b/src/test/ui/unsized-locals/unsized-parameters.rs
@@ -1,10 +1,11 @@
 // run-pass
 
-#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+#![feature(unsized_fn_params)]
 
 pub fn f0(_f: dyn FnOnce()) {}
 pub fn f1(_s: str) {}
-pub fn f2((_x, _y): (i32, [i32])) {}
+pub fn f2(_x: i32, _y: [i32]) {}
 
 fn main() {
     let foo = "foo".to_string().into_boxed_str();
diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr
index e85b73355e9..71dac236fa3 100644
--- a/src/test/ui/unsized6.stderr
+++ b/src/test/ui/unsized6.stderr
@@ -132,11 +132,11 @@ LL | fn g1<X: ?Sized>(x: X) {}
    |       |
    |       this type parameter needs to be `Sized`
    |
-   = help: unsized locals are gated as an unstable feature
+   = 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 g1<X: ?Sized>(x: &X) {}
-   |                     ^
+LL | fn g1<X: ?Sized>(&x: X) {}
+   |                  ^
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized6.rs:40:22
@@ -146,11 +146,11 @@ LL | fn g2<X: ?Sized + T>(x: X) {}
    |       |
    |       this type parameter needs to be `Sized`
    |
-   = help: unsized locals are gated as an unstable feature
+   = 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 g2<X: ?Sized + T>(x: &X) {}
-   |                         ^
+LL | fn g2<X: ?Sized + T>(&x: X) {}
+   |                      ^
 
 error: aborting due to 13 previous errors