about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs14
-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.rs4
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
-rw-r--r--compiler/rustc_typeck/src/check/gather_locals.rs32
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs2
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/core/src/lib.rs1
-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/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.rs2
-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.rs2
-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/unsized-locals/autoderef.rs3
-rw-r--r--src/test/ui/unsized-locals/auxiliary/ufuncs.rs2
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.rs2
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs3
-rw-r--r--src/test/ui/unsized-locals/double-move.rs2
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr6
-rw-r--r--src/test/ui/unsized-locals/issue-30276.stderr2
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.rs2
-rw-r--r--src/test/ui/unsized-locals/issue-50940.stderr2
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs-rpass.rs10
-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.rs10
-rw-r--r--src/test/ui/unsized-locals/unsized-parameters.rs2
-rw-r--r--src/test/ui/unsized6.stderr12
46 files changed, 165 insertions, 86 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index f5c530c192a..8a5a1066b06 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
     // -------------------------------------------------------------------------
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..1bd4440c9c8 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1456,7 +1456,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(LangItem::Sized, Some(self.last_span)),
                         substs: tcx.mk_substs_trait(place_ty, &[]),
@@ -1717,9 +1719,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_locals {
+                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);
                 }
@@ -1880,9 +1882,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);
@@ -2024,7 +2026,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/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 080afdcd2c0..beee162eaed 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1161,6 +1161,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..40366003d43 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -105,7 +105,7 @@ pub(super) 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.local_def_id_to_hir_id(outer_def_id);
-    GatherLocalsVisitor::new(&fcx, outer_hir_id).visit_body(body);
+    GatherLocalsVisitor::new(&fcx, outer_hir_id, 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).
@@ -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..d5e45c3b89f 100644
--- a/compiler/rustc_typeck/src/check/gather_locals.rs
+++ b/compiler/rustc_typeck/src/check/gather_locals.rs
@@ -10,11 +10,19 @@ use rustc_trait_selection::traits;
 pub(super) 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> {
-    pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
-        Self { fcx, parent_id }
+    pub(super) fn new(
+        fcx: &'a FnCtxt<'a, 'tcx>,
+        parent_id: hir::HirId,
+        within_fn_param: bool,
+    ) -> Self {
+        Self { fcx, parent_id, within_fn_param }
     }
 
     fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
@@ -88,13 +96,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>) {
+        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(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!(
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 169ad0df3a5..4ec114b1f2c 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -553,7 +553,7 @@ fn typeck_with_fallback<'tcx>(
             };
 
             // Gather locals in statics (because of block expressions).
-            GatherLocalsVisitor::new(&fcx, id).visit_body(body);
+            GatherLocalsVisitor::new(&fcx, id, false).visit_body(body);
 
             fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
 
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..6de766ffd56 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -133,6 +133,7 @@
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
 #![feature(unsized_locals)]
+#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
 #![cfg_attr(bootstrap, feature(untagged_unions))]
 #![feature(unwind_attributes)]
 #![feature(variant_count)]
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/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..45bde37a3ac
--- /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 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..ecd7c1744a0 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 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..abd2faa7dc6 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 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/unsized-locals/autoderef.rs b/src/test/ui/unsized-locals/autoderef.rs
index 7f2d2f9c7ef..63d9ce6d3c3 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 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..4e02ea6a4f4 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 8b39a99da58..b05504fbe82 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 c3a50341bc9..5c430a0c388 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 46e381611a1..be033c0b176 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,9 @@ 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 `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
 
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..310dfc9b623 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 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/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
index 24c2758a0a2..fc564d16ddb 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 8ca88edcb6a..be3140db86b 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 534439aa6c4..495316c276e 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 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..470e0e2f12e 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 3624154d5c4..6d87f07f43b 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 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