Release 0.2¶
Incan 0.2 introduces namespaced stdlib imports and namespaced decorators under the std.* module tree (RFC 022).
This is a breaking change to import syntax — all stdlib imports and decorators must now use their fully qualified paths.
This release lays the groundwork for a cleaner stdlib architecture where the compiler knows less about domain-specific modules (web, testing, async) and the stdlib can grow without polluting the global namespace.
Migrating from 0.1¶
Use this checklist when moving a 0.1 codebase to 0.2.
Import paths¶
All stdlib imports move from bare module names to the std.* namespace:
# Before (0.1)
from web import App, Response, Json
from testing import assert_eq, assert_ne
# After (0.2)
from std.web import App, Response, Json
from std.testing import assert_eq, assert_ne
This also applies to async modules:
# Before (0.1)
from async.time import sleep
# After (0.2)
from std.async.time import sleep
Decorators¶
Decorators are now resolved by their fully qualified module path. Use an explicit import or a canonical path:
# Import and use short name (preferred)
from std.web.routing import route
@route("/hello")
async def hello() -> str:
return "Hello!"
# Canonical path (also works)
@std.web.routing.route("/hello")
async def hello() -> str:
return "Hello!"
Testing decorators follow the same rule:
# Canonical path
@std.testing.skip("not implemented")
def test_future() -> None:
pass
Or with an alias:
import std.web.routing as routing
@routing.route("/hello")
async def hello() -> str:
return "Hello!"
and:
import std.testing as testing
@testing.skip("not implemented")
def test_future() -> None:
pass
Soft keyword activation¶
async/await keywords are activated per file through stdlib imports.
If a file uses async syntax, import std.async (or a submodule like std.async.time) in that same file.
Stdlib types require explicit imports¶
Types like App, Response, Html, Json, and Query are no longer globally available — import them from std.web.
The compiler will suggest the correct import if you use a stdlib type without importing it.
Testing markers are runner metadata¶
@skip, @xfail, @slow, @fixture, and @parametrize are consumed by incan test from std.testing metadata.
They are not intended as runtime function calls.
Reserved names¶
std and rust are now reserved at the module level and cannot be used as declaration names.
Features and Enhancements¶
- Compiler: Namespaced stdlib imports under
std.*— all stdlib modules use qualified paths (RFC 022). - Parser/formatter: Parenthesized multi-line import lists are supported for both
from module import (...)andfrom rust::crate import (...), with optional per-item aliases and formatter-aware wrapping (#116). - Compiler: Import-activated soft keywords —
asyncandawaitare identifiers by default and become reserved only whenimport std.async(orfrom std.async...) is present. Forgetting the import produces a targeted diagnostic with a fix suggestion. Similarly,std.testingactivates theassertstatement syntax (RFC 023). - Compiler: Surface Semantics Engine — soft keywords (
assert,async,await) and decorator semantics are routed through a registry-driven dispatch system (SurfaceSemanticsPack). The parser emits genericSurfaceAST nodes keyed bySurfaceFeatureKey; downstream stages dispatch on that key rather than per-keyword AST variants. Adding a new soft keyword requires no parser, AST, or IR changes — only a keyword descriptor and a semantics-pack handler (RFC 023). - Compiler:
incan-vocabestablishes a standalone, registry-driven keyword/manifest/desugaring contract for future library vocabulary extensions, and core tooling consumers now read keyword surface data through that shared registry path (RFC 027). - Compiler: Namespaced decorator resolution — decorators resolved by module path
(e.g.,
from std.web.routing import routeenables@route(...)) with alias support (RFC 022). - Compiler:
@rust.externmarker for Rust-backed function stubs, replacing the internal@std.builtindecorator (RFC 022, RFC 023). - Compiler:
@staticmethoddecorator for type-scoped methods with noselfreceiver, available onclass,model, andnewtypedeclarations. Required for@rust.externmethods on types (instance delegation is not supported). - Testing:
std.testingis Incan-first — user-facing API and assertion behavior are defined incrates/incan_stdlib/stdlib/testing.incn, with Rust limited to explicit@rust.externhost boundaries (for examplefailandfail_t) (RFC 023). - Compiler: Stdlib namespace registry (
STDLIB_NAMESPACES) replaces the flat stdlib-module list — convention-based submodule discovery, registry-driven unknown-module diagnostics, and soft-keyword activation metadata. - Compiler: Reserved root namespaces —
stdandrustcannot be used as user declaration names. - Compiler: Stdlib types require explicit imports with actionable error messages when used without import.
- Compiler:
from rust import <crate>syntax for importing Rust crates — the compiler validates imports against[dependencies]inincan.tomland emits the correctusestatements in generated Rust (RFC 013). - Compiler: Rust crate dependency management with inline version annotations, manifest-based configuration, version validation (semver), and lock files for reproducible builds (RFC 013).
- Compiler: Convention-based source root resolution — the compiler and test runner resolve user module imports
against
src/(or an explicit[build] source-root) so imports are uniform across source and test files (RFC 015). - Web: Compiler-to-stdlib routing handoff via
incan_stdlibmacros (RFC 022). - Web: Web-free compiler — all web-specific knowledge (route registration, extractor types, response builders)
lives in
std.webstdlib modules and theincan_web_macrosproc-macro crate. The compiler uses generic decorator passthrough (@rust.extern+rust.module()) and derive passthrough (@derive(X)fromrust.module()traits) with no domain-specific web logic in the compiler core (RFC 023). - Web: Import-driven web feature activation — importing
std.webautomatically enablesaxum,incan_web_macros, andinventorydependencies in the generated project (RFC 023). - Runtime:
incan_stdlib::r#asyncnow provides the narrow Rust runtime leaves behind the source-declaredstd.asyncmodules, rather than exposing the async surface as a raw Tokio re-export facade. - Tooling:
incan initscaffolds a full project:src/main.incn,tests/test_main.incn, andincan.tomlwith[project.scripts] mainset (RFC 015). - Tooling:
incan lockgeneratesincan.lockfor reproducible builds;--lockedand--frozenflags enforce lock freshness in CI (RFC 013). - Tooling: Test runner resolves imports against the project source root, enabling tests to import directly from
source modules (e.g.,
from greet import greet) without duplication (RFC 015). - Tooling: Test marker semantics (
@skip,@xfail,@slow,@fixture,@parametrize) are derived fromstd.testingmetadata incrates/incan_stdlib/stdlib/testing.incninstead of brittle string/path hardcoding (RFC 023). - Parser:
asyncis allowed as a module path segment in imports (e.g.,from std.async.time import sleep). - Diagnostics: Clearer error messages for unknown decorators and reserved namespace violations.
- Diagnostics: Enhanced lock-out-of-date error with expected vs actual fingerprint for easier debugging.
- Compiler:
rust::coreandrust::allocare now rejected at the typechecker level with a targeted diagnostic pointing users torust::std::...instead (reserved for futureno_std/target work) (RFC 005). - Diagnostics: Rust interop dependency errors now include the import site path and a hint to verify the
crate/module/item path or add version/features in
incan.toml(RFC 005, RFC 013). - Docs: "Your first Incan project" tutorial covering
incan init, modules, and testing. - Docs: Contributor docs now describe the registry-driven keyword path, including
incan-vocab, parserIdentkeyword handling, and generated VS Code grammar synchronization (RFC 027). - Codegen: String literals passed to external Rust type methods now emit
.into()instead of.to_string(), letting the Rust compiler resolve custom string types (e.g. Polars'PlSmallStr) via theIntotrait. - Compiler: MSRV bumped from 1.85 to 1.88 (required by
timecrate v0.3.47).
Bugfixes¶
- Diagnostics: Unknown symbol errors in f-string interpolations now point to the precise
{expr}span (including nested interpolation expressions) instead of the full f-string (RFC 011, #71). - Compiler: Fixed project root resolving to empty string when running
incan run src/main.incnfrom the project directory, causing "No such file or directory" errors. - Docs: Web tutorial examples updated to
std.webimports and namespaced decorators. - Docs: Derives and traits explanation updated to use
@rust.extern.
Known limitations (0.2)¶
- Web route handlers and their request models must be declared
pubfor cross-module wrapper generation (#117). - Rust macro syntax (e.g.,
serde_json::json!(...)) is not supported in Incan source — use Rust crate functions and types directly instead.
RFCs implemented¶
- Namespaced stdlib modules and compiler-to-stdlib handoff: RFC 022
- Compilable stdlib and Rust module binding (web-free compiler): RFC 023
- Rust crate dependency management: RFC 013
- Hatch-like tooling (partial —
incan init, project discovery, source root resolution): RFC 015 - Rust interop surface (
rust::imports, type mapping, string borrow adaptation, curated derives): RFC 005 - Precise f-string interpolation diagnostics: RFC 011