Calling hooks in a fn without `#[hook]` has terrible diagnostics
Problem
Hooks can be called in either function components or other functions marked as #[hook] (custom hooks). Calling hooks in a context that is not either of those results in terrible diagnostics, that make it very hard to figure out what is actually happening.
Steps To Reproduce Try to compile the following snippet
use yew::{use_effect, use_state, hook};
// #[hook] // uncomment this line to see the hook compile properly
fn use_some_hook() -> String {
let state = use_state(String::new);
{
let state = state.clone();
use_effect(move || {
state.set(String::from("some new value"));
|| {}
})
}
(*state).clone()
}
Actual behavior This error:
$ cargo check --target wasm32-unknown-unknown
Checking yew v0.19.3 (/home/hamza/code/yew/packages/yew)
error[E0599]: no method named `clone` found for opaque type `impl functional::hooks::Hook<Output = functional::hooks::use_state::UseStateHandle<String>>` in the current scope
--> packages/yew/src/suspense/hooks.rs:74:27
|
74 | let state = state.clone();
| ^^^^^ method not found in `impl functional::hooks::Hook<Output = functional::hooks::use_state::UseStateHandle<String>>`
error[E0308]: mismatched types
--> packages/yew/src/suspense/hooks.rs:75:9
|
75 | / use_effect(move || {
76 | | state.set(String::from("some new value"));
77 | | || {}
78 | | })
| | ^- help: consider using a semicolon here: `;`
| |__________|
| expected `()`, found opaque type
|
::: packages/yew/src/functional/hooks/use_effect.rs:141:1
|
141 | #[hook]
| ------- the found opaque type
|
= note: expected unit type `()`
found opaque type `impl functional::hooks::Hook<Output = ()>`
error[E0614]: type `impl functional::hooks::Hook<Output = functional::hooks::use_state::UseStateHandle<String>>` cannot be dereferenced
--> packages/yew/src/suspense/hooks.rs:81:5
|
81 | (*state).clone()
| ^^^^^^^^
Some errors have detailed explanations: E0308, E0599, E0614.
For more information about an error, try `rustc --explain E0308`.
warning: `yew` (lib) generated 1 warning
error: could not compile `yew` due to 3 previous errors; 1 warning emitted
Expected behavior Should give a better error message.
Environment:
- Yew version: master
- Rust version: 1.60.0
- Target, if relevant: wasm32-unknown-emscripten
- Build tool, if relevant:
cargo check --target wasm32-unknown-unknown
Questionnaire
- I'm interested in fixing this myself but don't know where to start
Gave it a little try. It does not seem possible only using proc macros. As function_component macro cant introspect code and check if Hook trait is implemented. https://github.com/yewstack/yew/blob/7178d2ea3d3a12e08189c7e97fb2e2292e32270a/packages/yew-macro/src/hook/body.rs#L45-L56