Skip to content

Commit 346aeef

Browse files
authored
Rollup merge of #78152 - spastorino:separate-unsized-locals, r=oli-obk
Separate unsized locals Closes #71694 Takes over again #72029 and #74971 cc @RalfJung @oli-obk @pnkfelix @eddyb as they've participated in previous reviews of this PR.
2 parents 07e968b + cc9ab1c commit 346aeef

File tree

62 files changed

+354
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+354
-147
lines changed

compiler/rustc_feature/src/active.rs

+4
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,9 @@ declare_features! (
607607
/// Allow anonymous constants from an inline `const` block
608608
(active, inline_const, "1.49.0", Some(76001), None),
609609

610+
/// Allows unsized fn parameters.
611+
(active, unsized_fn_params, "1.49.0", Some(48055), None),
612+
610613
// -------------------------------------------------------------------------
611614
// feature-group-end: actual feature gates
612615
// -------------------------------------------------------------------------
@@ -629,6 +632,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
629632
sym::specialization,
630633
sym::inline_const,
631634
sym::repr128,
635+
sym::unsized_locals,
632636
];
633637

634638
/// Some features are not allowed to be used together at the same time, if

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
974974
checker
975975
}
976976

977+
fn unsized_feature_enabled(&self) -> bool {
978+
let features = self.tcx().features();
979+
features.unsized_locals || features.unsized_fn_params
980+
}
981+
977982
/// Equate the inferred type and the annotated type for user type annotations
978983
fn check_user_type_annotations(&mut self) {
979984
debug!(
@@ -1456,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14561461
}
14571462

14581463
self.check_rvalue(body, rv, location);
1459-
if !self.tcx().features().unsized_locals {
1464+
if !self.unsized_feature_enabled() {
14601465
let trait_ref = ty::TraitRef {
14611466
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
14621467
substs: tcx.mk_substs_trait(place_ty, &[]),
@@ -1717,9 +1722,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
17171722
);
17181723
}
17191724

1720-
// When `#![feature(unsized_locals)]` is not enabled,
1725+
// When `unsized_fn_params` and `unsized_locals` are both not enabled,
17211726
// this check is done at `check_local`.
1722-
if self.tcx().features().unsized_locals {
1727+
if self.unsized_feature_enabled() {
17231728
let span = term.source_info.span;
17241729
self.ensure_place_sized(dest_ty, span);
17251730
}
@@ -1880,9 +1885,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18801885
LocalKind::Var | LocalKind::Temp => {}
18811886
}
18821887

1883-
// When `#![feature(unsized_locals)]` is enabled, only function calls
1888+
// When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
18841889
// and nullary ops are checked in `check_call_dest`.
1885-
if !self.tcx().features().unsized_locals {
1890+
if !self.unsized_feature_enabled() {
18861891
let span = local_decl.source_info.span;
18871892
let ty = local_decl.ty;
18881893
self.ensure_place_sized(ty, span);
@@ -2024,7 +2029,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20242029

20252030
Rvalue::NullaryOp(_, ty) => {
20262031
// Even with unsized locals cannot box an unsized value.
2027-
if self.tcx().features().unsized_locals {
2032+
if self.unsized_feature_enabled() {
20282033
let span = body.source_info(location).span;
20292034
self.ensure_place_sized(ty, span);
20302035
}

compiler/rustc_mir_build/src/build/expr/as_operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
165165

166166
let tcx = this.hir.tcx();
167167

168-
if tcx.features().unsized_locals {
168+
if tcx.features().unsized_fn_params {
169169
let ty = expr.ty;
170170
let span = expr.span;
171171
let param_env = this.hir.param_env;

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ symbols! {
11631163
unsafe_cell,
11641164
unsafe_no_drop_flag,
11651165
unsize,
1166+
unsized_fn_params,
11661167
unsized_locals,
11671168
unsized_tuple_coercion,
11681169
unstable,

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1845,9 +1845,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
18451845
err.note("all function arguments must have a statically known size");
18461846
}
18471847
if tcx.sess.opts.unstable_features.is_nightly_build()
1848-
&& !self.tcx.features().unsized_locals
1848+
&& !self.tcx.features().unsized_fn_params
18491849
{
1850-
err.help("unsized locals are gated as an unstable feature");
1850+
err.help("unsized fn params are gated as an unstable feature");
18511851
}
18521852
}
18531853
ObligationCauseCode::SizedReturnType => {

compiler/rustc_typeck/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub(super) fn check_fn<'a, 'tcx>(
131131
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
132132
// for simple cases like `fn foo(x: Trait)`,
133133
// where we would error once on the parameter as a whole, and once on the binding `x`.
134-
if param.pat.simple_ident().is_none() && !tcx.features().unsized_locals {
134+
if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
135135
fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
136136
}
137137

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
476476

477477
if let ty::FnDef(..) = ty.kind() {
478478
let fn_sig = ty.fn_sig(tcx);
479-
if !tcx.features().unsized_locals {
479+
if !tcx.features().unsized_fn_params {
480480
// We want to remove some Sized bounds from std functions,
481481
// but don't want to expose the removal to stable Rust.
482482
// i.e., we don't want to allow

compiler/rustc_typeck/src/check/gather_locals.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
66
use rustc_middle::ty::Ty;
77
use rustc_span::Span;
88
use rustc_trait_selection::traits;
9+
use std::mem;
910

1011
pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
1112
fcx: &'a FnCtxt<'a, 'tcx>,
1213
parent_id: hir::HirId,
14+
// parameters are special cases of patterns, but we want to handle them as
15+
// *distinct* cases. so track when we are hitting a pattern *within* an fn
16+
// parameter.
17+
outermost_fn_param_pat: bool,
1318
}
1419

1520
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
1621
pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
17-
Self { fcx, parent_id }
22+
Self { fcx, parent_id, outermost_fn_param_pat: false }
1823
}
1924

2025
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> {
8893
intravisit::walk_local(self, local);
8994
}
9095

96+
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
97+
let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, true);
98+
intravisit::walk_param(self, param);
99+
self.outermost_fn_param_pat = old_outermost_fn_param_pat;
100+
}
101+
91102
// Add pattern bindings.
92103
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
93104
if let PatKind::Binding(_, _, ident, _) = p.kind {
94105
let var_ty = self.assign(p.span, p.hir_id, None);
95106

96-
if !self.fcx.tcx.features().unsized_locals {
97-
self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
107+
if self.outermost_fn_param_pat {
108+
if !self.fcx.tcx.features().unsized_fn_params {
109+
self.fcx.require_type_is_sized(
110+
var_ty,
111+
p.span,
112+
traits::SizedArgumentType(Some(p.span)),
113+
);
114+
}
115+
} else {
116+
if !self.fcx.tcx.features().unsized_locals {
117+
self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id));
118+
}
98119
}
99120

100121
debug!(
@@ -104,7 +125,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
104125
var_ty
105126
);
106127
}
128+
let old_outermost_fn_param_pat = mem::replace(&mut self.outermost_fn_param_pat, false);
107129
intravisit::walk_pat(self, p);
130+
self.outermost_fn_param_pat = old_outermost_fn_param_pat;
108131
}
109132

110133
// Don't descend into the bodies of nested closures.

library/alloc/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@
130130
#![feature(unicode_internals)]
131131
#![feature(unsafe_block_in_unsafe_fn)]
132132
#![feature(unsize)]
133-
#![feature(unsized_locals)]
133+
#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
134+
#![cfg_attr(bootstrap, feature(unsized_locals))]
134135
#![feature(allocator_internals)]
135136
#![feature(slice_partition_dedup)]
136137
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]

library/core/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@
132132
#![feature(transparent_unions)]
133133
#![feature(try_blocks)]
134134
#![feature(unboxed_closures)]
135-
#![feature(unsized_locals)]
135+
#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
136+
#![cfg_attr(bootstrap, feature(unsized_locals))]
136137
#![cfg_attr(bootstrap, feature(untagged_unions))]
137138
#![feature(unwind_attributes)]
138139
#![feature(variant_count)]

src/doc/unstable-book/src/language-features/unsized-locals.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ This implements [RFC1909]. When turned on, you can have unsized arguments and lo
1111
[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md
1212

1313
```rust
14-
#![feature(unsized_locals)]
14+
#![allow(incomplete_features)]
15+
#![feature(unsized_locals, unsized_fn_params)]
1516

1617
use std::any::Any;
1718

@@ -85,7 +86,7 @@ fn main() {
8586
With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
8687

8788
```rust
88-
#![feature(unsized_locals)]
89+
#![feature(unsized_fn_params)]
8990

9091
trait Foo {
9192
fn foo(self) {}
@@ -102,7 +103,7 @@ fn main() {
102103
And `Foo` will also be object-safe.
103104

104105
```rust
105-
#![feature(unsized_locals)]
106+
#![feature(unsized_fn_params)]
106107

107108
trait Foo {
108109
fn foo(self) {}

src/test/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#![feature(unsized_locals)]
1+
#![allow(incomplete_features)]
2+
#![feature(unsized_locals, unsized_fn_params)]
23

34
use std::fmt;
45

@@ -45,11 +46,7 @@ fn main() {
4546

4647
{
4748
let x: fmt::Display = *gen_foo();
48-
let x = if true {
49-
x
50-
} else {
51-
*gen_foo()
52-
};
49+
let x = if true { x } else { *gen_foo() };
5350
foo(x);
5451
}
5552
}

src/test/ui/async-await/issue-72590-type-error-sized.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LL | async fn frob(self) {}
1818
|
1919
= help: within `Foo`, the trait `Sized` is not implemented for `str`
2020
= note: required because it appears within the type `Foo`
21-
= help: unsized locals are gated as an unstable feature
21+
= help: unsized fn params are gated as an unstable feature
2222
help: function arguments must have a statically known size, borrowed types always have a known size
2323
|
2424
LL | async fn frob(&self) {}

src/test/ui/closures/issue-41366.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LL | (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
1616
| ^ doesn't have a size known at compile-time
1717
|
1818
= help: the trait `Sized` is not implemented for `<u32 as T<'_>>::V`
19-
= help: unsized locals are gated as an unstable feature
19+
= help: unsized fn params are gated as an unstable feature
2020
help: consider further restricting the associated type
2121
|
2222
LL | fn main() where <u32 as T<'_>>::V: Sized {

src/test/ui/error-codes/E0161.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
//[zflagsul]compile-flags: -Z borrowck=migrate
1010
//[editionul]edition:2018
1111

12+
#![allow(incomplete_features)]
1213
#![cfg_attr(nll, feature(nll))]
1314
#![cfg_attr(nllul, feature(nll))]
1415
#![cfg_attr(migrateul, feature(unsized_locals))]
1516
#![cfg_attr(zflagsul, feature(unsized_locals))]
1617
#![cfg_attr(nllul, feature(unsized_locals))]
1718
#![cfg_attr(editionul, feature(unsized_locals))]
18-
1919
#![feature(box_syntax)]
2020

2121
fn foo(x: Box<[i32]>) {

src/test/ui/error-codes/E0277.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ LL | fn f(p: Path) { }
66
|
77
= help: within `Path`, the trait `Sized` is not implemented for `[u8]`
88
= note: required because it appears within the type `Path`
9-
= help: unsized locals are gated as an unstable feature
9+
= help: unsized fn params are gated as an unstable feature
1010
help: function arguments must have a statically known size, borrowed types always have a known size
1111
|
12-
LL | fn f(p: &Path) { }
13-
| ^
12+
LL | fn f(&p: Path) { }
13+
| ^
1414

1515
error[E0277]: the trait bound `i32: Foo` is not satisfied
1616
--> $DIR/E0277.rs:17:15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[repr(align(256))]
2+
#[allow(dead_code)]
3+
struct A {
4+
v: u8,
5+
}
6+
7+
trait Foo {
8+
fn foo(&self);
9+
}
10+
11+
impl Foo for A {
12+
fn foo(&self) {
13+
assert_eq!(self as *const A as usize % 256, 0);
14+
}
15+
}
16+
17+
fn foo(x: dyn Foo) {
18+
//~^ ERROR [E0277]
19+
x.foo()
20+
}
21+
22+
fn main() {
23+
let x: Box<dyn Foo> = Box::new(A { v: 22 });
24+
foo(*x);
25+
//~^ ERROR [E0277]
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
2+
--> $DIR/feature-gate-unsized_fn_params.rs:17:8
3+
|
4+
LL | fn foo(x: dyn Foo) {
5+
| ^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
8+
= help: unsized fn params are gated as an unstable feature
9+
help: function arguments must have a statically known size, borrowed types always have a known size
10+
|
11+
LL | fn foo(&x: dyn Foo) {
12+
| ^
13+
14+
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
15+
--> $DIR/feature-gate-unsized_fn_params.rs:24:5
16+
|
17+
LL | foo(*x);
18+
| ^^^ doesn't have a size known at compile-time
19+
|
20+
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
21+
= note: all function arguments must have a statically known size
22+
= help: unsized fn params are gated as an unstable feature
23+
24+
error: aborting due to 2 previous errors
25+
26+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/feature-gates/feature-gate-unsized_locals.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ LL | fn f(f: dyn FnOnce()) {}
55
| ^ doesn't have a size known at compile-time
66
|
77
= help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
8-
= help: unsized locals are gated as an unstable feature
8+
= help: unsized fn params are gated as an unstable feature
99
help: function arguments must have a statically known size, borrowed types always have a known size
1010
|
11-
LL | fn f(f: &dyn FnOnce()) {}
12-
| ^
11+
LL | fn f(&f: dyn FnOnce()) {}
12+
| ^
1313

1414
error: aborting due to previous error
1515

src/test/ui/fn/dyn-fn-alignment.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// run-pass
22

3-
#![feature(unsized_locals)]
43
#![allow(dead_code)]
54
#[repr(align(256))]
65
struct A {

src/test/ui/issues/issue-17651.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | (|| Box::new(*(&[0][..])))();
1515
|
1616
= help: the trait `Sized` is not implemented for `[{integer}]`
1717
= note: all function arguments must have a statically known size
18-
= help: unsized locals are gated as an unstable feature
18+
= help: unsized fn params are gated as an unstable feature
1919

2020
error: aborting due to 2 previous errors
2121

src/test/ui/issues/issue-27078.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
44
LL | fn foo(self) -> &'static i32 {
55
| ^^^^ doesn't have a size known at compile-time
66
|
7-
= help: unsized locals are gated as an unstable feature
7+
= help: unsized fn params are gated as an unstable feature
88
help: consider further restricting `Self`
99
|
1010
LL | fn foo(self) -> &'static i32 where Self: Sized {

0 commit comments

Comments
 (0)