Skip to content

Add automatically_derived and allow lints in macros #701

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

Merged
merged 1 commit into from Apr 15, 2021
Merged

Add automatically_derived and allow lints in macros #701

merged 1 commit into from Apr 15, 2021

Conversation

ghost
Copy link

@ghost ghost commented Feb 23, 2021

@ghost ghost added feature Adds functionality to the library c: export Component: export (mod export, derive) labels Feb 23, 2021
@ghost
Copy link
Author

ghost commented Mar 6, 2021

bors r+

bors bot added a commit that referenced this pull request Mar 6, 2021
701: Add automatically_derived and allow lints in macros r=toasteater a=toasteater

This should prevent clippy lints from showing up in user code in the future. See:

- https://doc.rust-lang.org/reference/attributes/derive.html
- https://doc.rust-lang.org/rustc/lints/groups.html
- https://github.com/rust-lang/rust-clippy#clippy

Co-authored-by: toasteater <[email protected]>
@bors
Copy link
Contributor

bors bot commented Mar 6, 2021

Build failed:

This should prevent clippy lints from showing up in user code in the future.
@ghost
Copy link
Author

ghost commented Apr 15, 2021

Also finally fixing this 😅

bors retry

bors bot added a commit that referenced this pull request Apr 15, 2021
701: Add automatically_derived and allow lints in macros r=toasteater a=toasteater

This should prevent clippy lints from showing up in user code in the future. See:

- https://doc.rust-lang.org/reference/attributes/derive.html
- https://doc.rust-lang.org/rustc/lints/groups.html
- https://github.com/rust-lang/rust-clippy#clippy

709: Minimal async-await foundations r=toasteater a=toasteater

This sets the foundations for async-await support in godot-rust, based on the original idea in #284. However, although the tests work, this is not a full implementation:

- Async methods can only be registered manually using `build_method`. Macro syntax and implementation are out of the scope of this PR.
- The runtime types aren't registered automatically yet. Users need to manually call `register_runtime` and `terminate_runtime` functions in their library lifecycle hooks. Improving this is out of the scope of this PR for now.
- The crate is currently re-exported as `gdnative::asn`, instead of the much longer `async_yield`. The name is open to discussion -- I don't like it very much.
- Only local spawners are supported, due to issues with thread safety. Users may off-load tasks that don't contain `yield`-likes to thread pool spawners using something like `futures::future::Remote`, however.
- Panics in async methods don't currently behave very well. Their `FunctionState`-likes simply block forever and any outstanding bridge objects for futures can be leaked.

- - -

While the feature is not yet complete, the commit is already pretty big, and I feel that it's in a somewhat usable state. As a result, I'm putting this up as a draft PR to gather some feedback. If you have uses for async-await / "yield" from GDScript, please feel free to try it and tell me what you think!

Registering an async method currently looks like this (excerpt from the tests):

```rust

struct ResumeAddFn;

impl AsyncMethod<AsyncMethods> for ResumeAddFn {
    fn spawn_with(&self, spawner: Spawner<'_, AsyncMethods>) {
        spawner.spawn(|ctx, _this, mut args| {
            let a = args.read::<i32>().get().unwrap();
            let obj = args.read::<Ref<Object>>().get().unwrap();
            let name = args.read::<GodotString>().get().unwrap();

            async move {
                let b = ctx.until_resume().await;
                let b = i32::from_variant(&b).unwrap();

                let c = unsafe { obj.assume_safe().call(name, &[]) };
                let c = Ref::<Reference>::from_variant(&c).unwrap();
                let c = unsafe { c.assume_safe() };
                let c = ctx.signal(c, "completed").unwrap().await;
                assert_eq!(1, c.len());
                let c = i32::from_variant(&c[0]).unwrap();

                (a + b + c).to_variant()
            }
        });
    }
}

fn register_methods(builder: &ClassBuilder<AsyncMethods>) {
    builder
        .build_method("resume_add", Async::new(ResumeAddFn))
        .done();
}
```

Using it is almost like any other GDScript coroutine:

```gdscript
func _async_call(obj):
	var fn_state = obj.resume_add(1, self, "_get_async_number")
	# the "resumable" signal is unique to Rust, since unlike GDScript coroutines,
	# Rust futures aren't guaranteed to be polled up to a yield right after spawning.
	yield(fn_state, "resumable")
	fn_state = fn_state.resume(2)
	# no "resumable" signal when awaiting signals, though
	var result = yield(fn_state, "completed")
	assert(result == 42)

func _get_async_number():
	yield(get_tree().create_timer(0.1), "timeout")
	return 39
```

Co-authored-by: toasteater <[email protected]>
@bors
Copy link
Contributor

bors bot commented Apr 15, 2021

Build failed (retrying...):

@bors
Copy link
Contributor

bors bot commented Apr 15, 2021

Build succeeded:

@bors bors bot merged commit 37a35c5 into godot-rust:master Apr 15, 2021
@ghost ghost mentioned this pull request May 1, 2021
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: export Component: export (mod export, derive) feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants