Auto merge of #116081 - compiler-errors:closure-captures-sized, r=cjgillot
Check that closure/generator's interior/capture types are sized check that closure upvars and generator interiors are sized. this check is only necessary when `unsized_fn_params` or `unsized_locals` is enabled, so only check if those are active. Fixes #93622 Fixes #61335 Fixes #68543
This commit is contained in:
commit
3050938abd
17 changed files with 296 additions and 4 deletions
|
@ -18,7 +18,7 @@ use rustc_infer::traits::{Obligation, TraitEngineExt as _};
|
||||||
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::stability::EvalResult;
|
use rustc_middle::middle::stability::EvalResult;
|
||||||
use rustc_middle::traits::DefiningAnchor;
|
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||||
|
@ -1626,6 +1626,25 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
|
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
|
||||||
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
|
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tcx.features().unsized_locals || tcx.features().unsized_fn_params)
|
||||||
|
&& let Some(generator) = tcx.mir_generator_witnesses(def_id)
|
||||||
|
{
|
||||||
|
for field_ty in generator.field_tys.iter() {
|
||||||
|
fulfillment_cx.register_bound(
|
||||||
|
&infcx,
|
||||||
|
param_env,
|
||||||
|
field_ty.ty,
|
||||||
|
tcx.require_lang_item(hir::LangItem::Sized, Some(field_ty.source_info.span)),
|
||||||
|
ObligationCause::new(
|
||||||
|
field_ty.source_info.span,
|
||||||
|
def_id,
|
||||||
|
ObligationCauseCode::SizedGeneratorInterior(def_id),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
||||||
debug!(?errors);
|
debug!(?errors);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
|
|
|
@ -518,8 +518,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.select_obligations_where_possible(|_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
|
|
||||||
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
||||||
for (_, body_id, interior, kind) in generators.drain(..) {
|
for (generator_def_id, body_id, interior, kind) in generators.drain(..) {
|
||||||
crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
|
crate::generator_interior::resolve_interior(
|
||||||
|
self,
|
||||||
|
def_id,
|
||||||
|
generator_def_id,
|
||||||
|
body_id,
|
||||||
|
interior,
|
||||||
|
kind,
|
||||||
|
);
|
||||||
self.select_obligations_where_possible(|_| {});
|
self.select_obligations_where_possible(|_| {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,13 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::{pluralize, DelayDm};
|
use rustc_errors::{pluralize, DelayDm};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::hir_id::HirIdSet;
|
use rustc_hir::hir_id::HirIdSet;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
|
use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
|
||||||
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
||||||
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
use rustc_middle::ty::fold::FnMutDelegate;
|
use rustc_middle::ty::fold::FnMutDelegate;
|
||||||
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
@ -188,6 +189,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||||
pub fn resolve_interior<'a, 'tcx>(
|
pub fn resolve_interior<'a, 'tcx>(
|
||||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
generator_def_id: LocalDefId,
|
||||||
body_id: hir::BodyId,
|
body_id: hir::BodyId,
|
||||||
interior: Ty<'tcx>,
|
interior: Ty<'tcx>,
|
||||||
kind: hir::GeneratorKind,
|
kind: hir::GeneratorKind,
|
||||||
|
@ -214,6 +216,16 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||||
// The types are already kept in insertion order.
|
// The types are already kept in insertion order.
|
||||||
let types = visitor.types;
|
let types = visitor.types;
|
||||||
|
|
||||||
|
if fcx.tcx.features().unsized_locals || fcx.tcx.features().unsized_fn_params {
|
||||||
|
for interior_ty in &types {
|
||||||
|
fcx.require_type_is_sized(
|
||||||
|
interior_ty.ty,
|
||||||
|
interior_ty.span,
|
||||||
|
ObligationCauseCode::SizedGeneratorInterior(generator_def_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The types in the generator interior contain lifetimes local to the generator itself,
|
// The types in the generator interior contain lifetimes local to the generator itself,
|
||||||
// which should not be exposed outside of the generator. Therefore, we replace these
|
// which should not be exposed outside of the generator. Therefore, we replace these
|
||||||
// lifetimes with existentially-bound lifetimes, which reflect the exact value of the
|
// lifetimes with existentially-bound lifetimes, which reflect the exact value of the
|
||||||
|
|
|
@ -41,6 +41,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_infer::infer::UpvarRegion;
|
use rustc_infer::infer::UpvarRegion;
|
||||||
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
|
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
|
||||||
use rustc_middle::mir::FakeReadCause;
|
use rustc_middle::mir::FakeReadCause;
|
||||||
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
|
self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
|
||||||
};
|
};
|
||||||
|
@ -295,6 +296,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
||||||
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
|
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
|
||||||
|
|
||||||
|
if self.tcx.features().unsized_locals || self.tcx.features().unsized_fn_params {
|
||||||
|
for capture in
|
||||||
|
self.typeck_results.borrow().closure_min_captures_flattened(closure_def_id)
|
||||||
|
{
|
||||||
|
if let UpvarCapture::ByValue = capture.info.capture_kind {
|
||||||
|
self.require_type_is_sized(
|
||||||
|
capture.place.ty(),
|
||||||
|
capture.get_path_span(self.tcx),
|
||||||
|
ObligationCauseCode::SizedClosureCapture(closure_def_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build a tuple (U0..Un) of the final upvar types U0..Un
|
// Build a tuple (U0..Un) of the final upvar types U0..Un
|
||||||
// and unify the upvar tuple type in the closure with it:
|
// and unify the upvar tuple type in the closure with it:
|
||||||
let final_tupled_upvars_type = Ty::new_tup(self.tcx, &final_upvar_tys);
|
let final_tupled_upvars_type = Ty::new_tup(self.tcx, &final_upvar_tys);
|
||||||
|
|
|
@ -299,6 +299,10 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
SizedYieldType,
|
SizedYieldType,
|
||||||
/// Inline asm operand type must be `Sized`.
|
/// Inline asm operand type must be `Sized`.
|
||||||
InlineAsmSized,
|
InlineAsmSized,
|
||||||
|
/// Captured closure type must be `Sized`.
|
||||||
|
SizedClosureCapture(LocalDefId),
|
||||||
|
/// Types live across generator yields must be `Sized`.
|
||||||
|
SizedGeneratorInterior(LocalDefId),
|
||||||
/// `[expr; N]` requires `type_of(expr): Copy`.
|
/// `[expr; N]` requires `type_of(expr): Copy`.
|
||||||
RepeatElementCopy {
|
RepeatElementCopy {
|
||||||
/// If element is a `const fn` we display a help message suggesting to move the
|
/// If element is a `const fn` we display a help message suggesting to move the
|
||||||
|
|
|
@ -3007,6 +3007,24 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
ObligationCauseCode::InlineAsmSized => {
|
ObligationCauseCode::InlineAsmSized => {
|
||||||
err.note("all inline asm arguments must have a statically known size");
|
err.note("all inline asm arguments must have a statically known size");
|
||||||
}
|
}
|
||||||
|
ObligationCauseCode::SizedClosureCapture(closure_def_id) => {
|
||||||
|
err.note("all values captured by value by a closure must have a statically known size");
|
||||||
|
let hir::ExprKind::Closure(closure) = self.tcx.hir().get_by_def_id(closure_def_id).expect_expr().kind else {
|
||||||
|
bug!("expected closure in SizedClosureCapture obligation");
|
||||||
|
};
|
||||||
|
if let hir::CaptureBy::Value = closure.capture_clause
|
||||||
|
&& let Some(span) = closure.fn_arg_span
|
||||||
|
{
|
||||||
|
err.span_label(span, "this closure captures all values by move");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObligationCauseCode::SizedGeneratorInterior(generator_def_id) => {
|
||||||
|
let what = match self.tcx.generator_kind(generator_def_id) {
|
||||||
|
None | Some(hir::GeneratorKind::Gen) => "yield",
|
||||||
|
Some(hir::GeneratorKind::Async(..)) => "await",
|
||||||
|
};
|
||||||
|
err.note(format!("all values live across `{what}` must have a statically known size"));
|
||||||
|
}
|
||||||
ObligationCauseCode::ConstPatternStructural => {
|
ObligationCauseCode::ConstPatternStructural => {
|
||||||
err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
|
err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/awaiting-unsized-param.rs:5:31
|
||||||
|
|
|
||||||
|
LL | #![feature(unsized_fn_params, unsized_locals)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `(dyn Future<Output = T> + Unpin + 'static)` cannot be known at compilation time
|
||||||
|
--> $DIR/awaiting-unsized-param.rs:10:17
|
||||||
|
|
|
||||||
|
LL | async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
|
||||||
|
| ^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = T> + Unpin + 'static)`
|
||||||
|
= note: all values captured by value by a closure must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,21 @@
|
||||||
|
warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/awaiting-unsized-param.rs:5:31
|
||||||
|
|
|
||||||
|
LL | #![feature(unsized_fn_params, unsized_locals)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `(dyn Future<Output = T> + Unpin + 'static)` cannot be known at compilation time
|
||||||
|
--> $DIR/awaiting-unsized-param.rs:10:17
|
||||||
|
|
|
||||||
|
LL | async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
|
||||||
|
| ^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = T> + Unpin + 'static)`
|
||||||
|
= note: all values captured by value by a closure must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
15
tests/ui/async-await/awaiting-unsized-param.rs
Normal file
15
tests/ui/async-await/awaiting-unsized-param.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// edition: 2021
|
||||||
|
// revisions: no_drop_tracking drop_tracking_mir
|
||||||
|
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
|
||||||
|
|
||||||
|
#![feature(unsized_fn_params, unsized_locals)]
|
||||||
|
//~^ WARN the feature `unsized_locals` is incomplete
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
async fn bug<T>(mut f: dyn Future<Output = T> + Unpin) -> T {
|
||||||
|
//~^ ERROR the size for values of type `(dyn Future<Output = T> + Unpin + 'static)` cannot be known at compilation time
|
||||||
|
(&mut f).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,21 @@
|
||||||
|
warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/unsized-across-await.rs:5:12
|
||||||
|
|
|
||||||
|
LL | #![feature(unsized_locals)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `dyn std::fmt::Display` cannot be known at compilation time
|
||||||
|
--> $DIR/unsized-across-await.rs:11:9
|
||||||
|
|
|
||||||
|
LL | let _x = *x;
|
||||||
|
| ^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `dyn std::fmt::Display`
|
||||||
|
= note: all values live across `await` must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,21 @@
|
||||||
|
warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/unsized-across-await.rs:5:12
|
||||||
|
|
|
||||||
|
LL | #![feature(unsized_locals)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `dyn std::fmt::Display` cannot be known at compilation time
|
||||||
|
--> $DIR/unsized-across-await.rs:11:9
|
||||||
|
|
|
||||||
|
LL | let _x = *x;
|
||||||
|
| ^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `dyn std::fmt::Display`
|
||||||
|
= note: all values live across `await` must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
18
tests/ui/async-await/unsized-across-await.rs
Normal file
18
tests/ui/async-await/unsized-across-await.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// edition: 2021
|
||||||
|
// revisions: no_drop_tracking drop_tracking_mir
|
||||||
|
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
|
||||||
|
|
||||||
|
#![feature(unsized_locals)]
|
||||||
|
//~^ WARN the feature `unsized_locals` is incomplete
|
||||||
|
|
||||||
|
async fn f() {}
|
||||||
|
|
||||||
|
async fn g(x: Box<dyn std::fmt::Display>) {
|
||||||
|
let _x = *x;
|
||||||
|
//~^ ERROR the size for values of type `dyn std::fmt::Display` cannot be known at compilation time
|
||||||
|
f().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _a = g(Box::new(5));
|
||||||
|
}
|
10
tests/ui/closures/capture-unsized-by-move.rs
Normal file
10
tests/ui/closures/capture-unsized-by-move.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// compile-flags: --crate-type=lib
|
||||||
|
|
||||||
|
#![feature(unsized_fn_params)]
|
||||||
|
|
||||||
|
pub fn f(k: dyn std::fmt::Display) {
|
||||||
|
let k2 = move || {
|
||||||
|
k.to_string();
|
||||||
|
//~^ ERROR the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time
|
||||||
|
};
|
||||||
|
}
|
14
tests/ui/closures/capture-unsized-by-move.stderr
Normal file
14
tests/ui/closures/capture-unsized-by-move.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0277]: the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time
|
||||||
|
--> $DIR/capture-unsized-by-move.rs:7:9
|
||||||
|
|
|
||||||
|
LL | let k2 = move || {
|
||||||
|
| -- this closure captures all values by move
|
||||||
|
LL | k.to_string();
|
||||||
|
| ^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `(dyn std::fmt::Display + 'static)`
|
||||||
|
= note: all values captured by value by a closure must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
10
tests/ui/closures/capture-unsized-by-ref.rs
Normal file
10
tests/ui/closures/capture-unsized-by-ref.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// build-pass
|
||||||
|
// compile-flags: --crate-type=lib
|
||||||
|
|
||||||
|
#![feature(unsized_fn_params)]
|
||||||
|
|
||||||
|
pub fn f(k: dyn std::fmt::Display) {
|
||||||
|
let k2 = || {
|
||||||
|
k.to_string();
|
||||||
|
};
|
||||||
|
}
|
34
tests/ui/generator/unsized-across-yield.rs
Normal file
34
tests/ui/generator/unsized-across-yield.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#![feature(generator_trait)]
|
||||||
|
#![feature(generators)]
|
||||||
|
#![feature(unsized_locals)]
|
||||||
|
//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
|
||||||
|
use std::ops::Generator;
|
||||||
|
|
||||||
|
fn across() -> impl Generator {
|
||||||
|
move || {
|
||||||
|
let b: [u8] = *(Box::new([]) as Box<[u8]>);
|
||||||
|
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
|
||||||
|
yield;
|
||||||
|
|
||||||
|
for elem in b.iter() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capture() -> impl Generator {
|
||||||
|
let b: [u8] = *(Box::new([]) as Box<[u8]>);
|
||||||
|
move || {
|
||||||
|
println!("{:?}", &b);
|
||||||
|
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
|
||||||
|
yield;
|
||||||
|
|
||||||
|
for elem in b.iter() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
across();
|
||||||
|
capture();
|
||||||
|
}
|
32
tests/ui/generator/unsized-across-yield.stderr
Normal file
32
tests/ui/generator/unsized-across-yield.stderr
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/unsized-across-yield.rs:3:12
|
||||||
|
|
|
||||||
|
LL | #![feature(unsized_locals)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
--> $DIR/unsized-across-yield.rs:10:13
|
||||||
|
|
|
||||||
|
LL | let b: [u8] = *(Box::new([]) as Box<[u8]>);
|
||||||
|
| ^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `[u8]`
|
||||||
|
= note: all values live across `yield` must have a statically known size
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
--> $DIR/unsized-across-yield.rs:22:27
|
||||||
|
|
|
||||||
|
LL | move || {
|
||||||
|
| -- this closure captures all values by move
|
||||||
|
LL | println!("{:?}", &b);
|
||||||
|
| ^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `[u8]`
|
||||||
|
= note: all values captured by value by a closure must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue