Skip to content

Autocomplete doesn't work inside 'async_stream' function-like macro #12759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
elimist3 opened this issue Jul 13, 2022 · 7 comments
Open

Autocomplete doesn't work inside 'async_stream' function-like macro #12759

elimist3 opened this issue Jul 13, 2022 · 7 comments
Labels
C-support Category: support questions

Comments

@elimist3
Copy link

elimist3 commented Jul 13, 2022

rust-analyzer version: rust-analyzer 0.0.0 (5342f47f4 2022-07-09)

rustc version: rustc 1.64.0-nightly (27eb6d701 2022-07-04)


I'm learning Rust and I was playing around with the routeguide tutorial from tonic.

When I open routeguide/client.rs and type some characters at the top of the run_route_chat function, autocomplete works fine. However, when typing characters inside the async_stream::stream! macro block, the autocompletions don't show up.

async fn run_route_chat(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
    let start = time::Instant::now();

    let outbound = async_stream::stream! {
    
       // ------------------------------------------------------------------------------------
       // ----------------- autocompletions stop working inside here ------------------------
       // ------------------------------------------------------------------------------------
     
        let mut interval = time::interval(Duration::from_secs(1));

        loop {
            let time = interval.tick().await;
            let elapsed = time.duration_since(start);
            let note = RouteNote {
                location: Some(Point {
                    latitude: 409146138 + elapsed.as_secs() as i32,
                    longitude: -746188906,
                }),
                message: format!("at {:?}", elapsed),
            };

            yield note;
        }
    };

    let response = client.route_chat(Request::new(outbound)).await?;
    let mut inbound = response.into_inner();

    while let Some(note) = inbound.message().await? {
        println!("NOTE = {:?}", note);
    }

    Ok(())
}

Demo:
https://streamable.com/c0vl10#

I've read the blog post and all the various issues talking about the root causes so I think I have an understanding of why this is occurring, but I thought I'd file the issue anyway.

@lnicola
Copy link
Member

lnicola commented Jul 13, 2022

Try using a stable toolchain if you don't depend on nightly.

@elimist3
Copy link
Author

I think I originally had it on rust stable, but changed it to nightly to see if the problem had been patched!
I just changed it back to rust stable again to verify, and autocomplete still doesn't work inside the macro.

@flodiebold
Copy link
Member

flodiebold commented Jul 13, 2022

Since async_stream is a function-like proc macro, there isn't much we can do to make it handle incomplete code. So as long as what you're typing isn't syntactically complete Rust, the macro probably refuses to expand and so we can't provide completions. This would have to be fixed by the macro authors. (You can test whether this is the case by 1. using the "expand macro" function to see whether rust-analyzer can actually expand the macro, and 2. writing some complete, but not necessarily valid statement like start.f; at the place you marked and then trying to get completions after the f.)

@elimist3
Copy link
Author

elimist3 commented Jul 13, 2022

That makes sense. I just tried both 1 and 2 above and it looks like it's definitely the case that the syntactically incomplete Rust is preventing the macro from expanding properly, which in turn is killing the autocomplete - when typing any valid statement or simply holding the cursor inside the macro and invoking macro expand, I can see that rust-analyzer expands it to this:

// =======================================
// Recursive expansion of the stream macro
// =======================================

{
    let (mut __yield_tx, __yield_rx) = $crate::yielder::pair();
    $crate::AsyncStream::new(__yield_rx, async move {
        let mut interval = time::interval(Duration::from_secs(1));
        loop {
            let time = interval.tick().await;
            let elapsed = time.duration_since(start);
            let note = RouteNote {
                location: Some(Point {
                    latitude: 409146138 + elapsed.as_secs() as i32,
                    longitude: -746188906,
                }),
                message: {
                    let res = $crate::fmt::format(std::fmt::Arguments::new_v1(
                        &[],
                        &[std::fmt::ArgumentV1::new(
                            &(elapsed),
                            std::fmt::Display::fmt,
                        )],
                    ));
                    res
                },
            };
            __yield_tx.send(note).await;
        }
    })
}


Typing in any incomplete Rust and attempting to expand the macro fails as predicted.

I'll try to bring it up with the macro authors!

@flodiebold flodiebold added the C-support Category: support questions label Jul 15, 2022
@nyxtom

This comment was marked as off-topic.

@flodiebold
Copy link
Member

@nyxtom That's not the same problem. If proc macros aren't expanding for you, there should be an error underline on the Validate derive. If you're using nightly, it's currently a known problem, otherwise it might be a setup issue.

@hasezoey
Copy link

i think i run in the same problem with crossbeam::channel::select macro

code:

fn main() -> Result<(), Box<dyn std::error::Error>> {
	use crossbeam::channel::*;

	let (tx1, rx1) = unbounded::<usize>();
	let (tx2, rx2) = unbounded::<usize>();

	// if the following is just *one* "recv", completion works until something invalid
	select! {
		recv(rx1) -> msg => {
			// no completion at all
		},
		recv(rx2) -> msg => {
			// no completion at all
		},
		default => (),
	}

	return Ok(());
}

the weird thing is if there is just 1 recv inside the select, then it has auto-completion until something invalid / incomplete is written (like writing msg. and asking for suggestions, where msg is Result<_, _>)

personally i would expect there to have full typings like a normal(closure) function (|msg| { here }) would have

full repository

rust-analyzer (vscode): 0.3.1631-standalone
rustc 1.71.1 (eb26296b5 2023-08-03)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-support Category: support questions
Projects
None yet
Development

No branches or pull requests

5 participants