Skip to content

bug - Method-call decorators emit invalid Rust for static/class receivers #645

@dannymeijer

Description

@dannymeijer

Thanks for reporting! Please include a minimal reproduction when possible.

Area

  • Compiler (frontend/backend/codegen)

Summary

Expected: method-call decorators should lower using the same receiver/member-call rules as ordinary checked Incan code. A class static method decorator such as @Registry::add("col") should emit a Rust associated function call, and a static registry instance decorator such as @FUNCTIONS.add("col") should access the static cell value before invoking the instance method.

Actual: both forms typecheck, but generated Rust is invalid. This blocks using a registry API where registry.add(...) is the decorator factory for function catalog registration.

Reproduction steps

  1. Create repro_static_method.incn:
class Registry:
    pub names: list[str]

    @staticmethod
    def new() -> Self:
        return Registry(names=[])

    @staticmethod
    def add[F](name: str) -> (F) -> F:
        FUNCTIONS.names.append(name)
        return (func) => func


static FUNCTIONS: Registry = Registry.new()


@Registry::add("col")
def col(name: str) -> str:
    return name


def main() -> None:
    println(col("amount"))
    println(len(FUNCTIONS.names))
  1. Run incan --check repro_static_method.incn.
  2. Run incan build repro_static_method.incn.
  3. Create repro_static_receiver.incn:
class Registry:
    pub names: list[str]

    @staticmethod
    def new() -> Self:
        return Registry(names=[])

    def add[F](mut self, name: str) -> (F) -> F:
        self.names.append(name)
        return (func) => func


static FUNCTIONS: Registry = Registry.new()


@FUNCTIONS.add("col")
def col(name: str) -> str:
    return name


def main() -> None:
    println(col("amount"))
    println(len(FUNCTIONS.names))
  1. Run incan --check repro_static_receiver.incn.
  2. Run incan build repro_static_receiver.incn.

Output / logs

$ incan --check repro_static_method.incn
✓ Type check passed!

$ incan build repro_static_method.incn
error[E0423]: expected value, found struct `Registry`
  --> src/main.rs:49:5
   |
49 |     Registry.add("col".into())(__incan_original_col),
   |     ^^^^^^^^
   |
help: use the path separator to refer to an item
   |
49 -     Registry.add("col".into())(__incan_original_col),
49 +     Registry::add("col".into())(__incan_original_col),
   |

$ incan --check repro_static_receiver.incn
✓ Type check passed!

$ incan build repro_static_receiver.incn
error[E0599]: no method named `add` found for struct `LazyLock<StaticCell<Registry>>` in the current scope
  --> src/main.rs:54:15
   |
54 |     FUNCTIONS.add("col".to_string())(__incan_original_col),
   |               ^^^ method not found in `LazyLock<StaticCell<Registry>>`

Environment

OS: macOS
Rust: rustc 1.96.0-nightly (362211dc2 2026-03-24)
Incan: 0.3.0-rc10 on release/v0.3
Command: incan --check repro_static_method.incn, incan build repro_static_method.incn, incan --check repro_static_receiver.incn, incan build repro_static_receiver.incn

Related context: discovered while implementing InQL RFC 014 function registry decorators. The desired API is a registry-owned add decorator factory with all function metadata supplied in the decorator call.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingincan compilerSuggestions, features, or bugs related to the Compiler (frontend/backend/codegen)

Type

No fields configured for Bug.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions