Skip to content

Unstable error variant in unstable function leads to compilation error #2210

Open

Description

@moldhouse

The following WIT world fails to compile with wit-bindgen==0.42.1 and the tool feature not being active. This error comes after introducing the tool-error variant and changing the return type of invoke-tool to a result:

error: found a reference to a type which is excluded due to its feature not being activated
            --> .../wit-unstable/skill.wit:27:39
             |
          27 |     invoke-tool: func(request: u8) -> result<list<u8>, error>;
             |                                       ^-----
 --> src/main.rs:3:1
  |
3 | generate!({ path: "skill.wit", world: "skill" });

It appears like a bug, as only small changes to the WIT world (changing the unrelated type of output-schema from a list<u8> to a u8) will lead to a successful compilation. My expectation would have been that it is possible to have unstable types in the signature of unstable functions.

package pharia:skill@0.3.0;

world skill {
    import tool;
    export skill-handler;
}

@since(version = 0.3.0)
interface skill-handler {
    @since(version = 0.3.0)
    record skill-metadata {
        output-schema: list<u8>,
    }

    @since(version = 0.3.0)
    metadata: func() -> skill-metadata;
}

interface tool {
    @unstable(feature = tool)
    variant error {
        other(string)
    }

    @unstable(feature = tool)
    invoke-tool: func(request: u8) -> result<list<u8>, error>;
}

A minimum reproducable example can be achieved with the following main:

use wit_bindgen::generate;

generate!({ path: "skill.wit", world: "skill" });

fn main() {
    println!("Hello, world!");
}

Activity

  1. alexcrichton commented on May 28, 2025

    @alexcrichton
    Member

    I've transferred this to the wasm-tools repository since here is where the issue lies, and this can additionally be reproduced with wasm-tools component wit over the above WIT package as well.

    This points to subpar handling of "anonymous types" (in this case result<list<u8>, error>) and gated types. The problem here is that the anonymous type definition result<list<u8>, error> refers to a gated type (error) but the anonymous type is itself not gated (and has no means of being gated). This is very much an (unforseen) limitation of WIT. Thank you for the report!

    One possible workaround is something like:

        @unstable(feature = tool)
        type result-list = result<list<u8>, error>;
        @unstable(feature = tool)
        invoke-tool: func(request: u8) -> result-list;

    but that's just a workaround and I realize it's not great

  2. moldhouse commented on May 28, 2025

    @moldhouse
    Author

    Thanks for getting back so quickly and for pointing me to the workaround. With the knowledge about the "anonymous type" I can see where the limitation comes from.

    The thing that threw me off was that I can get it compiling with unrelated changes. E.g. the following WIT world with some changes to the skill-handler interface works fine:

    package pharia:skill@0.3.0;
    
    world skill {
        import tool;
        export skill-handler;
    }
    
    @since(version = 0.3.0)
    interface skill-handler {
        @since(version = 0.3.0)
        metadata: func() -> u8;
    }
    
    interface tool {
        @unstable(feature = tool)
        variant error {
            other(string)
        }
    
        @unstable(feature = tool)
        invoke-tool: func(request: u8) -> result<list<u8>, error>;
    }
    
  3. alexcrichton commented on May 28, 2025

    @alexcrichton
    Member

    Oh wow ok yeah that is indeed very weird! I think that may have to do with the fact that list<u8> is deduplicated across packages to point to the same type, but that may also point to a possible solution where we don't deduplicate in the face of differing stability annotations... Worth digging into!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    witrelated to the `*.wit` text format

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions