CONCEPTS

Lie-Typing

Lie-Typing

Tutorial: Lie-TypingSee also: Lazy Construction, API: instantiate

The Core Insight

Python's type system has no way to say "this is a DictConfig that materializes into a T when passed to instantiate." The real runtime type is DictConfig; the useful static type is T.

Laco resolves the tension with an intentional mismatch. L.call(nn.Linear)(...) is declared to return nn.Linear. The IDE and type-checkers accept this declaration, but at runtime it returns a DictConfig. This mismatch is load- bearing. Without it, nested composition collapses to Any after the first level.

The Six Constructs

ConstructStatic typeRuntime typeUse case
L.call(T)(...)TDictConfigLazy class construction
L.partial(T)(...)TDictConfigDeferred partial application
L.just(v)type(v)DictConfigWrap an existing value
L.required[T]()TDictConfigMandatory placeholder
L.slot(G)GDictConfigGroup placeholder in schema
L.chosen(G)GDictConfigIn-body cross-reference

Where the Mismatch is Enforced

Laco enforces the mismatch at two system boundaries.

  1. laco.load accepts only Laco nodes produced by the six constructs above, plus primitives. It rejects plain Python objects that are not node instances.
  2. laco.instantiate converts DictConfig back to the genuine T, both at runtime and in its static signature.

Between those two boundaries, type-checked code sees T. Code at runtime sees DictConfig. The mismatch matters only inside config files, where you construct nodes. It does not matter inside training code, where you consume them after instantiate.

LazyObject[T]

When a function receives a config node that will be instantiated inside it, annotate the parameter with LazyObject[T]:

from laco import LazyObject, instantiate

def build(model_cfg: LazyObject[nn.Module]) -> nn.Module:
    return instantiate(model_cfg)

LazyObject[T] exists only for type-checking. It is an alias for DictConfig at runtime. The instantiate overload LazyObject[T] -> T makes the return type concrete.

LACO_STRICT_NODES

During development you can set LACO_STRICT_NODES=1 to make DictConfig nodes raise AttributeError on attribute access that isn't a config key. This catches accidental use of a node as if it were the real object.

LACO001 Lint Rule

laco-lint emits LACO001 when it detects attribute access on a value annotated as a Laco node type. Add # noqa: LACO001 to suppress an intentional access (e.g. introspecting ._metadata).