mirror of https://github.com/rust-lang/rust.git
Auto merge of #123792 - oli-obk:coroutine_closures, r=compiler-errors
Require explicitly marking closures as coroutines instead of relying on patching up the closure to be a coroutine if it happens to contain a `yield` expression. I only do this in the 2024 edition, as the `gen` keyword is only available there.
This commit is contained in:
commit
e9362896e0
|
@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign =
|
|||
.label = `_` not allowed here
|
||||
|
||||
ast_lowering_use_angle_brackets = use angle brackets instead
|
||||
ast_lowering_yield_in_closure =
|
||||
`yield` can only be used in `#[coroutine]` closures, or `gen` blocks
|
||||
.suggestion = use `#[coroutine]` to make this closure a coroutine
|
||||
|
|
|
@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_yield_in_closure)]
|
||||
pub(crate) struct YieldInClosure {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
|
||||
pub suggestion: Option<Span>,
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use super::errors::{
|
|||
};
|
||||
use super::ResolverAstLoweringExt;
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||
use crate::errors::YieldInClosure;
|
||||
use crate::{FnDeclKind, ImplTraitPosition};
|
||||
use rustc_ast::ptr::P as AstP;
|
||||
use rustc_ast::*;
|
||||
|
@ -217,6 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
binder,
|
||||
*capture_clause,
|
||||
e.id,
|
||||
hir_id,
|
||||
*constness,
|
||||
*movability,
|
||||
fn_decl,
|
||||
|
@ -955,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
binder: &ClosureBinder,
|
||||
capture_clause: CaptureBy,
|
||||
closure_id: NodeId,
|
||||
closure_hir_id: hir::HirId,
|
||||
constness: Const,
|
||||
movability: Movability,
|
||||
decl: &FnDecl,
|
||||
|
@ -965,8 +968,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
let mut coroutine_kind = None;
|
||||
let mut coroutine_kind = if this
|
||||
.attrs
|
||||
.get(&closure_hir_id.local_id)
|
||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||
{
|
||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
this.coroutine_kind = coroutine_kind;
|
||||
let e = this.lower_expr_mut(body);
|
||||
coroutine_kind = this.coroutine_kind;
|
||||
e
|
||||
|
@ -1565,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)
|
||||
.emit();
|
||||
}
|
||||
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
|
||||
self.dcx().emit_err(YieldInClosure { span, suggestion });
|
||||
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
|
||||
|
||||
false
|
||||
}
|
||||
};
|
||||
|
|
|
@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
body,
|
||||
..
|
||||
}) => {
|
||||
self.with_new_scopes(ident.span, |this| {
|
||||
self.with_new_scopes(*fn_sig_span, |this| {
|
||||
// Note: we don't need to change the return type from `T` to
|
||||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
use std::pin::Pin;
|
||||
|
@ -8,7 +8,8 @@ fn main() {
|
|||
}
|
||||
|
||||
fn run_coroutine<T>() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine]
|
||||
|| {
|
||||
yield;
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(
|
||||
core_intrinsics,
|
||||
coroutines,
|
||||
stmt_expr_attributes,
|
||||
coroutine_trait,
|
||||
is_sorted,
|
||||
repr_simd,
|
||||
|
@ -123,9 +124,12 @@ fn main() {
|
|||
test_simd();
|
||||
}
|
||||
|
||||
Box::pin(move |mut _task_context| {
|
||||
yield ();
|
||||
})
|
||||
Box::pin(
|
||||
#[coroutine]
|
||||
move |mut _task_context| {
|
||||
yield ();
|
||||
},
|
||||
)
|
||||
.as_mut()
|
||||
.resume(0);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
|
@ -103,7 +103,7 @@ fn main() {
|
|||
test_simd();
|
||||
}
|
||||
|
||||
Box::pin(move |mut _task_context| {
|
||||
Box::pin(#[coroutine] move |mut _task_context| {
|
||||
yield ();
|
||||
}).as_mut().resume(0);
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ yield point.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0626
|
||||
# #![feature(coroutines, coroutine_trait, pin)]
|
||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
# use std::ops::Coroutine;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine] || {
|
||||
let a = &String::new(); // <-- This borrow...
|
||||
yield (); // ...is still in scope here, when the yield occurs.
|
||||
println!("{}", a);
|
||||
|
@ -23,10 +23,10 @@ resolve the previous example by removing the borrow and just storing
|
|||
the integer by value:
|
||||
|
||||
```
|
||||
# #![feature(coroutines, coroutine_trait, pin)]
|
||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
# use std::ops::Coroutine;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine] || {
|
||||
let a = 3;
|
||||
yield ();
|
||||
println!("{}", a);
|
||||
|
@ -41,10 +41,10 @@ in those cases, something like the `Rc` or `Arc` types may be useful.
|
|||
This error also frequently arises with iteration:
|
||||
|
||||
```compile_fail,E0626
|
||||
# #![feature(coroutines, coroutine_trait, pin)]
|
||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
# use std::ops::Coroutine;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine] || {
|
||||
let v = vec![1,2,3];
|
||||
for &x in &v { // <-- borrow of `v` is still in scope...
|
||||
yield x; // ...when this yield occurs.
|
||||
|
@ -57,10 +57,10 @@ Such cases can sometimes be resolved by iterating "by value" (or using
|
|||
`into_iter()`) to avoid borrowing:
|
||||
|
||||
```
|
||||
# #![feature(coroutines, coroutine_trait, pin)]
|
||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
# use std::ops::Coroutine;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine] || {
|
||||
let v = vec![1,2,3];
|
||||
for x in v { // <-- Take ownership of the values instead!
|
||||
yield x; // <-- Now yield is OK.
|
||||
|
@ -72,10 +72,10 @@ Pin::new(&mut b).resume(());
|
|||
If taking ownership is not an option, using indices can work too:
|
||||
|
||||
```
|
||||
# #![feature(coroutines, coroutine_trait, pin)]
|
||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
# use std::ops::Coroutine;
|
||||
# use std::pin::Pin;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine] || {
|
||||
let v = vec![1,2,3];
|
||||
let len = v.len(); // (*)
|
||||
for i in 0..len {
|
||||
|
|
|
@ -3,7 +3,7 @@ A yield expression was used outside of the coroutine literal.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0627
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
fn fake_coroutine() -> &'static str {
|
||||
yield 1;
|
||||
|
@ -19,10 +19,10 @@ The error occurs because keyword `yield` can only be used inside the coroutine
|
|||
literal. This can be fixed by constructing the coroutine correctly.
|
||||
|
||||
```
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
return "foo"
|
||||
};
|
||||
|
|
|
@ -3,10 +3,10 @@ More than one parameter was used for a coroutine.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0628
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let coroutine = |a: i32, b: i32| {
|
||||
let coroutine = #[coroutine] |a: i32, b: i32| {
|
||||
// error: too many parameters for a coroutine
|
||||
// Allowed only 0 or 1 parameter
|
||||
yield a;
|
||||
|
@ -20,10 +20,10 @@ at most 1 parameter for the coroutine. For example, we might resolve
|
|||
the previous example by passing only one parameter.
|
||||
|
||||
```
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let coroutine = |a: i32| {
|
||||
let coroutine = #[coroutine] |a: i32| {
|
||||
yield a;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ A `yield` clause was used in an `async` context.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0727,edition2018
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let coroutine = || {
|
||||
let coroutine = #[coroutine] || {
|
||||
async {
|
||||
yield;
|
||||
}
|
||||
|
@ -20,10 +20,10 @@ which is not yet supported.
|
|||
To fix this error, you have to move `yield` out of the `async` block:
|
||||
|
||||
```edition2018
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let coroutine = || {
|
||||
let coroutine = #[coroutine] || {
|
||||
yield;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -534,6 +534,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::Yes, experimental!(cfi_encoding)
|
||||
),
|
||||
|
||||
// `#[coroutine]` attribute to be applied to closures to make them coroutines instead
|
||||
gated!(
|
||||
coroutine, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::No, coroutines, experimental!(coroutines)
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes: Stability, deprecation, and unsafe:
|
||||
// ==========================================================================
|
||||
|
|
|
@ -1260,30 +1260,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
id: DefIndex,
|
||||
sess: &'a Session,
|
||||
) -> impl Iterator<Item = ModChild> + 'a {
|
||||
iter::from_coroutine(move || {
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
// If we are loading as a proc macro, we want to return
|
||||
// the view of this crate as a proc macro crate.
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for child_index in data.macros.decode(self) {
|
||||
iter::from_coroutine(
|
||||
#[cfg_attr(not(bootstrap), coroutine)]
|
||||
move || {
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
// If we are loading as a proc macro, we want to return
|
||||
// the view of this crate as a proc macro crate.
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for child_index in data.macros.decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Iterate over all children.
|
||||
let non_reexports =
|
||||
self.root.tables.module_children_non_reexports.get(self, id);
|
||||
for child_index in non_reexports.unwrap().decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Iterate over all children.
|
||||
let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
|
||||
for child_index in non_reexports.unwrap().decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
|
||||
let reexports = self.root.tables.module_children_reexports.get(self, id);
|
||||
if !reexports.is_default() {
|
||||
for reexport in reexports.decode((self, sess)) {
|
||||
yield reexport;
|
||||
let reexports = self.root.tables.module_children_reexports.get(self, id);
|
||||
if !reexports.is_default() {
|
||||
for reexport in reexports.decode((self, sess)) {
|
||||
yield reexport;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#![feature(const_type_name)]
|
||||
#![feature(discriminant_kind)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
|
|
|
@ -422,49 +422,53 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>(
|
|||
child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
|
||||
mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T,
|
||||
) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> {
|
||||
std::iter::from_coroutine(move || {
|
||||
let mut child_captures = child_captures.into_iter().enumerate().peekable();
|
||||
std::iter::from_coroutine(
|
||||
#[cfg_attr(not(bootstrap), coroutine)]
|
||||
move || {
|
||||
let mut child_captures = child_captures.into_iter().enumerate().peekable();
|
||||
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
|
||||
// A parent matches a child if they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
while child_captures.peek().map_or(false, |(_, child_capture)| {
|
||||
child_prefix_matches_parent_projections(parent_capture, child_capture)
|
||||
}) {
|
||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||
// This analysis only makes sense if the parent capture is a
|
||||
// prefix of the child capture.
|
||||
assert!(
|
||||
child_capture.place.projections.len() >= parent_capture.place.projections.len(),
|
||||
"parent capture ({parent_capture:#?}) expected to be prefix of \
|
||||
// A parent matches a child if they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
while child_captures.peek().map_or(false, |(_, child_capture)| {
|
||||
child_prefix_matches_parent_projections(parent_capture, child_capture)
|
||||
}) {
|
||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||
// This analysis only makes sense if the parent capture is a
|
||||
// prefix of the child capture.
|
||||
assert!(
|
||||
child_capture.place.projections.len()
|
||||
>= parent_capture.place.projections.len(),
|
||||
"parent capture ({parent_capture:#?}) expected to be prefix of \
|
||||
child capture ({child_capture:#?})"
|
||||
);
|
||||
);
|
||||
|
||||
yield for_each(
|
||||
(parent_field_idx, parent_capture),
|
||||
(child_field_idx, child_capture),
|
||||
);
|
||||
yield for_each(
|
||||
(parent_field_idx, parent_capture),
|
||||
(child_field_idx, child_capture),
|
||||
);
|
||||
|
||||
field_used_at_least_once = true;
|
||||
field_used_at_least_once = true;
|
||||
}
|
||||
|
||||
// Make sure the field was used at least once.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure the field was used at least once.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
);
|
||||
}
|
||||
assert_eq!(child_captures.next(), None, "leftover child captures?");
|
||||
})
|
||||
assert_eq!(child_captures.next(), None, "leftover child captures?");
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn child_prefix_matches_parent_projections(
|
||||
|
|
|
@ -1284,20 +1284,23 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||
|
||||
let definitions = &self.untracked.definitions;
|
||||
std::iter::from_coroutine(|| {
|
||||
let mut i = 0;
|
||||
std::iter::from_coroutine(
|
||||
#[cfg_attr(not(bootstrap), coroutine)]
|
||||
|| {
|
||||
let mut i = 0;
|
||||
|
||||
// Recompute the number of definitions each time, because our caller may be creating
|
||||
// new ones.
|
||||
while i < { definitions.read().num_definitions() } {
|
||||
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
||||
yield LocalDefId { local_def_index };
|
||||
i += 1;
|
||||
}
|
||||
// Recompute the number of definitions each time, because our caller may be creating
|
||||
// new ones.
|
||||
while i < { definitions.read().num_definitions() } {
|
||||
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
||||
yield LocalDefId { local_def_index };
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
|
||||
definitions.freeze();
|
||||
})
|
||||
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
|
||||
definitions.freeze();
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
|
||||
|
|
|
@ -183,7 +183,7 @@ pub enum TyKind<I: Interner> {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(coroutines)]
|
||||
/// static |a| {
|
||||
/// #[coroutine] static |a| {
|
||||
/// let x = &vec![3];
|
||||
/// yield a;
|
||||
/// yield x[0];
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::pin::Pin;
|
|||
/// #![feature(coroutines)]
|
||||
/// #![feature(iter_from_coroutine)]
|
||||
///
|
||||
/// let it = std::iter::from_coroutine(|| {
|
||||
/// let it = std::iter::from_coroutine(#[cfg_attr(not(bootstrap), coroutine)] || {
|
||||
/// yield 1;
|
||||
/// yield 2;
|
||||
/// yield 3;
|
||||
|
|
|
@ -40,12 +40,13 @@ pub enum CoroutineState<Y, R> {
|
|||
/// ```rust
|
||||
/// #![feature(coroutines)]
|
||||
/// #![feature(coroutine_trait)]
|
||||
/// #![feature(stmt_expr_attributes)]
|
||||
///
|
||||
/// use std::ops::{Coroutine, CoroutineState};
|
||||
/// use std::pin::Pin;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut coroutine = || {
|
||||
/// let mut coroutine = #[cfg_attr(not(bootstrap), coroutine)] || {
|
||||
/// yield 1;
|
||||
/// "foo"
|
||||
/// };
|
||||
|
|
|
@ -1809,7 +1809,7 @@ impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U>
|
|||
/// fn coroutine_fn() -> impl Coroutine<Yield = usize, Return = ()> /* not Unpin */ {
|
||||
/// // Allow coroutine to be self-referential (not `Unpin`)
|
||||
/// // vvvvvv so that locals can cross yield points.
|
||||
/// static || {
|
||||
/// #[cfg_attr(not(bootstrap), coroutine)] static || {
|
||||
/// let foo = String::from("foo");
|
||||
/// let foo_ref = &foo; // ------+
|
||||
/// yield 0; // | <- crosses yield point!
|
||||
|
|
|
@ -26,13 +26,13 @@ tweaks to the overall design.
|
|||
A syntactical example of a coroutine is:
|
||||
|
||||
```rust
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
return "foo"
|
||||
};
|
||||
|
@ -48,7 +48,8 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
Coroutines are closure-like literals which can contain a `yield` statement. The
|
||||
Coroutines are closure-like literals which are annotated with `#[coroutine]`
|
||||
and can contain a `yield` statement. The
|
||||
`yield` statement takes an optional expression of a value to yield out of the
|
||||
coroutine. All coroutine literals implement the `Coroutine` trait in the
|
||||
`std::ops` module. The `Coroutine` trait has one main method, `resume`, which
|
||||
|
@ -58,13 +59,13 @@ An example of the control flow of coroutines is that the following example
|
|||
prints all numbers in order:
|
||||
|
||||
```rust
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
println!("2");
|
||||
yield;
|
||||
println!("4");
|
||||
|
@ -78,9 +79,9 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
At this time the main intended use case of coroutines is an implementation
|
||||
primitive for async/await syntax, but coroutines will likely be extended to
|
||||
ergonomic implementations of iterators and other primitives in the future.
|
||||
At this time the main use case of coroutines is an implementation
|
||||
primitive for `async`/`await` and `gen` syntax, but coroutines
|
||||
will likely be extended to other primitives in the future.
|
||||
Feedback on the design and usage is always appreciated!
|
||||
|
||||
### The `Coroutine` trait
|
||||
|
@ -163,14 +164,14 @@ which point all state is saved off in the coroutine and a value is returned.
|
|||
Let's take a look at an example to see what's going on here:
|
||||
|
||||
```rust
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let ret = "foo";
|
||||
let mut coroutine = move || {
|
||||
let mut coroutine = #[coroutine] move || {
|
||||
yield 1;
|
||||
return ret
|
||||
};
|
||||
|
@ -183,7 +184,7 @@ fn main() {
|
|||
This coroutine literal will compile down to something similar to:
|
||||
|
||||
```rust
|
||||
#![feature(arbitrary_self_types, coroutines, coroutine_trait)]
|
||||
#![feature(arbitrary_self_types, coroutine_trait)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
|
|
@ -5,13 +5,13 @@ each one organized by a "feature flag." That is, when using an unstable
|
|||
feature of Rust, you must use a flag, like this:
|
||||
|
||||
```rust
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
return "foo"
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
yield;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(coroutines)]
|
||||
#![warn(clippy::large_futures)]
|
||||
#![allow(clippy::never_loop)]
|
||||
#![allow(clippy::future_not_send)]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(coroutines)]
|
||||
#![warn(clippy::large_futures)]
|
||||
#![allow(clippy::never_loop)]
|
||||
#![allow(clippy::future_not_send)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: large future with a size of 16385 bytes
|
||||
--> tests/ui/large_futures.rs:11:9
|
||||
--> tests/ui/large_futures.rs:10:9
|
||||
|
|
||||
LL | big_fut([0u8; 1024 * 16]).await;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
|
||||
|
@ -8,37 +8,37 @@ LL | big_fut([0u8; 1024 * 16]).await;
|
|||
= help: to override `-D warnings` add `#[allow(clippy::large_futures)]`
|
||||
|
||||
error: large future with a size of 16386 bytes
|
||||
--> tests/ui/large_futures.rs:15:5
|
||||
--> tests/ui/large_futures.rs:14:5
|
||||
|
|
||||
LL | f.await
|
||||
| ^ help: consider `Box::pin` on it: `Box::pin(f)`
|
||||
|
||||
error: large future with a size of 16387 bytes
|
||||
--> tests/ui/large_futures.rs:20:9
|
||||
--> tests/ui/large_futures.rs:19:9
|
||||
|
|
||||
LL | wait().await;
|
||||
| ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
|
||||
|
||||
error: large future with a size of 16387 bytes
|
||||
--> tests/ui/large_futures.rs:25:13
|
||||
--> tests/ui/large_futures.rs:24:13
|
||||
|
|
||||
LL | wait().await;
|
||||
| ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
|
||||
|
||||
error: large future with a size of 65540 bytes
|
||||
--> tests/ui/large_futures.rs:33:5
|
||||
--> tests/ui/large_futures.rs:32:5
|
||||
|
|
||||
LL | foo().await;
|
||||
| ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
|
||||
|
||||
error: large future with a size of 49159 bytes
|
||||
--> tests/ui/large_futures.rs:35:5
|
||||
--> tests/ui/large_futures.rs:34:5
|
||||
|
|
||||
LL | calls_fut(fut).await;
|
||||
| ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
|
||||
|
||||
error: large future with a size of 65540 bytes
|
||||
--> tests/ui/large_futures.rs:48:5
|
||||
--> tests/ui/large_futures.rs:47:5
|
||||
|
|
||||
LL | / async {
|
||||
LL | |
|
||||
|
@ -59,7 +59,7 @@ LL + })
|
|||
|
|
||||
|
||||
error: large future with a size of 65540 bytes
|
||||
--> tests/ui/large_futures.rs:60:13
|
||||
--> tests/ui/large_futures.rs:59:13
|
||||
|
|
||||
LL | / async {
|
||||
LL | | let x = [0i32; 1024 * 16];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//@aux-build:proc_macros.rs
|
||||
#![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
|
||||
#![warn(clippy::redundant_locals)]
|
||||
#![feature(async_closure, coroutines)]
|
||||
#![feature(async_closure, coroutines, stmt_expr_attributes)]
|
||||
|
||||
extern crate proc_macros;
|
||||
use proc_macros::{external, with_span};
|
||||
|
@ -191,11 +191,11 @@ fn issue12225() {
|
|||
let v4 = v4;
|
||||
dbg!(&v4);
|
||||
});
|
||||
assert_static(static || {
|
||||
assert_static(#[coroutine] static || {
|
||||
let v5 = v5;
|
||||
yield;
|
||||
});
|
||||
assert_static(|| {
|
||||
assert_static(#[coroutine] || {
|
||||
let v6 = v6;
|
||||
yield;
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::{
|
||||
ops::{Coroutine, CoroutineState},
|
||||
|
@ -7,7 +7,7 @@ use std::{
|
|||
};
|
||||
|
||||
fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
|
||||
static move || {
|
||||
#[coroutine] static move || {
|
||||
let mut num = 0;
|
||||
let num = &mut num;
|
||||
*num += 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@revisions: stack tree
|
||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||
#![feature(coroutines, coroutine_trait, never_type)]
|
||||
#![feature(coroutines, coroutine_trait, never_type, stmt_expr_attributes)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
@ -43,9 +43,9 @@ fn basic() {
|
|||
panic!()
|
||||
}
|
||||
|
||||
finish(1, false, || yield 1);
|
||||
finish(1, false, #[coroutine] || yield 1);
|
||||
|
||||
finish(3, false, || {
|
||||
finish(3, false, #[coroutine] || {
|
||||
let mut x = 0;
|
||||
yield 1;
|
||||
x += 1;
|
||||
|
@ -55,27 +55,27 @@ fn basic() {
|
|||
assert_eq!(x, 2);
|
||||
});
|
||||
|
||||
finish(7 * 8 / 2, false, || {
|
||||
finish(7 * 8 / 2, false, #[coroutine] || {
|
||||
for i in 0..8 {
|
||||
yield i;
|
||||
}
|
||||
});
|
||||
|
||||
finish(1, false, || {
|
||||
finish(1, false, #[coroutine] || {
|
||||
if true {
|
||||
yield 1;
|
||||
} else {
|
||||
}
|
||||
});
|
||||
|
||||
finish(1, false, || {
|
||||
finish(1, false, #[coroutine] || {
|
||||
if false {
|
||||
} else {
|
||||
yield 1;
|
||||
}
|
||||
});
|
||||
|
||||
finish(2, false, || {
|
||||
finish(2, false, #[coroutine] || {
|
||||
if {
|
||||
yield 1;
|
||||
false
|
||||
|
@ -88,7 +88,7 @@ fn basic() {
|
|||
|
||||
// also test self-referential coroutines
|
||||
assert_eq!(
|
||||
finish(5, true, static || {
|
||||
finish(5, true, #[coroutine] static || {
|
||||
let mut x = 5;
|
||||
let y = &mut x;
|
||||
*y = 5;
|
||||
|
@ -99,7 +99,7 @@ fn basic() {
|
|||
10
|
||||
);
|
||||
assert_eq!(
|
||||
finish(5, true, || {
|
||||
finish(5, true, #[coroutine] || {
|
||||
let mut x = Box::new(5);
|
||||
let y = &mut *x;
|
||||
*y = 5;
|
||||
|
@ -111,7 +111,7 @@ fn basic() {
|
|||
);
|
||||
|
||||
let b = true;
|
||||
finish(1, false, || {
|
||||
finish(1, false, #[coroutine] || {
|
||||
yield 1;
|
||||
if b {
|
||||
return;
|
||||
|
@ -123,7 +123,7 @@ fn basic() {
|
|||
drop(x);
|
||||
});
|
||||
|
||||
finish(3, false, || {
|
||||
finish(3, false, #[coroutine] || {
|
||||
yield 1;
|
||||
#[allow(unreachable_code)]
|
||||
let _x: (String, !) = (String::new(), {
|
||||
|
@ -172,7 +172,7 @@ fn smoke_resume_arg() {
|
|||
}
|
||||
|
||||
drain(
|
||||
&mut |mut b| {
|
||||
&mut #[coroutine] |mut b| {
|
||||
while b != 0 {
|
||||
b = yield (b + 1);
|
||||
}
|
||||
|
@ -181,21 +181,21 @@ fn smoke_resume_arg() {
|
|||
vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))],
|
||||
);
|
||||
|
||||
expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))]));
|
||||
expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))]));
|
||||
|
||||
expect_drops(6, || {
|
||||
drain(
|
||||
&mut |a| yield yield a,
|
||||
&mut #[coroutine] |a| yield yield a,
|
||||
vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))],
|
||||
)
|
||||
});
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))]));
|
||||
expect_drops(2, || drain(&mut #[coroutine] |a| yield return a, vec![(DropMe, Complete(DropMe))]));
|
||||
|
||||
expect_drops(2, || {
|
||||
drain(
|
||||
&mut |a: DropMe| {
|
||||
&mut #[coroutine] |a: DropMe| {
|
||||
if false { yield () } else { a }
|
||||
},
|
||||
vec![(DropMe, Complete(DropMe))],
|
||||
|
@ -205,7 +205,7 @@ fn smoke_resume_arg() {
|
|||
expect_drops(4, || {
|
||||
drain(
|
||||
#[allow(unused_assignments, unused_variables)]
|
||||
&mut |mut a: DropMe| {
|
||||
&mut #[coroutine] |mut a: DropMe| {
|
||||
a = yield;
|
||||
a = yield;
|
||||
a = yield;
|
||||
|
@ -228,7 +228,7 @@ fn uninit_fields() {
|
|||
}
|
||||
|
||||
fn run<T>(x: bool, y: bool) {
|
||||
let mut c = || {
|
||||
let mut c = #[coroutine] || {
|
||||
if x {
|
||||
let _a: T;
|
||||
if y {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
|
||||
// this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::{
|
||||
ops::{Coroutine, CoroutineState},
|
||||
|
@ -8,7 +8,7 @@ use std::{
|
|||
};
|
||||
|
||||
fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
|
||||
static move || {
|
||||
#[coroutine] static move || {
|
||||
let mut num = 0;
|
||||
let num = &mut num;
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ fn test_coroutine() {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let coroutine = #[track_caller] |arg: String| {
|
||||
let coroutine = #[track_caller] #[coroutine] |arg: String| {
|
||||
yield ("first", arg.clone(), Location::caller());
|
||||
yield ("second", arg.clone(), Location::caller());
|
||||
};
|
||||
|
@ -255,7 +255,7 @@ fn test_coroutine() {
|
|||
assert_eq!(mono_loc.column(), 42);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let non_tracked_coroutine = || { yield Location::caller(); };
|
||||
let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); };
|
||||
let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
|
||||
let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
|
||||
CoroutineState::Yielded(val) => val,
|
||||
|
@ -263,7 +263,7 @@ fn test_coroutine() {
|
|||
};
|
||||
assert_eq!(non_tracked_loc.file(), file!());
|
||||
assert_eq!(non_tracked_loc.line(), non_tracked_line);
|
||||
assert_eq!(non_tracked_loc.column(), 44);
|
||||
assert_eq!(non_tracked_loc.column(), 57);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -3869,7 +3869,7 @@ use std::ops::{Coroutine, CoroutineState};
|
|||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
return "foo"
|
||||
};
|
||||
|
@ -3901,7 +3901,7 @@ use std::ops::Coroutine;
|
|||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
println!("2");
|
||||
yield;
|
||||
println!("4");
|
||||
|
@ -4007,7 +4007,7 @@ use std::pin::Pin;
|
|||
|
||||
fn main() {
|
||||
let ret = "foo";
|
||||
let mut coroutine = move || {
|
||||
let mut coroutine = #[coroutine] move || {
|
||||
yield 1;
|
||||
return ret
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#![feature(coroutines)]
|
||||
|
||||
unsafe fn foo() {
|
||||
let mut ga = static || {
|
||||
let mut ga = #[coroutine]
|
||||
static || {
|
||||
yield 1;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#![feature(coroutines)]
|
||||
|
||||
unsafe fn foo() {
|
||||
let mut ga = static || {
|
||||
let mut ga = #[coroutine]
|
||||
static || {
|
||||
yield 1;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use std::ops::Coroutine;
|
||||
|
||||
fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
yield 0;
|
||||
let s = String::from("foo");
|
||||
yield 1;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use std::ops::Coroutine;
|
||||
|
||||
fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
yield 0;
|
||||
let s = String::from("foo");
|
||||
yield 1;
|
||||
|
|
|
@ -43,11 +43,11 @@ Number of file 0 mappings: 9
|
|||
= ((c4 - c5) - c6)
|
||||
|
||||
Function name: coroutine::main::{closure#0}
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 1c, 01, 1f, 05, 02, 10, 01, 06]
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 29, 01, 1f, 05, 02, 10, 01, 06]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 21, 28) to (start + 1, 31)
|
||||
- Code(Counter(0)) at (prev + 21, 41) to (start + 1, 31)
|
||||
- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
LL| |#![feature(coroutines, coroutine_trait)]
|
||||
LL| |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
LL| |
|
||||
LL| |use std::ops::{Coroutine, CoroutineState};
|
||||
LL| |use std::pin::Pin;
|
||||
|
@ -18,7 +18,7 @@
|
|||
LL| |
|
||||
LL| 1|fn main() {
|
||||
LL| 1| let is_true = std::env::args().len() == 1;
|
||||
LL| 1| let mut coroutine = || {
|
||||
LL| 1| let mut coroutine = #[coroutine] || {
|
||||
LL| 1| yield get_u32(is_true);
|
||||
LL| 1| return "foo";
|
||||
LL| 1| };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
@ -18,7 +18,7 @@ fn get_u32(val: bool) -> Result<u32, String> {
|
|||
|
||||
fn main() {
|
||||
let is_true = std::env::args().len() == 1;
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield get_u32(is_true);
|
||||
return "foo";
|
||||
};
|
||||
|
|
|
@ -41,21 +41,21 @@ Number of file 0 mappings: 16
|
|||
- Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2)
|
||||
|
||||
Function name: yield::main::{closure#0}
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06]
|
||||
Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 29, 01, 10, 05, 02, 10, 01, 06]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 2
|
||||
- Code(Counter(0)) at (prev + 8, 28) to (start + 1, 16)
|
||||
- Code(Counter(0)) at (prev + 8, 41) to (start + 1, 16)
|
||||
- Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6)
|
||||
|
||||
Function name: yield::main::{closure#1}
|
||||
Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 1c, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06]
|
||||
Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 29, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 4
|
||||
- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 16)
|
||||
- Code(Counter(0)) at (prev + 22, 41) to (start + 1, 16)
|
||||
- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16)
|
||||
- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16)
|
||||
- Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
LL| |#![feature(coroutines, coroutine_trait)]
|
||||
LL| |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
LL| |#![allow(unused_assignments)]
|
||||
LL| |
|
||||
LL| |use std::ops::{Coroutine, CoroutineState};
|
||||
LL| |use std::pin::Pin;
|
||||
LL| |
|
||||
LL| 1|fn main() {
|
||||
LL| 1| let mut coroutine = || {
|
||||
LL| 1| let mut coroutine = #[coroutine] || {
|
||||
LL| 1| yield 1;
|
||||
LL| 1| return "foo";
|
||||
LL| 1| };
|
||||
|
@ -19,7 +19,7 @@
|
|||
LL| 0| _ => panic!("unexpected value from resume"),
|
||||
LL| | }
|
||||
LL| |
|
||||
LL| 1| let mut coroutine = || {
|
||||
LL| 1| let mut coroutine = #[coroutine] || {
|
||||
LL| 1| yield 1;
|
||||
LL| 1| yield 2;
|
||||
LL| 0| yield 3;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn main() {
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
return "foo";
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
|||
_ => panic!("unexpected value from resume"),
|
||||
}
|
||||
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine] || {
|
||||
yield 1;
|
||||
yield 2;
|
||||
yield 3;
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
// lldb-command:v c
|
||||
// lldb-check:(int) c = 6
|
||||
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
|
@ -54,7 +54,8 @@ use std::pin::Pin;
|
|||
|
||||
fn main() {
|
||||
let mut a = 5;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine]
|
||||
|| {
|
||||
let c = 6; // Live across multiple yield points
|
||||
|
||||
let d = 7; // Live across only one yield point
|
||||
|
@ -76,4 +77,6 @@ fn main() {
|
|||
_zzz(); // #break
|
||||
}
|
||||
|
||||
fn _zzz() {()}
|
||||
fn _zzz() {
|
||||
()
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
// cdb-check: b : Returned [Type: enum2$<coroutine_objects::main::coroutine_env$0>]
|
||||
// cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *]
|
||||
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
|
@ -71,7 +71,8 @@ use std::pin::Pin;
|
|||
|
||||
fn main() {
|
||||
let mut a = 5;
|
||||
let mut b = || {
|
||||
let mut b = #[coroutine]
|
||||
|| {
|
||||
let mut c = 6;
|
||||
let mut d = 7;
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
#![allow(unused_variables)]
|
||||
#![feature(omit_gdb_pretty_printer_section)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
#![feature(adt_const_params, coroutines, coroutine_trait)]
|
||||
#![feature(adt_const_params, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
|
@ -111,7 +111,8 @@ fn main() {
|
|||
closure();
|
||||
|
||||
// Coroutine
|
||||
let mut coroutine = || {
|
||||
let mut coroutine = #[coroutine]
|
||||
|| {
|
||||
yield;
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// lldb-command:v b
|
||||
// lldbg-check:(issue_57822::main::{coroutine_env#3}) b =
|
||||
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)]
|
||||
#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
|
@ -38,11 +38,13 @@ fn main() {
|
|||
let g = move || f();
|
||||
|
||||
let mut y = 2;
|
||||
let mut a = move || {
|
||||
let mut a = #[coroutine]
|
||||
move || {
|
||||
y += 1;
|
||||
yield;
|
||||
};
|
||||
let mut b = move || {
|
||||
let mut b = #[coroutine]
|
||||
move || {
|
||||
Pin::new(&mut a).resume(());
|
||||
yield;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}` 0 coroutine_drop
|
||||
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () {
|
||||
let mut _0: ();
|
||||
let mut _2: ();
|
||||
let _3: std::string::String;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}` 0 coroutine_drop
|
||||
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () {
|
||||
let mut _0: ();
|
||||
let mut _2: ();
|
||||
let _3: std::string::String;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// skip-filecheck
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
|
@ -8,7 +8,8 @@
|
|||
|
||||
// EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir
|
||||
fn main() {
|
||||
let gen = || {
|
||||
let gen = #[coroutine]
|
||||
|| {
|
||||
let _s = String::new();
|
||||
yield;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}` before StateTransform
|
||||
|
||||
fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
|
||||
fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
|
||||
yields ()
|
||||
{
|
||||
let mut _0: ();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}` before StateTransform
|
||||
|
||||
fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> ()
|
||||
fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> ()
|
||||
yields ()
|
||||
{
|
||||
let mut _0: ();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Basic block and local names can safely change, but the StorageDead statements
|
||||
// should not go away.
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
struct Foo(i32);
|
||||
|
||||
|
@ -20,7 +20,8 @@ fn take<T>(_x: T) {}
|
|||
|
||||
// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
|
||||
fn main() {
|
||||
let _gen = || {
|
||||
let _gen = #[coroutine]
|
||||
|| {
|
||||
let a = Foo(5);
|
||||
let b = Bar(6);
|
||||
yield;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
_0: CoroutineSavedTy {
|
||||
ty: HasDrop,
|
||||
source_info: SourceInfo {
|
||||
span: $DIR/coroutine_tiny.rs:21:13: 21:15 (#0),
|
||||
span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
|
||||
scope: scope[0],
|
||||
},
|
||||
ignore_for_traits: false,
|
||||
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
} */
|
||||
|
||||
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}>, _2: u8) -> CoroutineState<(), ()> {
|
||||
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
|
||||
debug _x => _10;
|
||||
let mut _0: std::ops::CoroutineState<(), ()>;
|
||||
let _3: HasDrop;
|
||||
|
@ -34,18 +34,18 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24
|
|||
let _10: u8;
|
||||
let mut _11: u32;
|
||||
scope 1 {
|
||||
debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop);
|
||||
debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop);
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})));
|
||||
_11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
|
||||
switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_10 = move _2;
|
||||
nop;
|
||||
(((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop) = HasDrop;
|
||||
(((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop;
|
||||
StorageLive(_4);
|
||||
goto -> bb2;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24
|
|||
StorageDead(_4);
|
||||
StorageDead(_6);
|
||||
StorageDead(_7);
|
||||
discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))) = 3;
|
||||
discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))) = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//@ compile-flags: -C panic=abort
|
||||
//@ no-prefer-dynamic
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
struct HasDrop;
|
||||
|
||||
|
@ -17,7 +17,8 @@ fn callee() {}
|
|||
|
||||
// EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir
|
||||
fn main() {
|
||||
let _gen = |_x: u8| {
|
||||
let _gen = #[coroutine]
|
||||
|_x: u8| {
|
||||
let _d = HasDrop;
|
||||
loop {
|
||||
yield;
|
||||
|
|
|
@ -4,24 +4,24 @@
|
|||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let _1: std::ops::CoroutineState<i32, bool>;
|
||||
let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>;
|
||||
let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>;
|
||||
let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
+ let mut _5: bool;
|
||||
scope 1 {
|
||||
debug _r => _1;
|
||||
}
|
||||
+ scope 2 (inlined g) {
|
||||
+ }
|
||||
+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) {
|
||||
+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
|
||||
+ debug pointer => _3;
|
||||
+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) {
|
||||
+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
|
||||
+ debug pointer => _3;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 5 (inlined g::{closure#0}) {
|
||||
+ debug a => _5;
|
||||
+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
+ let mut _7: u32;
|
||||
+ let mut _8: i32;
|
||||
+ }
|
||||
|
@ -32,22 +32,22 @@
|
|||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
- _4 = g() -> [return: bb1, unwind unreachable];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
+ StorageLive(_6);
|
||||
+ StorageLive(_7);
|
||||
+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8});
|
||||
+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8});
|
||||
+ _7 = discriminant((*_6));
|
||||
+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _3 = &mut _4;
|
||||
- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind unreachable];
|
||||
- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind unreachable];
|
||||
+ StorageDead(_4);
|
||||
+ _0 = const ();
|
||||
+ StorageDead(_1);
|
||||
|
@ -56,7 +56,7 @@
|
|||
|
||||
bb2: {
|
||||
- StorageDead(_3);
|
||||
- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
|
||||
- _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind unreachable];
|
||||
+ StorageDead(_7);
|
||||
+ StorageDead(_6);
|
||||
+ StorageDead(_5);
|
||||
|
|
|
@ -4,24 +4,24 @@
|
|||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let _1: std::ops::CoroutineState<i32, bool>;
|
||||
let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>;
|
||||
let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>;
|
||||
let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
+ let mut _5: bool;
|
||||
scope 1 {
|
||||
debug _r => _1;
|
||||
}
|
||||
+ scope 2 (inlined g) {
|
||||
+ }
|
||||
+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) {
|
||||
+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
|
||||
+ debug pointer => _3;
|
||||
+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) {
|
||||
+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
|
||||
+ debug pointer => _3;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 5 (inlined g::{closure#0}) {
|
||||
+ debug a => _5;
|
||||
+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
|
||||
+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8};
|
||||
+ let mut _7: u32;
|
||||
+ let mut _8: i32;
|
||||
+ }
|
||||
|
@ -32,22 +32,22 @@
|
|||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
- _4 = g() -> [return: bb1, unwind continue];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
+ StorageLive(_6);
|
||||
+ StorageLive(_7);
|
||||
+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8});
|
||||
+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8});
|
||||
+ _7 = discriminant((*_6));
|
||||
+ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _3 = &mut _4;
|
||||
- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5];
|
||||
- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind: bb5];
|
||||
+ StorageDead(_4);
|
||||
+ _0 = const ();
|
||||
+ StorageDead(_1);
|
||||
|
@ -56,7 +56,7 @@
|
|||
|
||||
- bb2: {
|
||||
- StorageDead(_3);
|
||||
- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
|
||||
- _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
|
||||
+ bb2 (cleanup): {
|
||||
+ drop(_4) -> [return: bb3, unwind terminate(cleanup)];
|
||||
}
|
||||
|
|
|
@ -16,5 +16,6 @@ fn main() {
|
|||
#[inline]
|
||||
pub fn g() -> impl Coroutine<bool> {
|
||||
#[inline]
|
||||
|a| { yield if a { 7 } else { 13 } }
|
||||
#[coroutine]
|
||||
|a| yield if a { 7 } else { 13 }
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/async-outside-of-await-issue-121096.rs:7:7
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
...
|
||||
LL | }.await
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
|
|
@ -141,7 +141,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/incorrect-syntax-suggestions.rs:68:19
|
||||
|
|
||||
LL | fn foo13() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
| ---------------------------- this is not `async`
|
||||
LL | let _ = bar().await();
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
@ -149,7 +149,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/incorrect-syntax-suggestions.rs:73:19
|
||||
|
|
||||
LL | fn foo14() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
| ---------------------------- this is not `async`
|
||||
LL | let _ = bar().await()?;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
@ -157,7 +157,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/incorrect-syntax-suggestions.rs:78:19
|
||||
|
|
||||
LL | fn foo15() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
| ---------------------------- this is not `async`
|
||||
LL | let _ = bar().await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
@ -165,7 +165,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/incorrect-syntax-suggestions.rs:82:19
|
||||
|
|
||||
LL | fn foo16() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
| ---------------------------- this is not `async`
|
||||
LL | let _ = bar().await?;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
@ -173,7 +173,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/incorrect-syntax-suggestions.rs:87:23
|
||||
|
|
||||
LL | fn foo() -> Result<(), ()> {
|
||||
| --- this is not `async`
|
||||
| -------------------------- this is not `async`
|
||||
LL | let _ = bar().await?;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//@ edition:2018
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::future::Future;
|
||||
use std::ops::Coroutine;
|
||||
|
@ -9,6 +9,7 @@ fn returns_async_block() -> impl Future<Output = ()> {
|
|||
async {}
|
||||
}
|
||||
fn returns_coroutine() -> impl Coroutine<(), Yield = (), Return = ()> {
|
||||
#[coroutine]
|
||||
|| {
|
||||
let _: () = yield ();
|
||||
}
|
||||
|
@ -23,9 +24,12 @@ fn main() {
|
|||
takes_future(returns_async_block());
|
||||
takes_future(async {});
|
||||
takes_coroutine(returns_coroutine());
|
||||
takes_coroutine(|| {
|
||||
let _: () = yield ();
|
||||
});
|
||||
takes_coroutine(
|
||||
#[coroutine]
|
||||
|| {
|
||||
let _: () = yield ();
|
||||
},
|
||||
);
|
||||
|
||||
// async futures are not coroutines:
|
||||
takes_coroutine(async_fn());
|
||||
|
@ -38,8 +42,11 @@ fn main() {
|
|||
// coroutines are not futures:
|
||||
takes_future(returns_coroutine());
|
||||
//~^ ERROR is not a future
|
||||
takes_future(|ctx| {
|
||||
//~^ ERROR is not a future
|
||||
ctx = yield ();
|
||||
});
|
||||
takes_future(
|
||||
#[coroutine]
|
||||
|ctx| {
|
||||
//~^ ERROR is not a future
|
||||
ctx = yield ();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:31:21
|
||||
--> $DIR/coroutine-not-future.rs:35:21
|
||||
|
|
||||
LL | takes_coroutine(async_fn());
|
||||
| --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
|
||||
|
@ -7,13 +7,13 @@ LL | takes_coroutine(async_fn());
|
|||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:18:39
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: the trait bound `impl Future<Output = ()>: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:33:21
|
||||
--> $DIR/coroutine-not-future.rs:37:21
|
||||
|
|
||||
LL | takes_coroutine(returns_async_block());
|
||||
| --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future<Output = ()>`
|
||||
|
@ -21,27 +21,27 @@ LL | takes_coroutine(returns_async_block());
|
|||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:18:39
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:35:21: 35:29}: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:35:21
|
||||
error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}: Coroutine<_>` is not satisfied
|
||||
--> $DIR/coroutine-not-future.rs:39:21
|
||||
|
|
||||
LL | takes_coroutine(async {});
|
||||
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:35:21: 35:29}`
|
||||
| --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `takes_coroutine`
|
||||
--> $DIR/coroutine-not-future.rs:18:39
|
||||
--> $DIR/coroutine-not-future.rs:19:39
|
||||
|
|
||||
LL | fn takes_coroutine<ResumeTy>(_g: impl Coroutine<ResumeTy, Yield = (), Return = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine`
|
||||
|
||||
error[E0277]: `impl Coroutine<Yield = (), Return = ()>` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:39:18
|
||||
--> $DIR/coroutine-not-future.rs:43:18
|
||||
|
|
||||
LL | takes_future(returns_coroutine());
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine<Yield = (), Return = ()>` is not a future
|
||||
|
@ -50,26 +50,26 @@ LL | takes_future(returns_coroutine());
|
|||
|
|
||||
= help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/coroutine-not-future.rs:17:26
|
||||
--> $DIR/coroutine-not-future.rs:18:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
||||
error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:41:18
|
||||
error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
|
||||
--> $DIR/coroutine-not-future.rs:47:9
|
||||
|
|
||||
LL | takes_future(|ctx| {
|
||||
| _____------------_^
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | takes_future(
|
||||
| ------------ required by a bound introduced by this call
|
||||
LL | #[coroutine]
|
||||
LL | / |ctx| {
|
||||
LL | |
|
||||
LL | | ctx = yield ();
|
||||
LL | | });
|
||||
| |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
|
||||
LL | | ctx = yield ();
|
||||
LL | | },
|
||||
| |_________^ `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}`
|
||||
= help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}`
|
||||
note: required by a bound in `takes_future`
|
||||
--> $DIR/coroutine-not-future.rs:17:26
|
||||
--> $DIR/coroutine-not-future.rs:18:26
|
||||
|
|
||||
LL | fn takes_future(_f: impl Future<Output = ()>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future`
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/issue-51751.rs:9:27
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
LL | let result = inc(10000);
|
||||
LL | let finished = result.await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/issue-62009-1.rs:6:23
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
LL | async { let (); }.await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
@ -10,7 +10,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/issue-62009-1.rs:10:7
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
...
|
||||
LL | }.await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
@ -19,7 +19,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/issue-62009-1.rs:12:16
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
...
|
||||
LL | (|_| 2333).await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/issue-62009-2.rs:8:23
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
LL | (async || 2333)().await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
|
|
|
@ -6,15 +6,13 @@
|
|||
//@ error-pattern:coroutine resumed after completion
|
||||
//@ edition:2018
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::{
|
||||
ops::Coroutine,
|
||||
pin::Pin,
|
||||
};
|
||||
use std::{ops::Coroutine, pin::Pin};
|
||||
|
||||
fn main() {
|
||||
let mut g = || {
|
||||
let mut g = #[coroutine]
|
||||
|| {
|
||||
yield;
|
||||
};
|
||||
Pin::new(&mut g).resume(()); // Yields once.
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|||
--> $DIR/non-async-enclosing-span.rs:9:28
|
||||
|
|
||||
LL | fn main() {
|
||||
| ---- this is not `async`
|
||||
| --------- this is not `async`
|
||||
LL | let x = move || {};
|
||||
LL | let y = do_the_thing().await;
|
||||
| ^^^^^ only allowed inside `async` functions and blocks
|
||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
|||
}
|
||||
|
||||
fn foo() {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
yield drop(Config {
|
||||
nickname: NonCopy,
|
||||
b: NonCopy2,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
type OpaqueCoroutine = impl Sized;
|
||||
fn defining_use() -> OpaqueCoroutine {
|
||||
#[coroutine]
|
||||
|| {
|
||||
for i in 0..10 {
|
||||
yield i;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
|
||||
--> $DIR/coherence-with-coroutine.rs:21:1
|
||||
--> $DIR/coherence-with-coroutine.rs:22:1
|
||||
|
|
||||
LL | impl Trait for Wrapper<OpaqueCoroutine> {}
|
||||
| --------------------------------------- first implementation here
|
||||
|
|
|
@ -5,21 +5,21 @@
|
|||
// is being used), we were failing to account for all types that might
|
||||
// possibly be live across a yield point.
|
||||
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
fn foo() {
|
||||
let _x = static || {
|
||||
let _x = #[coroutine] static || {
|
||||
let mut s = String::new();
|
||||
s += { yield; "" };
|
||||
};
|
||||
|
||||
let _y = static || {
|
||||
let _y = #[coroutine] static || {
|
||||
let x = &mut 0;
|
||||
*{ yield; x } += match String::new() { _ => 0 };
|
||||
};
|
||||
|
||||
// Please don't ever actually write something like this
|
||||
let _z = static || {
|
||||
let _z = #[coroutine] static || {
|
||||
let x = &mut 0;
|
||||
*{
|
||||
let inner = &mut 1;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
#![feature(auto_traits)]
|
||||
#![feature(negative_impls)]
|
||||
|
||||
|
@ -23,7 +23,7 @@ fn assert_foo<T: Foo>(f: T) {}
|
|||
fn main() {
|
||||
// Make sure 'static is erased for coroutine interiors so we can't match it in trait selection
|
||||
let x: &'static _ = &OnlyFooIfStaticRef(No);
|
||||
let gen = move || {
|
||||
let gen = #[coroutine] move || {
|
||||
let x = x;
|
||||
yield;
|
||||
assert_foo(x);
|
||||
|
@ -33,7 +33,7 @@ fn main() {
|
|||
|
||||
// Allow impls which matches any lifetime
|
||||
let x = &OnlyFooIfRef(No);
|
||||
let gen = move || {
|
||||
let gen = #[coroutine] move || {
|
||||
let x = x;
|
||||
yield;
|
||||
assert_foo(x);
|
||||
|
@ -41,7 +41,7 @@ fn main() {
|
|||
assert_foo(gen); // ok
|
||||
|
||||
// Disallow impls which relates lifetimes in the coroutine interior
|
||||
let gen = move || {
|
||||
let gen = #[coroutine] move || {
|
||||
let a = A(&mut true, &mut true, No);
|
||||
//~^ temporary value dropped while borrowed
|
||||
//~| temporary value dropped while borrowed
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::marker::Unpin;
|
|||
use std::ops::Coroutine;
|
||||
|
||||
pub fn g() -> impl Coroutine<(), Yield = (), Return = ()> {
|
||||
#[coroutine]
|
||||
|| {
|
||||
yield;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
//@ no-prefer-dynamic
|
||||
//@ edition:2021
|
||||
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
pub fn run<T>(a: T) {
|
||||
let _ = move || {
|
||||
let _ = #[coroutine]
|
||||
move || {
|
||||
drop(a);
|
||||
yield;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@ fn msg() -> u32 {
|
|||
}
|
||||
|
||||
pub fn foo() -> impl Coroutine<(), Yield = (), Return = u32> {
|
||||
#[coroutine]
|
||||
|| {
|
||||
yield;
|
||||
return msg();
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::ops::Coroutine;
|
||||
|
||||
pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
|
||||
#[coroutine]
|
||||
|| {
|
||||
if false {
|
||||
yield;
|
||||
|
@ -12,7 +13,10 @@ pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
|
|||
}
|
||||
|
||||
pub fn bar<T: 'static>(t: T) -> Box<Coroutine<(), Yield = T, Return = ()> + Unpin> {
|
||||
Box::new(|| {
|
||||
yield t;
|
||||
})
|
||||
Box::new(
|
||||
#[coroutine]
|
||||
|| {
|
||||
yield t;
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let _a = || {
|
||||
let _a = #[coroutine] || {
|
||||
yield;
|
||||
let a = String::new();
|
||||
a.len()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
use std::pin::Pin;
|
||||
|
@ -6,13 +6,13 @@ use std::pin::Pin;
|
|||
fn main() {
|
||||
let _b = {
|
||||
let a = 3;
|
||||
Pin::new(&mut || yield &a).resume(())
|
||||
Pin::new(&mut #[coroutine] || yield &a).resume(())
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
};
|
||||
|
||||
let _b = {
|
||||
let a = 3;
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
yield &a
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/borrowing.rs:9:33
|
||||
--> $DIR/borrowing.rs:9:46
|
||||
|
|
||||
LL | let _b = {
|
||||
| -- borrow later stored here
|
||||
LL | let a = 3;
|
||||
LL | Pin::new(&mut || yield &a).resume(())
|
||||
| -- ^ borrowed value does not live long enough
|
||||
| |
|
||||
| value captured here by coroutine
|
||||
LL | Pin::new(&mut #[coroutine] || yield &a).resume(())
|
||||
| -- ^ borrowed value does not live long enough
|
||||
| |
|
||||
| value captured here by coroutine
|
||||
LL |
|
||||
LL | };
|
||||
| - `a` dropped here while still borrowed
|
||||
|
@ -18,8 +18,8 @@ error[E0597]: `a` does not live long enough
|
|||
LL | let _b = {
|
||||
| -- borrow later stored here
|
||||
LL | let a = 3;
|
||||
LL | || {
|
||||
| -- value captured here by coroutine
|
||||
LL | #[coroutine] || {
|
||||
| -- value captured here by coroutine
|
||||
LL | yield &a
|
||||
| ^ borrowed value does not live long enough
|
||||
...
|
||||
|
|
|
@ -7,27 +7,27 @@ struct Contravariant<'a>(fn(&'a ()));
|
|||
struct Covariant<'a>(fn() -> &'a ());
|
||||
|
||||
fn bad1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'short>> {
|
||||
|_: Covariant<'short>| {
|
||||
#[coroutine] |_: Covariant<'short>| {
|
||||
let a: Covariant<'long> = yield ();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn bad2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'long>> {
|
||||
|_: Contravariant<'long>| {
|
||||
#[coroutine] |_: Contravariant<'long>| {
|
||||
let a: Contravariant<'short> = yield ();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn good1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'long>> {
|
||||
|_: Covariant<'long>| {
|
||||
#[coroutine] |_: Covariant<'long>| {
|
||||
let a: Covariant<'short> = yield ();
|
||||
}
|
||||
}
|
||||
|
||||
fn good2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'short>> {
|
||||
|_: Contravariant<'short>| {
|
||||
#[coroutine] |_: Contravariant<'short>| {
|
||||
let a: Contravariant<'long> = yield ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@ LL | fn bad1<'short, 'long: 'short>() -> impl Coroutine<Covariant<'short>> {
|
|||
| ------ ----- lifetime `'long` defined here
|
||||
| |
|
||||
| lifetime `'short` defined here
|
||||
LL | |_: Covariant<'short>| {
|
||||
LL | #[coroutine] |_: Covariant<'short>| {
|
||||
LL | let a: Covariant<'long> = yield ();
|
||||
| ^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long`
|
||||
|
|
||||
= help: consider adding the following bound: `'short: 'long`
|
||||
help: consider adding 'move' keyword before the nested closure
|
||||
|
|
||||
LL | move |_: Covariant<'short>| {
|
||||
| ++++
|
||||
LL | #[coroutine] move |_: Covariant<'short>| {
|
||||
| ++++
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/check-resume-ty-lifetimes-2.rs:18:40
|
||||
|
@ -22,15 +22,15 @@ LL | fn bad2<'short, 'long: 'short>() -> impl Coroutine<Contravariant<'long>> {
|
|||
| ------ ----- lifetime `'long` defined here
|
||||
| |
|
||||
| lifetime `'short` defined here
|
||||
LL | |_: Contravariant<'long>| {
|
||||
LL | #[coroutine] |_: Contravariant<'long>| {
|
||||
LL | let a: Contravariant<'short> = yield ();
|
||||
| ^^^^^^^^ yielding this value requires that `'short` must outlive `'long`
|
||||
|
|
||||
= help: consider adding the following bound: `'short: 'long`
|
||||
help: consider adding 'move' keyword before the nested closure
|
||||
|
|
||||
LL | move |_: Contravariant<'long>| {
|
||||
| ++++
|
||||
LL | #[coroutine] move |_: Contravariant<'long>| {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![feature(coroutine_trait)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
#![allow(unused)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
|
@ -9,11 +9,14 @@ use std::pin::pin;
|
|||
fn mk_static(s: &str) -> &'static str {
|
||||
let mut storage: Option<&'static str> = None;
|
||||
|
||||
let mut coroutine = pin!(|_: &str| {
|
||||
let x: &'static str = yield ();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
storage = Some(x);
|
||||
});
|
||||
let mut coroutine = pin!(
|
||||
#[coroutine]
|
||||
|_: &str| {
|
||||
let x: &'static str = yield ();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
storage = Some(x);
|
||||
}
|
||||
);
|
||||
|
||||
coroutine.as_mut().resume(s);
|
||||
coroutine.as_mut().resume(s);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/check-resume-ty-lifetimes.rs:13:16
|
||||
--> $DIR/check-resume-ty-lifetimes.rs:15:20
|
||||
|
|
||||
LL | fn mk_static(s: &str) -> &'static str {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
...
|
||||
LL | let x: &'static str = yield ();
|
||||
| ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
|
||||
LL | let x: &'static str = yield ();
|
||||
| ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// gate-test-coroutine_clone
|
||||
// Verifies that static coroutines cannot be cloned/copied.
|
||||
|
||||
#![feature(coroutines, coroutine_clone)]
|
||||
#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let gen = static move || {
|
||||
let gen = #[coroutine]
|
||||
static move || {
|
||||
yield;
|
||||
};
|
||||
check_copy(&gen);
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Copy` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:10:16
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Copy` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:11:16
|
||||
|
|
||||
LL | check_copy(&gen);
|
||||
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
|
||||
| ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl-static.rs:16:18
|
||||
--> $DIR/clone-impl-static.rs:17:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Clone` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:12:17
|
||||
error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Clone` is not satisfied
|
||||
--> $DIR/clone-impl-static.rs:13:17
|
||||
|
|
||||
LL | check_clone(&gen);
|
||||
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}`
|
||||
| ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check_clone`
|
||||
--> $DIR/clone-impl-static.rs:17:19
|
||||
--> $DIR/clone-impl-static.rs:18:19
|
||||
|
|
||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||
| ^^^^^ required by this bound in `check_clone`
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
// Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held
|
||||
// across awaits can be cloned/copied.
|
||||
|
||||
#![feature(coroutines, coroutine_clone)]
|
||||
#![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
|
||||
|
||||
struct NonClone;
|
||||
|
||||
fn test1() {
|
||||
let copyable: u32 = 123;
|
||||
let gen_copy_0 = move || {
|
||||
let gen_copy_0 = #[coroutine]
|
||||
move || {
|
||||
yield;
|
||||
drop(copyable);
|
||||
};
|
||||
|
@ -18,7 +19,8 @@ fn test1() {
|
|||
|
||||
fn test2() {
|
||||
let copyable: u32 = 123;
|
||||
let gen_copy_1 = move || {
|
||||
let gen_copy_1 = #[coroutine]
|
||||
move || {
|
||||
/*
|
||||
let v = vec!['a'];
|
||||
let n = NonClone;
|
||||
|
@ -37,7 +39,8 @@ fn test2() {
|
|||
|
||||
fn test3() {
|
||||
let clonable_0: Vec<u32> = Vec::new();
|
||||
let gen_clone_0 = move || {
|
||||
let gen_clone_0 = #[coroutine]
|
||||
move || {
|
||||
let v = vec!['a'];
|
||||
yield;
|
||||
drop(v);
|
||||
|
@ -51,7 +54,8 @@ fn test3() {
|
|||
|
||||
fn test4() {
|
||||
let clonable_1: Vec<u32> = Vec::new();
|
||||
let gen_clone_1 = move || {
|
||||
let gen_clone_1 = #[coroutine]
|
||||
move || {
|
||||
let v = vec!['a'];
|
||||
/*
|
||||
let n = NonClone;
|
||||
|
@ -71,7 +75,8 @@ fn test4() {
|
|||
|
||||
fn test5() {
|
||||
let non_clonable: NonClone = NonClone;
|
||||
let gen_non_clone = move || {
|
||||
let gen_non_clone = #[coroutine]
|
||||
move || {
|
||||
yield;
|
||||
drop(non_clonable);
|
||||
};
|
||||
|
|
|
@ -1,76 +1,76 @@
|
|||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
|
||||
--> $DIR/clone-impl.rs:46:5
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
--> $DIR/clone-impl.rs:49:5
|
||||
|
|
||||
LL | let gen_clone_0 = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:44:14
|
||||
--> $DIR/clone-impl.rs:47:14
|
||||
|
|
||||
LL | drop(clonable_0);
|
||||
| ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:84:18
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
|
||||
--> $DIR/clone-impl.rs:46:5
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
--> $DIR/clone-impl.rs:49:5
|
||||
|
|
||||
LL | let gen_clone_0 = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy`
|
||||
|
|
||||
note: coroutine does not implement `Copy` as this value is used across a yield
|
||||
--> $DIR/clone-impl.rs:42:9
|
||||
--> $DIR/clone-impl.rs:45:9
|
||||
|
|
||||
LL | let v = vec!['a'];
|
||||
| - has type `Vec<char>` which does not implement `Copy`
|
||||
LL | yield;
|
||||
| ^^^^^ yield occurs here, with `v` maybe used later
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:84:18
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
|
||||
--> $DIR/clone-impl.rs:66:5
|
||||
error[E0277]: the trait bound `Vec<u32>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
--> $DIR/clone-impl.rs:70:5
|
||||
|
|
||||
LL | let gen_clone_1 = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<u32>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:64:14
|
||||
--> $DIR/clone-impl.rs:68:14
|
||||
|
|
||||
LL | drop(clonable_1);
|
||||
| ^^^^^^^^^^ has type `Vec<u32>` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:84:18
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
|
||||
--> $DIR/clone-impl.rs:66:5
|
||||
error[E0277]: the trait bound `Vec<char>: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
--> $DIR/clone-impl.rs:70:5
|
||||
|
|
||||
LL | let gen_clone_1 = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`
|
||||
...
|
||||
LL | check_copy(&gen_clone_1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec<char>`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy`
|
||||
|
|
||||
note: coroutine does not implement `Copy` as this value is used across a yield
|
||||
--> $DIR/clone-impl.rs:60:9
|
||||
--> $DIR/clone-impl.rs:64:9
|
||||
|
|
||||
LL | let v = vec!['a'];
|
||||
| - has type `Vec<char>` which does not implement `Copy`
|
||||
|
@ -78,27 +78,27 @@ LL | let v = vec!['a'];
|
|||
LL | yield;
|
||||
| ^^^^^ yield occurs here, with `v` maybe used later
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:84:18
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
||||
error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
|
||||
--> $DIR/clone-impl.rs:78:5
|
||||
error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
--> $DIR/clone-impl.rs:83:5
|
||||
|
|
||||
LL | let gen_non_clone = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
...
|
||||
LL | check_copy(&gen_non_clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Copy`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Copy`
|
||||
|
|
||||
note: captured value does not implement `Copy`
|
||||
--> $DIR/clone-impl.rs:76:14
|
||||
--> $DIR/clone-impl.rs:81:14
|
||||
|
|
||||
LL | drop(non_clonable);
|
||||
| ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy`
|
||||
note: required by a bound in `check_copy`
|
||||
--> $DIR/clone-impl.rs:84:18
|
||||
--> $DIR/clone-impl.rs:89:18
|
||||
|
|
||||
LL | fn check_copy<T: Copy>(_x: &T) {}
|
||||
| ^^^^ required by this bound in `check_copy`
|
||||
|
@ -108,22 +108,22 @@ LL + #[derive(Copy)]
|
|||
LL | struct NonClone;
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
|
||||
--> $DIR/clone-impl.rs:80:5
|
||||
error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
--> $DIR/clone-impl.rs:85:5
|
||||
|
|
||||
LL | let gen_non_clone = move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`
|
||||
LL | move || {
|
||||
| ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`
|
||||
...
|
||||
LL | check_clone(&gen_non_clone);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Clone`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Clone`
|
||||
|
|
||||
note: captured value does not implement `Clone`
|
||||
--> $DIR/clone-impl.rs:76:14
|
||||
--> $DIR/clone-impl.rs:81:14
|
||||
|
|
||||
LL | drop(non_clonable);
|
||||
| ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone`
|
||||
note: required by a bound in `check_clone`
|
||||
--> $DIR/clone-impl.rs:85:19
|
||||
--> $DIR/clone-impl.rs:90:19
|
||||
|
|
||||
LL | fn check_clone<T: Clone>(_x: &T) {}
|
||||
| ^^^^^ required by this bound in `check_clone`
|
||||
|
|
|
@ -5,32 +5,32 @@ LL | pub fn foo<'a, 'b>() -> impl Clone {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires coroutine witness types for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires match-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:14:5
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// witness types, which we don't know until after borrowck. When we later check
|
||||
// the goal for correctness, we want to be able to bind the `impl Clone` opaque.
|
||||
pub fn foo<'a, 'b>() -> impl Clone {
|
||||
#[coroutine]
|
||||
move |_: ()| {
|
||||
let () = yield ();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//@ revisions: default nomiropt
|
||||
//@[nomiropt]compile-flags: -Z mir-opt-level=0
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::Coroutine;
|
||||
use std::pin::Pin;
|
||||
|
@ -29,7 +29,7 @@ fn main() {
|
|||
}
|
||||
|
||||
fn t1() {
|
||||
let mut a = || {
|
||||
let mut a = #[coroutine] || {
|
||||
let b = B;
|
||||
if test() {
|
||||
drop(b);
|
||||
|
@ -45,7 +45,7 @@ fn t1() {
|
|||
}
|
||||
|
||||
fn t2() {
|
||||
let mut a = || {
|
||||
let mut a = #[coroutine] || {
|
||||
let b = B;
|
||||
if test2() {
|
||||
drop(b);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//@ revisions: default nomiropt
|
||||
//@[nomiropt]compile-flags: -Z mir-opt-level=0
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::{CoroutineState, Coroutine};
|
||||
use std::pin::Pin;
|
||||
|
@ -24,25 +24,25 @@ fn finish<T>(mut amt: usize, mut t: T) -> T::Return
|
|||
}
|
||||
|
||||
fn main() {
|
||||
finish(1, || yield);
|
||||
finish(8, || {
|
||||
finish(1, #[coroutine] || yield);
|
||||
finish(8, #[coroutine] || {
|
||||
for _ in 0..8 {
|
||||
yield;
|
||||
}
|
||||
});
|
||||
finish(1, || {
|
||||
finish(1, #[coroutine] || {
|
||||
if true {
|
||||
yield;
|
||||
} else {
|
||||
}
|
||||
});
|
||||
finish(1, || {
|
||||
finish(1, #[coroutine] || {
|
||||
if false {
|
||||
} else {
|
||||
yield;
|
||||
}
|
||||
});
|
||||
finish(2, || {
|
||||
finish(2, #[coroutine] || {
|
||||
if { yield; false } {
|
||||
yield;
|
||||
panic!()
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
||||
fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||
let mut g = || {
|
||||
let mut g = #[coroutine] || {
|
||||
yield;
|
||||
x
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// Test that we get the correct message for resuming a panicked coroutine.
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::{
|
||||
ops::Coroutine,
|
||||
|
@ -14,7 +14,7 @@ use std::{
|
|||
};
|
||||
|
||||
fn main() {
|
||||
let mut g = || {
|
||||
let mut g = #[coroutine] || {
|
||||
panic!();
|
||||
yield;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(coroutines)]
|
||||
|
||||
fn main() {
|
||||
#[coroutine]
|
||||
|| {
|
||||
// The reference in `_a` is a Legal with NLL since it ends before the yield
|
||||
let _a = &mut true;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0626]: borrow may still be in use when coroutine yields
|
||||
--> $DIR/coroutine-with-nll.rs:7:17
|
||||
--> $DIR/coroutine-with-nll.rs:8:17
|
||||
|
|
||||
LL | let b = &mut true;
|
||||
| ^^^^^^^^^
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![feature(coroutine_trait)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
// Test that we cannot create a coroutine that returns a value of its
|
||||
// own type.
|
||||
|
@ -12,7 +12,7 @@ pub fn want_cyclic_coroutine_return<T>(_: T)
|
|||
}
|
||||
|
||||
fn supply_cyclic_coroutine_return() {
|
||||
want_cyclic_coroutine_return(|| {
|
||||
want_cyclic_coroutine_return(#[coroutine] || {
|
||||
//~^ ERROR type mismatch
|
||||
if false { yield None.unwrap(); }
|
||||
None.unwrap()
|
||||
|
@ -25,7 +25,7 @@ pub fn want_cyclic_coroutine_yield<T>(_: T)
|
|||
}
|
||||
|
||||
fn supply_cyclic_coroutine_yield() {
|
||||
want_cyclic_coroutine_yield(|| {
|
||||
want_cyclic_coroutine_yield(#[coroutine] || {
|
||||
//~^ ERROR type mismatch
|
||||
if false { yield None.unwrap(); }
|
||||
None.unwrap()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36}`
|
||||
--> $DIR/coroutine-yielding-or-returning-itself.rs:15:34
|
||||
error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49}`
|
||||
--> $DIR/coroutine-yielding-or-returning-itself.rs:15:47
|
||||
|
|
||||
LL | want_cyclic_coroutine_return(|| {
|
||||
| _____----------------------------_^
|
||||
LL | want_cyclic_coroutine_return(#[coroutine] || {
|
||||
| _____----------------------------______________^
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | |
|
||||
|
@ -23,11 +23,11 @@ LL | pub fn want_cyclic_coroutine_return<T>(_: T)
|
|||
LL | where T: Coroutine<Yield = (), Return = T>
|
||||
| ^^^^^^^^^^ required by this bound in `want_cyclic_coroutine_return`
|
||||
|
||||
error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35}`
|
||||
--> $DIR/coroutine-yielding-or-returning-itself.rs:28:33
|
||||
error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48}`
|
||||
--> $DIR/coroutine-yielding-or-returning-itself.rs:28:46
|
||||
|
|
||||
LL | want_cyclic_coroutine_yield(|| {
|
||||
| _____---------------------------_^
|
||||
LL | want_cyclic_coroutine_yield(#[coroutine] || {
|
||||
| _____---------------------------______________^
|
||||
| | |
|
||||
| | required by a bound introduced by this call
|
||||
LL | |
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//@ build-pass
|
||||
|
||||
//! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR
|
||||
#![feature(coroutines)]
|
||||
#![feature(coroutines, stmt_expr_attributes)]
|
||||
|
||||
fn assert_send<T: Send>(_thing: T) {}
|
||||
|
||||
|
@ -9,8 +9,8 @@ fn assert_send<T: Send>(_thing: T) {}
|
|||
pub struct Client { pub nickname: String }
|
||||
|
||||
fn main() {
|
||||
let g = move || match drop(Client { ..Client::default() }) {
|
||||
_status => yield,
|
||||
};
|
||||
let g = #[coroutine] move || match drop(Client { ..Client::default() }) {
|
||||
_status => yield,
|
||||
};
|
||||
assert_send(g);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ fn cycle(
|
|||
fn main() {
|
||||
// Has only one invalid discr. value.
|
||||
let gen_u8_tiny_niche = || {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
// 3 reserved variants
|
||||
|
||||
yield250!(); // 253 variants
|
||||
|
@ -98,7 +98,7 @@ fn main() {
|
|||
|
||||
// Uses all values in the u8 discriminant.
|
||||
let gen_u8_full = || {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
// 3 reserved variants
|
||||
|
||||
yield250!(); // 253 variants
|
||||
|
@ -111,7 +111,7 @@ fn main() {
|
|||
|
||||
// Barely needs a u16 discriminant.
|
||||
let gen_u16 = || {
|
||||
|| {
|
||||
#[coroutine] || {
|
||||
// 3 reserved variants
|
||||
|
||||
yield250!(); // 253 variants
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// #60187, this produced incorrect code for coroutines when a saved local was
|
||||
// re-assigned.
|
||||
|
||||
#![feature(coroutines, coroutine_trait)]
|
||||
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
use std::ops::{Coroutine, CoroutineState};
|
||||
use std::pin::Pin;
|
||||
|
@ -17,7 +17,8 @@ impl Drop for Foo {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let mut a = || {
|
||||
let mut a = #[coroutine]
|
||||
|| {
|
||||
let mut x = Foo(4);
|
||||
yield;
|
||||
assert_eq!(x.0, 4);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// and also that values that are dropped along all paths to a yield do not get
|
||||
// included in the coroutine type.
|
||||
|
||||
#![feature(coroutines, negative_impls)]
|
||||
#![feature(coroutines, negative_impls, stmt_expr_attributes)]
|
||||
#![allow(unused_assignments, dead_code)]
|
||||
|
||||
struct Ptr;
|
||||
|
@ -19,7 +19,7 @@ fn assert_send<T: Send>(_: T) {}
|
|||
|
||||
// This test case is reduced from tests/ui/drop/dynamic-drop-async.rs
|
||||
fn one_armed_if(arg: bool) {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let arr = [Ptr];
|
||||
if arg {
|
||||
drop(arr);
|
||||
|
@ -29,7 +29,7 @@ fn one_armed_if(arg: bool) {
|
|||
}
|
||||
|
||||
fn two_armed_if(arg: bool) {
|
||||
assert_send(|| {
|
||||
assert_send(#[coroutine] || {
|
||||
let arr = [Ptr];
|
||||
if arg {
|
||||
drop(arr);
|
||||
|
@ -41,7 +41,7 @@ fn two_armed_if(arg: bool) {
|
|||
}
|
||||
|
||||
fn if_let(arg: Option<i32>) {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let arr = [Ptr];
|
||||
if let Some(_) = arg {
|
||||
drop(arr);
|
||||
|
@ -51,7 +51,7 @@ fn if_let(arg: Option<i32>) {
|
|||
}
|
||||
|
||||
fn init_in_if(arg: bool) {
|
||||
assert_send(|| {
|
||||
assert_send(#[coroutine] || {
|
||||
let mut x = NonSend;
|
||||
drop(x);
|
||||
if arg {
|
||||
|
@ -63,7 +63,7 @@ fn init_in_if(arg: bool) {
|
|||
}
|
||||
|
||||
fn init_in_match_arm(arg: Option<i32>) {
|
||||
assert_send(|| {
|
||||
assert_send(#[coroutine] || {
|
||||
let mut x = NonSend;
|
||||
drop(x);
|
||||
match arg {
|
||||
|
@ -74,7 +74,7 @@ fn init_in_match_arm(arg: Option<i32>) {
|
|||
}
|
||||
|
||||
fn reinit() {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let mut arr = [Ptr];
|
||||
drop(arr);
|
||||
arr = [Ptr];
|
||||
|
@ -83,7 +83,7 @@ fn reinit() {
|
|||
}
|
||||
|
||||
fn loop_uninit() {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let mut arr = [Ptr];
|
||||
let mut count = 0;
|
||||
drop(arr);
|
||||
|
@ -96,7 +96,7 @@ fn loop_uninit() {
|
|||
}
|
||||
|
||||
fn nested_loop() {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let mut arr = [Ptr];
|
||||
let mut count = 0;
|
||||
drop(arr);
|
||||
|
@ -111,7 +111,7 @@ fn nested_loop() {
|
|||
}
|
||||
|
||||
fn loop_continue(b: bool) {
|
||||
let _ = || {
|
||||
let _ = #[coroutine] || {
|
||||
let mut arr = [Ptr];
|
||||
let mut count = 0;
|
||||
drop(arr);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue