Bless tests, add comments
This commit is contained in:
parent
427896dd7e
commit
881b6b5149
@ -47,8 +47,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
user_provided_sig,
|
||||
);
|
||||
|
||||
// FIXME(async_closures): We must apply the same transformation to our
|
||||
// signature here as we do during closure checking.
|
||||
// FIXME(async_closures): It's kind of wacky that we must apply this
|
||||
// transformation here, since we do the same thing in HIR typeck.
|
||||
// Maybe we could just fix up the canonicalized signature during HIR typeck?
|
||||
if let DefiningTy::CoroutineClosure(_, args) =
|
||||
self.borrowck_context.universal_regions.defining_ty
|
||||
{
|
||||
|
@ -98,7 +98,10 @@ pub enum DefiningTy<'tcx> {
|
||||
Coroutine(DefId, GenericArgsRef<'tcx>),
|
||||
|
||||
/// The MIR is a special kind of closure that returns coroutines.
|
||||
/// TODO: describe how to make the sig...
|
||||
///
|
||||
/// See the documentation on `CoroutineClosureSignature` for details
|
||||
/// on how to construct the callable signature of the coroutine from
|
||||
/// its args.
|
||||
CoroutineClosure(DefId, GenericArgsRef<'tcx>),
|
||||
|
||||
/// The MIR is a fn item with the given `DefId` and args. The signature
|
||||
|
@ -335,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For this check, we do *not* want to treat async coroutine closures (async blocks)
|
||||
// For this check, we do *not* want to treat async coroutine-closures (async blocks)
|
||||
// as proper closures. Doing so would regress type inference when feeding
|
||||
// the return value of an argument-position async block to an argument-position
|
||||
// closure wrapped in a block.
|
||||
|
@ -262,8 +262,16 @@ pub struct CoroutineInfo<'tcx> {
|
||||
/// Coroutine drop glue. This field is populated after the state transform pass.
|
||||
pub coroutine_drop: Option<Body<'tcx>>,
|
||||
|
||||
/// The body of the coroutine, modified to take its upvars by move.
|
||||
/// TODO:
|
||||
/// The body of the coroutine, modified to take its upvars by move rather than by ref.
|
||||
///
|
||||
/// This is used by coroutine-closures, which must return a different flavor of coroutine
|
||||
/// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` which
|
||||
/// is run right after building the initial MIR, and will only be populated for coroutines
|
||||
/// which come out of the async closure desugaring.
|
||||
///
|
||||
/// This body should be processed in lockstep with the containing body -- any optimization
|
||||
/// passes, etc, should be applied to this body as well. This is done automatically if
|
||||
/// using `run_passes`.
|
||||
pub by_move_body: Option<Body<'tcx>>,
|
||||
|
||||
/// The layout of a coroutine. This field is populated after the state transform pass.
|
||||
|
@ -756,7 +756,7 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
query coroutine_for_closure(def_id: DefId) -> DefId {
|
||||
desc { |_tcx| "TODO" }
|
||||
desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,9 @@ pub enum SelectionCandidate<'tcx> {
|
||||
/// generated for an `async ||` expression.
|
||||
AsyncClosureCandidate,
|
||||
|
||||
// TODO:
|
||||
/// Implementation of the the `AsyncFnKindHelper` helper trait, which
|
||||
/// is used internally to delay computation for async closures until after
|
||||
/// upvar analysis is performed in HIR typeck.
|
||||
AsyncFnKindHelperCandidate,
|
||||
|
||||
/// Implementation of a `Coroutine` trait by one of the anonymous types
|
||||
|
@ -101,7 +101,10 @@ pub enum InstanceDef<'tcx> {
|
||||
target_kind: ty::ClosureKind,
|
||||
},
|
||||
|
||||
/// TODO:
|
||||
/// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce`
|
||||
/// is called on a coroutine-closure whose closure kind is not `FnOnce`. This
|
||||
/// will select the body that is produced by the `ByMoveBody` transform, and thus
|
||||
/// take and use all of its upvars by-move rather than by-ref.
|
||||
CoroutineByMoveShim { coroutine_def_id: DefId },
|
||||
|
||||
/// Compiler-generated accessor for thread locals which returns a reference to the thread local
|
||||
|
@ -877,7 +877,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
ty::CoroutineClosure(did, args) => {
|
||||
p!(write("{{"));
|
||||
if !self.should_print_verbose() {
|
||||
p!(write("coroutine closure"));
|
||||
p!(write("coroutine-closure"));
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||
|
@ -276,11 +276,31 @@ pub struct CoroutineClosureArgs<'tcx> {
|
||||
}
|
||||
|
||||
pub struct CoroutineClosureArgsParts<'tcx> {
|
||||
/// This is the args of the typeck root.
|
||||
pub parent_args: &'tcx [GenericArg<'tcx>],
|
||||
/// Represents the maximum calling capability of the closure.
|
||||
pub closure_kind_ty: Ty<'tcx>,
|
||||
/// Represents all of the relevant parts of the coroutine returned by this
|
||||
/// coroutine-closure. This signature parts type will have the general
|
||||
/// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
|
||||
/// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
|
||||
/// coroutine returned by the coroutine-closure.
|
||||
///
|
||||
/// Use `coroutine_closure_sig` to break up this type rather than using it
|
||||
/// yourself.
|
||||
pub signature_parts_ty: Ty<'tcx>,
|
||||
/// The upvars captured by the closure. Remains an inference variable
|
||||
/// until the upvar analysis, which happens late in HIR typeck.
|
||||
pub tupled_upvars_ty: Ty<'tcx>,
|
||||
/// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
|
||||
/// This allows us to represent the binder of the self-captures of the closure.
|
||||
///
|
||||
/// For example, if the coroutine returned by the closure borrows `String`
|
||||
/// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
|
||||
/// while the `tupled_upvars_ty`, representing the by-move version of the same
|
||||
/// captures, will be `(String,)`.
|
||||
pub coroutine_captures_by_ref_ty: Ty<'tcx>,
|
||||
/// Witness type returned by the generator produced by this coroutine-closure.
|
||||
pub coroutine_witness_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
@ -496,15 +516,27 @@ pub struct CoroutineArgs<'tcx> {
|
||||
pub struct CoroutineArgsParts<'tcx> {
|
||||
/// This is the args of the typeck root.
|
||||
pub parent_args: &'tcx [GenericArg<'tcx>],
|
||||
// TODO: why
|
||||
|
||||
/// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
|
||||
/// implementations must be distinguished since the former takes the closure's
|
||||
/// upvars by move, and the latter takes the closure's upvars by ref.
|
||||
///
|
||||
/// This field distinguishes these fields so that codegen can select the right
|
||||
/// body for the coroutine. This has the same type representation as the closure
|
||||
/// kind: `i8`/`i16`/`i32`.
|
||||
///
|
||||
/// For regular coroutines, this field will always just be `()`.
|
||||
pub kind_ty: Ty<'tcx>,
|
||||
|
||||
pub resume_ty: Ty<'tcx>,
|
||||
pub yield_ty: Ty<'tcx>,
|
||||
pub return_ty: Ty<'tcx>,
|
||||
|
||||
/// The interior type of the coroutine.
|
||||
/// Represents all types that are stored in locals
|
||||
/// in the coroutine's body.
|
||||
pub witness: Ty<'tcx>,
|
||||
|
||||
/// The upvars captured by the closure. Remains an inference variable
|
||||
/// until the upvar analysis, which happens late in HIR typeck.
|
||||
pub tupled_upvars_ty: Ty<'tcx>,
|
||||
@ -556,7 +588,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
||||
self.split().parent_args
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Returns the kind of the coroutine. See docs on the `kind_ty` field.
|
||||
pub fn kind_ty(self) -> Ty<'tcx> {
|
||||
self.split().kind_ty
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::CoroutineClosure(..) => {
|
||||
todo!("FIXME(async_closure): Lower these to SMIR")
|
||||
todo!("FIXME(async_closures): Lower these to SMIR")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
|
||||
tables.closure_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
)),
|
||||
ty::CoroutineClosure(..) => todo!("/* TODO */"),
|
||||
ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"),
|
||||
ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine(
|
||||
tables.coroutine_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
|
@ -321,6 +321,7 @@ symbols! {
|
||||
TyCtxt,
|
||||
TyKind,
|
||||
Unknown,
|
||||
Upvars,
|
||||
Vec,
|
||||
VecDeque,
|
||||
Wrapper,
|
||||
|
@ -190,7 +190,9 @@ pub(super) trait GoalKind<'tcx>:
|
||||
kind: ty::ClosureKind,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
/// TODO:
|
||||
/// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
|
||||
/// is used internally to delay computation for async closures until after
|
||||
/// upvar analysis is performed in HIR typeck.
|
||||
fn consider_builtin_async_fn_kind_helper_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -8,6 +8,7 @@ use rustc_middle::traits::solve::Goal;
|
||||
use rustc_middle::ty::{
|
||||
self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::solve::EvalCtxt;
|
||||
|
||||
@ -274,7 +275,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
||||
Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
|
||||
}
|
||||
|
||||
// Coroutine closures don't implement `Fn` traits the normal way.
|
||||
// Coroutine-closures don't implement `Fn` traits the normal way.
|
||||
ty::CoroutineClosure(..) => Err(NoSolution),
|
||||
|
||||
ty::Bool
|
||||
@ -341,11 +342,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
||||
vec![],
|
||||
))
|
||||
} else {
|
||||
let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
||||
// FIXME(async_closures): Make this into a lang item.
|
||||
let async_fn_kind_trait_def_id =
|
||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
||||
let upvars_projection_def_id = tcx
|
||||
.associated_items(helper_trait_def_id)
|
||||
.in_definition_order()
|
||||
.associated_items(async_fn_kind_trait_def_id)
|
||||
.filter_by_name_unhygienic(sym::Upvars)
|
||||
.next()
|
||||
.unwrap()
|
||||
.def_id;
|
||||
@ -375,7 +376,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
|
||||
vec![
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
helper_trait_def_id,
|
||||
async_fn_kind_trait_def_id,
|
||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||
)
|
||||
.to_predicate(tcx),
|
||||
|
@ -2461,12 +2461,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
||||
let goal_kind =
|
||||
tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap();
|
||||
|
||||
let helper_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
||||
let async_fn_kind_helper_trait_def_id =
|
||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
||||
nested.push(obligation.with(
|
||||
tcx,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
helper_trait_def_id,
|
||||
async_fn_kind_helper_trait_def_id,
|
||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||
),
|
||||
));
|
||||
@ -2476,9 +2477,12 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
|
||||
ty::ClosureKind::FnOnce => tcx.lifetimes.re_static,
|
||||
};
|
||||
|
||||
// FIXME(async_closures): Make this into a lang item.
|
||||
let upvars_projection_def_id =
|
||||
tcx.associated_items(helper_trait_def_id).in_definition_order().next().unwrap().def_id;
|
||||
let upvars_projection_def_id = tcx
|
||||
.associated_items(async_fn_kind_helper_trait_def_id)
|
||||
.filter_by_name_unhygienic(sym::Upvars)
|
||||
.next()
|
||||
.unwrap()
|
||||
.def_id;
|
||||
|
||||
// FIXME(async_closures): Confirmation is kind of a mess here. Ideally,
|
||||
// we'd short-circuit when we know that the goal_kind >= closure_kind, and not
|
||||
|
@ -202,7 +202,11 @@ pub enum TyKind<I: Interner> {
|
||||
/// `ClosureArgs` for more details.
|
||||
Closure(I::DefId, I::GenericArgs),
|
||||
|
||||
/// TODO
|
||||
/// The anonymous type of a closure. Used to represent the type of `async |a| a`.
|
||||
///
|
||||
/// Coroutine-closure args contain both the - potentially substituted - generic
|
||||
/// parameters of its parent and some synthetic parameters. See the documentation
|
||||
/// for `CoroutineClosureArgs` for more details.
|
||||
CoroutineClosure(I::DefId, I::GenericArgs),
|
||||
|
||||
/// The anonymous type of a coroutine. Used to represent the type of
|
||||
|
@ -108,9 +108,26 @@ mod impls {
|
||||
}
|
||||
|
||||
mod internal_implementation_detail {
|
||||
// TODO: needs a detailed explanation
|
||||
/// A helper trait that is used to enforce that the `ClosureKind` of a goal
|
||||
/// is within the capabilities of a `CoroutineClosure`, and which allows us
|
||||
/// to delay the projection of the tupled upvar types until after upvar
|
||||
/// analysis is complete.
|
||||
///
|
||||
/// The `Self` type is expected to be the `kind_ty` of the coroutine-closure,
|
||||
/// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind`
|
||||
/// for an explanation of that). The `GoalKind` is also the same type, but
|
||||
/// representing the kind of the trait that the closure is being called with.
|
||||
#[cfg_attr(not(bootstrap), lang = "async_fn_kind_helper")]
|
||||
trait AsyncFnKindHelper<GoalKind> {
|
||||
type Assoc<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
|
||||
// Projects a set of closure inputs (arguments), a region, and a set of upvars
|
||||
// (by move and by ref) to the upvars that we expect the coroutine to have
|
||||
// according to the `GoalKind` parameter above.
|
||||
//
|
||||
// The `Upvars` parameter should be the upvars of the parent coroutine-closure,
|
||||
// and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape
|
||||
// `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
|
||||
// of the closure's self-capture, and these upvar types will be instantiated with
|
||||
// the `'closure_env` region provided to the associated type.
|
||||
type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,8 @@
|
||||
fn foo() -> Box<dyn std::future::Future<Output = u32>> {
|
||||
let x = 0u32;
|
||||
Box::new((async || x)())
|
||||
//~^ ERROR closure may outlive the current function, but it borrows `x`, which is owned by the current function
|
||||
//~^ ERROR cannot return value referencing local variable `x`
|
||||
//~| ERROR cannot return value referencing temporary value
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,21 +1,21 @@
|
||||
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
|
||||
--> $DIR/async-borrowck-escaping-closure-error.rs:6:15
|
||||
|
|
||||
LL | Box::new((async || x)())
|
||||
| ^^^^^^^^ - `x` is borrowed here
|
||||
| |
|
||||
| may outlive borrowed value `x`
|
||||
|
|
||||
note: closure is returned here
|
||||
error[E0515]: cannot return value referencing local variable `x`
|
||||
--> $DIR/async-borrowck-escaping-closure-error.rs:6:5
|
||||
|
|
||||
LL | Box::new((async || x)())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
||||
| ^^^^^^^^^------------^^^
|
||||
| | |
|
||||
| | `x` is borrowed here
|
||||
| returns a value referencing data owned by the current function
|
||||
|
||||
error[E0515]: cannot return value referencing temporary value
|
||||
--> $DIR/async-borrowck-escaping-closure-error.rs:6:5
|
||||
|
|
||||
LL | Box::new((async move || x)())
|
||||
| ++++
|
||||
LL | Box::new((async || x)())
|
||||
| ^^^^^^^^^------------^^^
|
||||
| | |
|
||||
| | temporary value created here
|
||||
| returns a value referencing data owned by the current function
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0373`.
|
||||
For more information about this error, try `rustc --explain E0515`.
|
||||
|
@ -1,12 +1,10 @@
|
||||
// edition:2021
|
||||
// check-pass
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {
|
||||
let x = async move |x: &str| {
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
// This error is proof that the `&str` type is higher-ranked.
|
||||
// This won't work until async closures are fully impl'd.
|
||||
println!("{x}");
|
||||
};
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/higher-ranked.rs:6:34
|
||||
|
|
||||
LL | let x = async move |x: &str| {
|
||||
| ____________________________-___-_^
|
||||
| | | |
|
||||
| | | return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2`
|
||||
| | let's call the lifetime of this reference `'1`
|
||||
LL | |
|
||||
LL | | // This error is proof that the `&str` type is higher-ranked.
|
||||
LL | | // This won't work until async closures are fully impl'd.
|
||||
LL | | println!("{x}");
|
||||
LL | | };
|
||||
| |_____^ returning this value requires that `'1` must outlive `'2`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -12,7 +12,8 @@ pub async fn async_fn(x: &mut i32) -> &i32 {
|
||||
|
||||
pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
(async move || {
|
||||
//~^ captured variable cannot escape `FnMut` closure body
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR temporary value dropped while borrowed
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
@ -21,7 +22,8 @@ pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
|
||||
pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
(async move || -> &i32 {
|
||||
//~^ captured variable cannot escape `FnMut` closure body
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR temporary value dropped while borrowed
|
||||
let y = &*x;
|
||||
*x += 1; //~ ERROR cannot assign to `*x` because it is borrowed
|
||||
y
|
||||
|
@ -11,7 +11,7 @@ LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:18:9
|
||||
|
|
||||
LL | let y = &*x;
|
||||
| --- `*x` is borrowed here
|
||||
@ -22,61 +22,92 @@ LL | y
|
||||
LL | })()
|
||||
| - return type of async closure is &'1 i32
|
||||
|
||||
error: captured variable cannot escape `FnMut` closure body
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:14:20
|
||||
|
|
||||
LL | pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
| - variable defined here
|
||||
LL | (async move || {
|
||||
| __________________-_^
|
||||
| | |
|
||||
| | inferred to be a `FnMut` closure
|
||||
| ______-------------_^
|
||||
| | | |
|
||||
| | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:14:20: 20:6}` contains a lifetime `'2`
|
||||
| | lifetime `'1` represents this closure's body
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let y = &*x;
|
||||
| | - variable captured here
|
||||
LL | | *x += 1;
|
||||
LL | | y
|
||||
LL | | })()
|
||||
| |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
|
||||
| |_____^ returning this value requires that `'1` must outlive `'2`
|
||||
|
|
||||
= note: `FnMut` closures only have access to their captured variables while they are executing...
|
||||
= note: ...therefore, they cannot allow references to captured variables to escape
|
||||
= note: closure implements `FnMut`, so references to captured variables can't escape the closure
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:14:5
|
||||
|
|
||||
LL | pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | // (async move || {
|
||||
LL | ||
|
||||
LL | ||
|
||||
LL | || let y = &*x;
|
||||
LL | || *x += 1;
|
||||
LL | || y
|
||||
LL | || })()
|
||||
| ||______^_- argument requires that borrow lasts for `'1`
|
||||
| |_______|
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:26:9
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:28:9
|
||||
|
|
||||
LL | (async move || -> &i32 {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL |
|
||||
LL | let y = &*x;
|
||||
| --- `*x` is borrowed here
|
||||
LL | *x += 1;
|
||||
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
|
||||
LL | y
|
||||
| - returning this value requires that `*x` is borrowed for `'1`
|
||||
LL | })()
|
||||
| - return type of async closure is &'1 i32
|
||||
|
||||
error: captured variable cannot escape `FnMut` closure body
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:23:28
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:24:28
|
||||
|
|
||||
LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
| - variable defined here
|
||||
LL | (async move || -> &i32 {
|
||||
| __________________________-_^
|
||||
| | |
|
||||
| | inferred to be a `FnMut` closure
|
||||
| ______---------------------_^
|
||||
| | | |
|
||||
| | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:24:28: 30:6}` contains a lifetime `'2`
|
||||
| | lifetime `'1` represents this closure's body
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let y = &*x;
|
||||
| | - variable captured here
|
||||
LL | | *x += 1;
|
||||
LL | | y
|
||||
LL | | })()
|
||||
| |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
|
||||
| |_____^ returning this value requires that `'1` must outlive `'2`
|
||||
|
|
||||
= note: `FnMut` closures only have access to their captured variables while they are executing...
|
||||
= note: ...therefore, they cannot allow references to captured variables to escape
|
||||
= note: closure implements `FnMut`, so references to captured variables can't escape the closure
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:24:5
|
||||
|
|
||||
LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | // (async move || -> &i32 {
|
||||
LL | ||
|
||||
LL | ||
|
||||
LL | || let y = &*x;
|
||||
LL | || *x += 1;
|
||||
LL | || y
|
||||
LL | || })()
|
||||
| ||______^_- argument requires that borrow lasts for `'1`
|
||||
| |_______|
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
error[E0506]: cannot assign to `*x` because it is borrowed
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:34:9
|
||||
--> $DIR/issue-74072-lifetime-name-annotations.rs:36:9
|
||||
|
|
||||
LL | let y = &*x;
|
||||
| --- `*x` is borrowed here
|
||||
@ -87,6 +118,7 @@ LL | y
|
||||
LL | }
|
||||
| - return type of async block is &'1 i32
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0506`.
|
||||
Some errors have detailed explanations: E0506, E0716.
|
||||
For more information about an error, try `rustc --explain E0506`.
|
||||
|
@ -1,8 +1,9 @@
|
||||
// edition:2021
|
||||
// check-pass
|
||||
|
||||
#![feature(closure_lifetime_binder)]
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {
|
||||
for<'a> async || ();
|
||||
//~^ ERROR `for<...>` binders on `async` closures are not currently supported
|
||||
//~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present
|
||||
for<'a> async || -> () {};
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
error: `for<...>` binders on `async` closures are not currently supported
|
||||
--> $DIR/async-closure-with-binder.rs:5:5
|
||||
|
|
||||
LL | for<'a> async || ();
|
||||
| ^^^^^^^
|
||||
|
||||
error: implicit types in closure signatures are forbidden when `for<...>` is present
|
||||
--> $DIR/async-closure-with-binder.rs:5:5
|
||||
|
|
||||
LL | for<'a> async || ();
|
||||
| -------^^^^^^^^^
|
||||
| |
|
||||
| `for<...>` is here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -18,25 +18,21 @@ help: use parentheses to call this function
|
||||
LL | bar(foo());
|
||||
| ++
|
||||
|
||||
error[E0277]: `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
|
||||
|
|
||||
LL | bar(async_closure);
|
||||
| --- ^^^^^^^^^^^^^ `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
| --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Future` is not implemented for closure `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
|
||||
= note: {closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
|
||||
= help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
|
||||
= note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
|
||||
|
|
||||
LL | fn bar(f: impl Future<Output=()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
|
||||
help: use parentheses to call this closure
|
||||
|
|
||||
LL | bar(async_closure());
|
||||
| ++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE)
|
||||
error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(basic::main::h9308686d0228fa1d)
|
||||
error: demangling(basic::main::h6fc0c8d27b1a289f)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E)
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h84ab5dafbd2a1508)
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hab58a402db4ebf3a)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
|
Loading…
x
Reference in New Issue
Block a user