yew icon indicating copy to clipboard operation
yew copied to clipboard

Calling hooks in a fn without `#[hook]` has terrible diagnostics

Open ranile opened this issue 3 years ago • 1 comments

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

ranile avatar Apr 15 '22 10:04 ranile

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

voidpumpkin avatar Apr 03 '23 19:04 voidpumpkin