Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate unsized locals #78152

Merged
merged 22 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
708fc3b
Add unsized_fn_params feature
spastorino Oct 16, 2020
953d7a6
Add unsized_locals to INCOMPLETE_FEATURES list
spastorino Oct 16, 2020
072e230
This flag is not really needed in the test
spastorino Oct 16, 2020
e049ba0
Make tidy happy
spastorino May 23, 2020
d57d3f3
Using unsized_local feature is not needed in these tests
spastorino May 23, 2020
1b7d0b2
Fix unstable-book doc tests
spastorino May 24, 2020
ba59aa2
Do not depend on except for bootstrap
spastorino Oct 17, 2020
2040b79
unsized_locals feature is not needed in this test
spastorino Oct 17, 2020
70b8c79
Bless issue-53448 test
spastorino Oct 20, 2020
f0a71f7
Better test unsized_fn_params
spastorino Oct 20, 2020
a3470b1
Test that unsized locals fail when turning unsized_fn_params feature …
spastorino Oct 20, 2020
58018d4
Properly restore within_fn_param value to the previous state
spastorino Oct 20, 2020
ca41681
Do not use unsized_fn_params in patterns
spastorino Oct 20, 2020
bdd1b85
Rename within_fn_param to outermost_fn_param_pat
spastorino Oct 20, 2020
497ee0e
param -> parameter, pat -> pattern
spastorino Oct 20, 2020
8b8b639
Add comment explaining why in these tests unsized locals are not acce…
spastorino Oct 21, 2020
f0fe0a6
or -> and
spastorino Oct 21, 2020
89eac50
Hide outermost_fn_param_pat, it's an internal detail
spastorino Oct 21, 2020
4760338
Bless tests again
spastorino Oct 21, 2020
9584b00
is -> are both
spastorino Oct 21, 2020
00fd703
Use unsized_feature_enabled helper function
spastorino Oct 21, 2020
cc9ab1c
Merge unsized locals pat tests
spastorino Oct 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
// -------------------------------------------------------------------------
Expand All @@ -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
Expand Down
17 changes: 11 additions & 6 deletions compiler/rustc_mir/src/borrow_check/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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, &[]),
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/build/expr/as_operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,7 @@ symbols! {
unsafe_cell,
unsafe_no_drop_flag,
unsize,
unsized_fn_params,
unsized_locals,
unsized_tuple_coercion,
unstable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 26 additions & 3 deletions compiler/rustc_typeck/src/check/gather_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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!(
Expand All @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
7 changes: 4 additions & 3 deletions src/doc/unstable-book/src/language-features/unsized-locals.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) {}
Expand All @@ -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) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![feature(unsized_locals)]
#![allow(incomplete_features)]
#![feature(unsized_locals, unsized_fn_params)]

use std::fmt;

Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/closures/issue-41366.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0161.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]>) {
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/error-codes/E0277.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
Original file line number Diff line number Diff line change
@@ -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]
}
26 changes: 26 additions & 0 deletions src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
Original file line number Diff line number Diff line change
@@ -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`.
6 changes: 3 additions & 3 deletions src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/fn/dyn-fn-alignment.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// run-pass

#![feature(unsized_locals)]
#![allow(dead_code)]
#[repr(align(256))]
struct A {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17651.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-27078.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading