Skip to content

bug - Decorator callable metadata still fails for imported partial defaults and alias callables #701

@dannymeijer

Description

@dannymeijer

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

Area

  • Incan Language (syntax/semantics)
  • Compiler (frontend/backend/codegen)

Summary

Expected: after #700 closed #694 and #698, decorator-backed registries should be able to combine imported public partial presets with decorated callable identity. In particular, a decorator argument such as an imported partial preset should preserve and qualify its captured defaults, and generic decorator helpers that read func.__name__ should work for callables whose signatures use imported aliases/unions.

Actual: release/v0.3 at c1b460d8 (incan 0.3.0-rc18) still fails on the broader InQL registry shape. Generated Rust loses qualification for symbols captured by imported partial defaults and emits invalid callable-name support for alias/union-expanded and async/generic callable shapes.

This blocks verification of InQL PR #44 after removing duplicated registry canonical-name arguments.

Related: #694, #698, #700, and broad follow-up #699.

Reproduction steps

Broad InQL reproducer

  1. Check out dannys-code-corner/InQL branch feature/33-35-41-wave1-function-catalog.
  2. Check out dannys-code-corner/incan branch release/v0.3 at c1b460d8 and build the incan binary.
  3. From the InQL checkout, run:
incan test tests/test_substrait_plan.incn
  1. The generated Rust test harness fails during preheat before any InQL assertions run.

Minimal imported partial default reproducer

Create src/registry.incn:

pub const DEFAULT_NAMESPACE: str = "core"


pub enum Policy(str):
  Portable = "portable"


pub model Spec:
  pub namespace: str
  pub policy: Policy
  pub lifecycle: str


pub static namespaces: list[str] = []
pub static names: list[str] = []


pub spec = partial Spec(namespace=DEFAULT_NAMESPACE, policy=Policy.Portable)


pub def capture(func: (int) -> int) -> ((int) -> int):
  names.append(func.__name__)
  return func


pub def add(spec_value: Spec) -> (((int) -> int) -> ((int) -> int)):
  namespaces.append(spec_value.namespace)
  return capture

Create src/helpers.incn:

from registry import add, spec


@add(spec(lifecycle="v1"))
pub def sample(value: int) -> int:
  return value + 1

Create tests/test_partial_default_symbols.incn:

from helpers import sample
from registry import names, namespaces


def test_partial_default_symbols_in_decorator() -> None:
  assert sample(1) == 2
  assert names[0] == "sample"
  assert namespaces[0] == "core"

Run:

incan test tests/test_partial_default_symbols.incn

Expected: test passes and the imported partial preset preserves DEFAULT_NAMESPACE and Policy.Portable inside the decorator argument.

Actual: generated Rust refers to captured default symbols from the wrong module scope.

Minimal alias/union callable-name reproducer

Create src/types.incn:

pub model A:
  pub value: int


pub model B:
  pub value: int


pub type Expr = Union[A, B]

Create src/registry.incn:

pub static names: list[str] = []


pub def capture[F](func: F) -> F:
  names.append(func.__name__)
  return func


pub def register[F]() -> ((F) -> F):
  return (func) => capture[F](func)

Create src/helpers.incn:

from registry import register
from types import Expr


@register[(Expr) -> Expr]()
pub def identity_expr(value: Expr) -> Expr:
  return value

Create tests/test_alias_union_callable_name.incn:

from helpers import identity_expr
from registry import names
from types import A


def test_alias_union_callable_name() -> None:
  identity_expr(A(value=1))
  assert names[0] == "identity_expr", names[0]

Run:

incan test tests/test_alias_union_callable_name.incn

Expected: test passes and the generic decorator can read the decorated callable name.

Actual: generated callable-name support references alias/union types from the wrong scope or expands them into conflicting callable-name impls in larger packages.

Output / logs

Representative broad InQL errors after #700:

error[E0425]: cannot find type `RejectedFunctionPolicy` in this scope
error[E0425]: cannot find value `CORE_FUNCTION_NAMESPACE` in this scope
error[E0119]: conflicting implementations of trait `__IncanCallableName` for type `fn(__IncanUnion...) -> __IncanUnion...`
error[E0605]: non-primitive cast: `fn() -> impl Future<Output = ()> ...` as `fn()`

The first two errors come from imported partial/default qualification. The __IncanCallableName conflicts and async casts come from callable-name metadata generation being applied too broadly or with the wrong lowered callable shape.

Environment

OS: macOS
Rust: stable toolchain used by release/v0.3
Incan: release/v0.3 at c1b460d8, incan 0.3.0-rc18
Command: incan test tests/test_substrait_plan.incn from the InQL branch feature/33-35-41-wave1-function-catalog
Blocking status: blocks InQL PR #44 verification after applying the intended ambient decorator-name and imported-partial registry shape.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingincan compilerSuggestions, features, or bugs related to the Compiler (frontend/backend/codegen)incan language semanticsSuggestions, features, or bugs related to the Incan Language itself (syntax and semantics)

Type

No fields configured for Bug.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions