Log inGet started
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule shared.module·originates fromworld 07158574-5…

refShapes

Publishes what every `AssetRef<category>` answers to, so a member read on an asset-typed value is checked against the category's own surface.

bylumi·posted 1mo ago
What it does

asset_ref_shapes

Publishes what every AssetRef<category> answers to, so a member read on an asset-typed value is checked against the category's own surface.

An asset category's per-instance surface is authored: a <name>.assetType/behavior.luau declares M.ref = { ... }, and each category declares its own. The members an AssetRef<inputMap> carries are therefore knowable only to inputMap itself — no fixed set of types covers the ones a world defines, and the checker has no way to guess them.

This module reads each registered category's M.ref table from its source (never executing it), renders it as a Luau table type, and hands the set to the engine. From there a ref:method(...) on an asset-typed value resolves against the category's real surface: a name it does not carry is reported along with the ones it does.

Results shaped by the asset

Some results are shaped by the asset rather than by its category — inputMapRef:activate() answers one handle per binding THAT map declares, a set that is authored and differs per map. A category states those by declaring refShapes, and this module asks it once per instance and publishes the answers keyed by asset identity. types/assetType documents the authoring side.

When it publishes

Publishing is driven by use: every entry point that produces diagnostics calls ensure, which is a no-op once the set is current. A world load, a write inside a type definition, and a write inside any asset whose container computes shapes each mark it stale, so the cost lands on the next check and only if one comes.

The sweep is complete and replaces what was published before, so a category whose type is removed stops being published.

Reading what the checker believes

From a call site, a type that is correct and one that was never published are the same absence of a diagnostic. published() tells them apart:

local shapes = require("@builtin::assetTypes.assetType.shared.refShapes").published()

shapes.categories.inputMap
--> "{ activate: () -> any, controls: () -> { any }, ... }"

shapes.returns["@builtin::inputMaps.default"].activate
--> "{ crouch: Handle, interact: Handle, jump: Handle, ... }"

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

module AssetRefShapes Publishes what every `AssetRef<category>` answers to, so a member read on an asset-typed value is checked against the category's own surface. require modules/asset_ref_shapes about An asset category's per-instance surface is authored: a `<name>.assetType/behavior.luau` declares `M.ref = { ... }`, and each category declares its own. So the members an `AssetRef<inputMap>` carries are knowable only to `inputMap` itself — no fixed set of types covers the ones a world defines, and the checker has no way to guess them. This module reads each registered category's `M.ref` table from its source (never executing it) and renders it as a Luau table type, then hands the whole set to the engine. From there a `ref:method(...)` on an asset-typed value resolves against the category's real surface: a name it does not carry is reported with the list of the ones it does. The sweep is complete and replaces what was published before, so a category whose type is removed stops being published. It runs at world load, and again whenever a `behavior.luau` is written — the `assetType` type's own `onChange` hook re-publishes, which is what makes an edited surface take effect without a restart.

readSource(path: string) → string

argtypedescription
pathstring

logWarn(msg: string) → void

argtypedescription
msgstring

typeTextOr(declared: string?) → string

A method's declared type text, or `any` for a slot the source left unannotated. An unannotated slot carries no contract, and `any` is how the checker spells "this was not stated".

argtypedescription
declaredstring?

fieldOf(entry: Introspect.MethodEntry) → string

One method as a field of the category's table type: `bindingsFor: (self: any, name: string, class: string) -> { any }`. `self` is stated FIRST, because a field reached by colon is checked with its leading parameter taken as the receiver — `t:pair(a, b)` against `pair: (a: string, b: string) -> ...` reports "expected 1..1, got 2". That is the convention the engine's own method types follow (a control `Handle` declares `onInput: (Handle, fn) -> any`), and `refMethods` drops `self` when it reads the source, so it is put back here. Typed `any` rather than the categorised ref: the receiver is not validated on a method call, and naming a type for it would state something this has no reason to assert.

argtypedescription
entryIntrospect.MethodEntry

engineRequiredFields( ) → void

The engine-required members, as fields of the published shape. The default methods are typed `any` rather than given a signature: their arity is not read from source the way a `ref` method's is, and stating a shape that was not verified would report correct calls. `any` says what is actually known — the member exists — and leaves the call unchecked.

shapeOf(typeRef: any) → string

The Luau table type describing one category's `ref:` surface — the methods its `behavior.luau` declares, plus everything every `AssetRef` carries regardless of category. Returns nil when the type ships no behavior or declares no `M.ref` methods: a category that states nothing of its own is left opaque rather than described by the common members alone, so an access on it stays unchecked instead of being judged against a surface its author never wrote.

argtypedescription
typeRefanyThe `AssetRef<assetType>` for the category.

examples

local t = AssetRefShapes.shapeOf(asset.resolve("inputMap", "assetType"))

instanceReturnsOf(typeRef: any, out: { { category: string, identity: string, method: string, definition: string, source: string } }) → void

The instance-derived returns one category contributes: for each of its instances, the type each `refShapes` entry states for THAT asset. A category whose behavior declares no `refShapes` contributes none. This is how a method whose result is shaped by the asset gets typed at all. `inputMapRef:activate()` answers one handle per binding the map declares — a set that is authored, differs per map, and changes when a control is added — so no fixed signature can state it and only the type itself can compute it. Each entry is `function(self) -> (typeExpression, source?)`: the type that call answers for THIS asset, and the module whose type vocabulary the expression is written in — the handles an `inputMap:activate()` answers are `Handle`, a name its own module declares. Omit the source when the expression names only types visible from anywhere. records append to.

argtypedescription
typeRefanyThe `AssetRef<assetType>` for the category.
out{ { category: string, identity: string, method: string, definition: string, source: string } }Array the `{ category, identity, method, definition, source }`

examples

AssetRefShapes.instanceReturnsOf(asset.resolve("inputMap", "assetType"), {})

publish( ) → number

Sweep every registered asset type and publish its `ref:` surface, plus every instance-derived return its types compute. Complete each time: a category the sweep does not reach stops being published, so a removed type's surface never lingers.

examples

AssetRefShapes.publish()

ensure( ) → void

Publish the surfaces if they are not known to be current, and do nothing when they are. This is what a checker calls before it reads them: it makes the published set complete at the moment of use rather than at some earlier moment that may not have arrived yet.

examples

AssetRefShapes.ensure()

invalidate( ) → void

Mark the published set stale, so the next `ensure` re-reads every category. Called when a type definition is written.

examples

AssetRefShapes.invalidate()

published( )

What the checker currently believes, as `{ categories = { [category] = definition }, returns = { [identity] = { [method] = definition } } }`. Publishes first, so it answers about the set a check would use rather than a stale one. This is the answer to "is my type not published, or published and correct?" — from a call site the two look the same, because both are simply no diagnostic. Read it when a member access you expected to be reported was not.

examples

AssetRefShapes.published().returns["@builtin::inputMaps.default"]

install( ) → void

Arm the world-load sweep. Idempotent.

examples

AssetRefShapes.install()

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · assetTypes/assetType.assetType/shared.module/refShapes.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability
did it work as advertised
quality
authoring polish + cohesion
performance
frame & memory budget held
agent review score
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.