Change:
suggested this is because when we lower the async function, we add `), whereas it should be parented as something outside of the impl trait context (as that is how such an expression would be parented, if it actually existing in the AST). I have a bit of code where I'd like to use a reference with a lifetime in an "async" function, which panics the compiler. I tried this code: I expected to see this happen: My understanding was that async functions are allowed to take references as parameters. helped to debug this a little bit and there is a suspicion that named lifetimes are somehow not properly propagated. I stumbled into this because I wanted to have 2 args with references, but if the lifetimes are elided the compiler asks for them to be . Adding them ICEs the compiler. Instead, this happened: I got a compiler panic. Backtrace:
suggested might be related
It would appear one can workaround this by using async blocks manually: I still need to test this does what I expect.
why do you need the immediately invoked closure there,
Yeah, just noticed. I think I also had some other issue / ICE, but I don't remember exactly what it was. Gonna have to check it again. Also, I don't think I knew that on blocks was a thing.
I didn't quite understand why I needed the move. I am trying to fix the original ICE, I think I got some time today tomorrow, hopefully, will make some progress. But compiler newbie, so might not work out.
You need to move to avoid the closure borrowing the references locally. It's the same situation as with I just removed all immeditaly invoked functions from eval :wink:
I am playing around with similar types of borrowing patterns, namely using StreamObj to carry a stream around inside of a struct. I can't seem to use the posted work-arounds: I am taking this working code and I'm refactoring it. Starts as: this works, compiles and runs. Then I try my hand at refactoring to move the stream out of the same scope as the await code pulling out values. Now I can get the same ICE as this ticket: ICE: full backtrace: Then I try some of your posted workarounds and they don't do the trick, here's my best try: but this fails to compile due to an ownership issue I can't figure out:
your final borrow error is because Fahrenheit while your contains a local stack borrow. You could try using  instead of Fahrenheit.
Alternatively to what suggested, you could move the code in to an async fn:

Discussion:
fn visit_async_fn( &mut self, id: NodeId, <del> async_node_id: NodeId, return_impl_trait_id: NodeId, </del> name: Name, span: Span, <del> visit_fn: impl FnOnce(&mut DefCollector<'a>) </del> <ins> header: &FnHeader, generics: &'a Generics, decl: &'a FnDecl, body: &'a Block, </ins> ) { <ins> let (closure_id, return_impl_trait_id) = match header.asyncness { IsAsync::Async { closure_id, return_impl_trait_id, } => (closure_id, return_impl_trait_id), _ => unreachable!(), }; </ins> // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span); return self.with_parent(fn_def, |this| { this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span); <del> let closure_def = this.create_def(async_node_id, </del> <ins> visit::walk_generics(this, generics); visit::walk_fn_decl(this, decl); let closure_def = this.create_def(closure_id, </ins> DefPathData::ClosureExpr, REGULAR_SPACE, span); <del> this.with_parent(closure_def, visit_fn) </del> <ins> this.with_parent(closure_def, |this| { visit::walk_block(this, body); }) </ins> }) }

ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } <del> ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async { closure_id, return_impl_trait_id, }, .. }, ..) => { </del> <ins> ItemKind::Fn( ref decl, ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, ref generics, ref body, ) => { </ins> return self.visit_async_fn( i.id, <del> closure_id, return_impl_trait_id, </del> i.ident.name, i.span, <del> |this| visit::walk_item(this, i) </del> <ins> header, generics, decl, body, </ins> ) } ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()),

fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(MethodSig { <del> header: FnHeader { asyncness: IsAsync::Async { closure_id, return_impl_trait_id, }, .. }, .. }, ..) => { </del> <ins> header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, ref decl, }, ref body) => { </ins> return self.visit_async_fn( ii.id, <del> closure_id, return_impl_trait_id, </del> ii.ident.name, ii.span, <del> |this| visit::walk_impl_item(this, ii) </del> <ins> header, &ii.generics, decl, body, </ins> ) } ImplItemKind::Method(..) | ImplItemKind::Const(..) =>

} } <ins> fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a { async move { await!(wake_and_yield_once()); *x } } </ins> fn async_nonmove_block(x: u8) -> impl Future<Output = u8> { async move { let future = async {

*x } <ins> async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { await!(wake_and_yield_once()); *x } fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a { async move { await!(wake_and_yield_once()); *x } } async fn async_fn_with_named_lifetime_multiple_args<'a>(x: &'a u8, _y: &'a u8) -> u8 { await!(wake_and_yield_once()); *x } </ins> fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> { async move { await!(async_fn_with_borrow(&y))

fn main() { macro_rules! test { <del> ($($fn_name:ident,)*) => { $( </del> <ins> ($($fn_name:expr,)*) => { $( </ins> test_future_yields_once_then_returns($fn_name); )* } } <ins> macro_rules! test_with_borrow { ($($fn_name:expr,)*) => { $( test_future_yields_once_then_returns(|x| { async move { await!($fn_name(&x)) } }); )* } } </ins> test! { async_block, async_nonmove_block, async_closure, async_fn, async_fn_with_internal_borrow, <ins> |x| { async move { unsafe { await!(unsafe_async_fn(x)) } } }, } test_with_borrow! { async_block_with_borrow_named_lifetime, async_fn_with_borrow, async_fn_with_borrow_named_lifetime, async_fn_with_impl_future_named_lifetime, |x| { async move { await!(async_fn_with_named_lifetime_multiple_args(x, x)) } }, </ins> } }