Skip to content

Commit

Permalink
Rollup merge of rust-lang#78152 - spastorino:separate-unsized-locals,…
Browse files Browse the repository at this point in the history
… r=oli-obk

Separate unsized locals

Closes rust-lang#71694

Takes over again rust-lang#72029 and rust-lang#74971

cc @RalfJung @oli-obk @pnkfelix @eddyb as they've participated in previous reviews of this PR.
  • Loading branch information
Dylan-DPC committed Oct 28, 2020
2 parents 07e968b + cc9ab1c commit 346aeef
Show file tree
Hide file tree
Showing 62 changed files with 354 additions and 147 deletions.
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 @@ -1163,6 +1163,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

0 comments on commit 346aeef

Please sign in to comment.