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