C+ 0.0.30 — 2026-10-16
This release brings WinUI 3 as the default Windows UI and agent backend, the
appenv package and a single cross-platform asset staging rule in cpc, one
hybrid_web page messaging contract across all five UI backends, Liquid Glass
and Material 3 UI parity, compiler soundness and borrow-checker hardening, and
security audit remediations across cplus-pm, agent_mcp, and CI.
Upgrade notes
facet_runtime::app_data_dir()andfacet_runtime::cache_dir()are removed; useappenv::app_data_dir()andappenv::cache_dir(), which answer from the first line ofmainon every platform without waiting for a window.- On Windows,
facet_runtimeandfacet_agentnow selectfacet_winuiandagent_winuiby default.facet_win32is deprecated and remains available as an explicit opt-out. scrollnow takes a@viewblock (scroll { ... }); attaching a@viewblock to a leaf control reports E1010.hybrid_webuses one page API on every backend: JavaScript sends messages up withwindow.facet.postMessage(str)(available from document start), native delivers down by firingHybridWebViewMessageReceivedonwindowwithe.detail.message, and the C+on_messagecallback reads the payload throughhybrid_page::message(sender). The old per-backendwindow.facet.onmessage/window.facet.receivehooks are gone.- Discarding a call's
Statusreturn value as a bare statement now warns with W0009 (let _ = call();silences it deliberately). - Value-producing functions across
stdlib,cpc-bindgencollection bridges, and vendored packages now return either the complete result or an empty value on allocation or read failure, never a truncated prefix.
Language and compiler
- Borrow checker and soundness hardening.
- A method returning a view derived from a parameter ties that parameter's
loan for the lifetime of the view, including calls through function values
and interface methods on generic receivers (
fn use_it[T: Picker](p: T)). takeof a view type (str,T[], or a view-carrying struct/enum) is checked as a borrow rather than a consuming move, andthread::spawn_withdetaches its argument's borrow ties properly.- Type aliases (
type S = str;,type Guard = Scope;) are resolved before borrow, move, and NLL drop analysis, so aliased views, non-Copytypes, andDropguards obey the same rules as their underlying types. - Deferred initialization (
let x: T; x = expr;) runs partial-move (E0509,E0337) and wrapper move consumption checks on the right-hand side. - Same-block LIFO drop ordering checks
E0514against active borrows before releasing each local's own loans; cross-statement writes andrefborrows check overlapping sub-place loans (d.field,d[i]); nested variant patterns on borrowed scrutinees enforceE0337; andSend/Synccycle detection tags struct and enum IDs in separate namespaces.
- A method returning a view derived from a parameter ties that parameter's
loan for the lifetime of the view, including calls through function values
and interface methods on generic receivers (
- Diagnostics and attributes.
- W0009 warns when a
Statusreturn value is discarded as an expression statement. - W0007 catches
(1 << n) as u64where a shift happens at defaulti32width before widening. - E0310 diagnoses cycles in
typealiases cleanly instead of recursing. - E0510 counts a helper as a release function only when its body actually releases.
#target_feature("avx2,fma")and the CLI flags--target-cpu/--target-featurecontrol target code generation per function or per build.
- W0009 warns when a
- Codegen.
gen_drop_in_placeusesfield_addron planned structs (#[align(N)],#[packed]), fixing invalid GEP emission when an owning field sits at a non-zero offset.- Static arrays of empty strings emit a valid constant initializer, and enums carrying inner enums size their payload slot from the inner layout.
- An interface default method body resolves imports from its declaring module.
Toolchain, assets, and package manager
- One project asset rule (
cpc build,cpc package,--print-asset-dir). Every app build stages<root>/assets/*flat intotarget/assets/<target>/<mode>/incrementally and mirrors staged assets beside a self-linked binary (tracked by.cplus-assetsand refusing any asset that would overwrite the binary).cpc build --print-asset-dirstages and prints the directory for external builders (Xcode, Gradle/aapt2, Iris), andcpc packagebundles from the same staged tree. - One
[package] app_idacross platforms.cpc initwritesapp_idintoCplus.tomland every generated platform file, andcpc buildvalidates it (E0415 on an invalid identifier, W0008 when a platform file drifts). A refusedcpc initleaves no directory behind. - Windows DLL and link support. A
[library]cdylibon Windows links against the standard Windows system libraries, writes<name>.dlland<name>.lib, exports the C ABI symbols declared in its generated header, and omits-rpathon PE links.[link] libsexpands${VAR}environment references likesearch-pathsandextra-objects. - Doctests.
cpc testruns```cplusdocumentation fences, skips other language fences, and fails on unclosed fences. - Security hardening (
cplus-pm,cpc,agent_mcp, CI).cplus-pmkeys cache slots and tag records injectively (audit F01), refuses to write or remove unstamped directories or followvendor/symlinks outside the project (audit F02), and verifies that fetched package directories resolve inside the repository checkout.agent_mcpplaces local descriptors in a verified0700per-user directory/tmp/cplus-<uid>/(audit F04), rejects cross-origin, foreign-Host, and non-JSON requests on the loopback HTTP transport (audit F03), and buffers partial non-blocking socket reads per client without stalling the UI loop.- GitHub Actions workflows run test jobs with read-only tokens, isolate release publishing into build-free jobs with provenance attestation, and pin all actions by commit SHA (audit F05).
Facet, WinUI 3, and the agent stack
- WinUI 3 (
facet_winui,agent_winui,winui).- Generated WinMD bindings and a complete native WinUI 3 backend: multi-window
host, custom and blended window chrome,
App::menuMenuBar, modal alerts and file/folder/save pickers,TabView, tables, lists, collections,WebView2andhybrid_web, drag-and-drop on any node, gesture and keyboard bands, focus commands, light/dark theme tracking, per-window density observers,run_on_mainfrom background threads, andadopt_nativefor hosting inside an existing WinUI window. agent_winuiandfacet_agent_winuiexpose every live window over the MCP and in-app agent surfaces.
- Generated WinMD bindings and a complete native WinUI 3 backend: multi-window
host, custom and blended window chrome,
- Cross-platform UI and mobile polish.
- One
hybrid_webpage bridge (facet/hybrid_page): unifiedwindow.facet.postMessageup,HybridWebViewMessageReceivedcustom event down, andhybrid_page::message(sender)across AppKit, UIKit, Android, GTK, and WinUI. - iOS 26 Liquid Glass (
facet_uikit): nativeUITabBarwith floating and sidebar glass placement, scroll panes running under glass bars, native whole-window push navigation, action sheets forchoose, andblur_effect. - Android Material 3 & Material You (
facet_android): dynamic system palette tokens, Material 3 top and bottom tab bars with indicator pills, Material bottom sheets, Material dialogs (alert,choose,prompt), per-corner radii, andcontent://URI reading/writing inFacetFiles. - Symbols and icons: bundled Material Symbols font compiled into the
binary (
facet/icon_font),button(symbol:)andicon_button(symbol:), and tab bar icons across backends. - Text roles:
named_sizeresolves to each platform's native typography ramp. - File drops and save panel:
allow_file_drop,dropped_files, anddrag_overon any node, pluschoose_save_path. - Agent & Inspector: every control property is readable and writable
through generated inspector descriptors (
window_width/window_heightincluded); agents can press individual tabs, pick popup items and date/time pickers, read and answer iOS/Android alerts, and are refused when targeting controls on hidden screens or behind an active sheet.
- One
Standard library and packages
appenv: cross-platformapp_data_dir,cache_dir,no_backup_dir,exclude_from_backup,resource_dir,asset_path,read_asset,read_asset_text, andapp_id, usable from the first line ofmainon macOS, Linux, Windows, iOS, and Android.stdlib: addedstdlib/template(Templateunjoined string literals),stdlib/path(join,parent,file_name,stem,extension), andprocess::current_id().File::read_to_endandFile::linesnever return a short read as whole.flex_layout: added.basis/.basis_percent, ladder-range band rules (hide_up_to,hide_from,show_up_to,show_from,add_rule_up_to,add_rule_from),bands::default_set(),BandSet::first_match, and HIG layout presets (.readable_width(),.sidebar_width(),screenfilling its viewport).jni:mutf8converts JNI's modified UTF-8 at every Java string boundary injni,android_view,http, andfilepicker, so astral-plane characters (such as emoji) and embedded NULs round-trip as valid UTF-8 without tripping CheckJNI.filepickerandshare:FileRefreads and writes both filesystem paths and Androidcontent://URIs;share::fileworks on Android;cameraaddspreview(fit:).
v0.0.29 — 2026-09-24
A compiler release: a bit-reinterpret intrinsic, four ownership and checking fixes in generic and enum code, and two toolchain defects that produced wrong output or failed builds without saying why.
Upgrade notes
fN::from_bits(uN)and a float's.to_bits()are removed; write#bitcast::[f32](bits)and#bitcast::[u32](x)(either signedness of the integer works). Both old spellings report E0324 naming the replacement. A SIMD mask's.to_bits()is a different method and stays.- A generic
implbody is now checked where it is written, so a template that never type-checked reports its errors (E0302, E0324, …) at its own line instead of compiling. - An unbounded
Tinside a generic body counts as owning a destructor, so E0509 and E0337 apply to it as they do toText:struct W[T] { v: T }withfn get(this) -> T { return this.v; }is now refused. Bound it[T: Copy], or take the payload with a consumingmatch.
Language
#bitcast::[T](v)reinterprets a float's bits. A float and an integer of the same width swap types with the bits unchanged:f32↔u32/i32,f64↔u64/i64,f16↔u16/i16.#bitcast::[u32](1.0f32)is0x3F800000, where1.0f32 as u32is1. An unsuffixed literal takes the partner type, so#bitcast::[f32](0xBF800000)is-1.0rather than an out-of-rangei32. NaN payloads, infinities and-0.0come through unchanged, and that holds inconst/staticposition too (const INF: f32 = #bitcast::[f32](https://github.com/netdur/cplus/blob/v0.0.30/0x7F800000);): a folded float travels as an f64, which drops an f32 signalling NaN or an f16 NaN payload, so the exact pattern rides alongside it and is what gets emitted.usize/isize, int↔int and float↔float are refused (E0302): the first pair's width depends on the target, and the others are whatasis for.jni'sJValue::of_float/of_double, which punned through a pointer for want of this, now use it.#bitcastis the only spelling. The unsigned-onlyfN::from_bits/.to_bits()pair it replaces is gone (see the upgrade notes); a derivedHashover float fields now bitcasts too, with the same hash values.
Toolchain
- A generic
impl's method bodies now report their errors. Sema type-checked every generic impl body against its template and then discarded what it found, on the recorded belief that the body was checked again per instantiation. Nothing checks a method body after that pass, so a template could carry an unknown method or field (a compiler panic at codegen), a wrong arity or a plain type mismatch (compiled), orreturn 5in a-> Tbody instantiated atbool(linked, asret i1 5). The reports now land at the template's own line, with the codes a concreteimplgets. Measured first: zero new errors across stdlib, facet and the example apps, whose generic bodies already obeyed the rules. - A template's
Tmay own a destructor. Inside a generic body a type parameter answered "carries no drop", sostruct W[T] { v: T }withfn get(this) -> T { return this.v; }was not a partial move — and atW[Text]the field was returned and then dropped again with the shell, a double free written in the safe subset with no raw pointer in sight. An unboundedTnow counts as owning, so E0509 and E0337 apply to it as they do toText; a[T: Copy]bound keeps the bit-copy getter, and a consumingmatchstays the way to take a payload out. E0509 also names the type as spelled (W[T],(T, i32)) instead of the internalW__Param_T/__Tuple[T, i32]. - A consuming method on an enum local is a move the drop scanner sees.
e.into_inner()through atake thismethod lefteclassified as never-moved, because the scanner consulted struct methods only: a debug build of the compiler aborted on the guard that exists to catch exactly that, and a release build dropped the moved-out shell again at the caller's scope exit. That second drop had been cancelling a leak on the callee's side, below, so the counts looked right. The scanner consults enum methods now. - A
take thismethod on an enum drops what it owns. The enum method emitter boundthisand the parameters and registered no drop for either, so a consuming method on an enum leaked its payload and everytakeparameter (fn both(take this, take d: H)dropped neither); the struct emitter had always dropped both. Measured with a weighted counter across twelve receiver and parameter shapes, enum and struct, method and free function: each now drops exactly what it owns, once. - A static with no constant form stops the build. Codegen's fallback
for an initializer it could not render emitted
poison, on the belief that the IR would then fail to assemble. It does not:global float poisonis valid, so such a static compiled and read garbage. The fallback now emits a marker clang rejects on that line (cpc-bug:static-initializer-has-no-constant-form). Reaching it is a compiler bug; no known program does. - Concurrent builds no longer break each other's prebuilds. Every cpc
that found a package's prebuilt slice stale rebuilt it, and each rebuild
began by deleting the package's shared object directory under the others'
running clangs (
unable to rename temporary …). Any two builds sharing avendor/tree could hit it, and it failed 2–4 tests of every e2e run that started with a cold stdlib. One process now prebuilds a package under a per-package lock while the others wait and reuse its slice, printingcpc: waiting for another cpc to finish prebuilding``.