Skip to content

comptime → inlined literals

comptime let and comptime def calls run inside tyc’s sandboxed interpreter at build time. The result is inlined as a Python literal.

comptime let

comptime let PORT: int = int(env("PORT", "8080"))
comptime let DB_URL: str = env("DATABASE_URL")
comptime let IS_PROD: bool = env("BUILD_TAG", "dev") == "prod"

The runtime sees only the literal — there is no env() call at runtime.

comptime def

comptime def double(n: int) -> int:
return n * 2
comptime def grade(score: int) -> str:
if score >= 90:
return "A"
elif score >= 80:
return "B"
else:
return "F"
comptime let PORT: int = double(4000)
comptime let MY_GRADE: str = grade(82)

The function definitions remain in the output (they’re ordinary Python functions; comptime is a build-time marker), so they’re available at runtime too.

Missing required env

comptime let DB_URL: str = env("DATABASE_URL")
[env]
required = ["DATABASE_URL"]

If DATABASE_URL is unset at build time, the build fails:

error[tyc::comptime]: required environment variable `DATABASE_URL` is not set
┌─ src/main.ty:1:33
│
1 │ comptime let DB_URL: str = env("DATABASE_URL")
│ ^^^^^^^^^^^^^^^^^^^^

No quiet KeyError: 'DATABASE_URL' at the first request in production.

comptime let T: type — types as values (v0.5.0; PEP 695 lowering in v0.9.0)

A comptime let can also hold a type, in which case the binding is substituted wherever the alias appears in an annotation:

# Typhon
comptime let IdKind: type = int
def lookup(id: IdKind) -> User?:
return USERS.get(id)
# Emitted Python
type IdKind = int
def lookup(id: IdKind) -> User | None:
return USERS.get(id)

Since v0.9.0 the lowering emits a PEP 695 type IdKind = int alias statement. The substitution also runs before tyc check parses the resolved module so check, build, and tyc run all see the same shape — no more “alias resolves at build but not at check” drift.

VM substitution parity (v0.9.0)

The in-process VM (tyc run) used to skip the substitution pass, so comptime let PORT = int(env("PORT", "8080")) crashed under tyc run with NameError: env is not defined even when the same source built cleanly. Since v0.9.0 the VM pipeline runs the same substitution pass as tyc build, so the inlined literal is what the VM sees.

Sandbox

Implementation in tyc-analyse. Walks the comptime AST, producing a ComptimeValue enum:

enum ComptimeValue {
Int(i128),
Float(f64),
Str(String),
Bool(bool),
Type(/* ... */), // v0.5.0
}

Supported operations: literals, arithmetic, comparisons, boolean ops, ternaries, env(), int()/str()/float()/bool(), parameter and local-binding references, if/elif/else, return, comptime def calls, and types-as-values via the type lattice (v0.5.0).

Not supported (in v1): containers, string methods, loops, I/O, time, random, imports, exceptions. See comptime reference for the full contract.

Where next