You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Before CellScript 0.25 is stabilized, decide whether user-defined value generics are part of the dependency-facing language or remain a package-local implementation mechanism.
Default recommendation: choose Proposal B unless concrete 0.25 packages demonstrate that cross-package user-defined generic libraries are required and Proposal A's normalization rules can be specified completely.
This is a bounded language-design decision. It is not a proposal for generic Cells, generic entry points, dynamic dispatch, traits, or runtime type reflection.
At a glance
Proposal A: restricted public generics
Proposal B: package-local generics
Cross-package user generics
Supported
Deferred
Package-local generics
Supported
Supported
Built-in Option<T> and fixed arrays
Supported
Supported
Public interface
Templates plus applied types
Concrete signatures only
Normal source spelling
Compact profile such as fixed_value
Concrete public wrappers
Compatibility commitment in 0.25
Larger
Smaller
Ability to redesign later
Limited after publication
Preserved
flowchart TD
NEED{"Does 0.25 have a concrete cross-package<br/>user-defined generic requirement?"}
PROFILE{"Can a closed constraint profile,<br/>derivation rules, and canonical identity<br/>be specified completely?"}
A["Proposal A<br/>Stabilize restricted public generics"]
B["Proposal B<br/>Keep user generics package-local"]
NEED -- "No" --> B
NEED -- "Yes" --> PROFILE
PROFILE -- "Yes" --> A
PROFILE -- "No" --> B
Loading
Why this needs an explicit decision
The existing implementation has strong safety properties, but its ordinary source form exposes a large amount of compiler vocabulary:
public struct Pair<T: copy + drop + store + fixed + serializable + non_linear>
has copy, drop, store, fixed, serializable, non_linear
{
left: T,
right: T,
}
The author's intent is much simpler:
T is an ordinary, fixed-width, serializable, non-Cell value.
Three costs currently leak into the user experience:
Constraint repetition: six properties appear on both the parameter and the resulting type.
Compatibility commitment: exporting a template commits its parameter count, phantom status, bounds, resulting abilities, layouts, and accepted applications.
Interface overload: the canonical audit record is appropriately detailed, but that detail is not a good default human review surface.
Current 0.25 baseline
The implementation already provides:
deterministic, budgeted monomorphization before IR;
generic structs, enums, and pure functions;
explicit parameters, phantom parameters, and value-ability constraints;
built-in Option<T> and generic fixed arrays;
specialization of imported public templates in their owning module;
rejection of generic Cell-backed values;
canonical package interfaces containing exported templates and applied types;
exclusion of implementation-only monomorphizations from the public interface;
compatibility comparison across source API, serialized layout, runtime ABI, effects/capabilities, generated builders, and deployment contracts.
Non-negotiable safety boundary under either proposal
Generic Cell-backed resource, shared, and receipt declarations remain rejected.
Actions and locks do not become generic entry points.
Specialization remains deterministic, bounded, and complete before IR.
Value abilities never grant Cell lifecycle capabilities.
No higher-kinded types, open traits, inheritance, dynamic dispatch, or runtime reflection.
The canonical machine record retains fully expanded constraints.
Private implementation instantiations do not affect the public interface hash.
Equivalent source sugar normalizes to one semantic interface identity.
No implicit signer, sighash, witness-placement, or authorization semantics are introduced.
Reference comparison: Move and Sui Move
Move is the closest mature reference design, but its execution and package model differ materially from CellScript.
What Move does
Concern
Move / Sui treatment
Relevance to CellScript
Public generics
Generic structs and functions are first-class public APIs. Type arguments are often inferred.
Evidence that public generics can be usable, but not that CellScript needs them in 0.25.
Constraint vocabulary
A closed set of four abilities: copy, drop, store, and key.
A small vocabulary keeps declarations readable. CellScript currently exposes six properties.
Conditional abilities
A generic datatype receives declared abilities only when its non-phantom arguments satisfy the corresponding requirements.
Prefer structural derivation over repeating the same property list.
Phantom identity
phantom T carries type identity without participating in datatype ability derivation.
Closely matches CellScript's bounded phantom identity use case.
Machine interface
Type parameters, constraints, phantom flags, parameters, returns, and generic instantiations remain in compiled module bytecode.
The complete machine contract can stay detailed without requiring a handwritten interface.
Upgrade compatibility
Public signatures cannot be removed or changed. Function constraints may be relaxed, not tightened. Existing datatype layouts and abilities remain fixed for Sui user-package upgrades.
Generic bounds are a real compatibility commitment, not implementation detail.
Sensitive generic calls
Sui adds a verifier-level “private generics” rule for selected framework functions: designated type arguments must be defined by the caller's module.
Authority-sensitive operations can be narrowed independently instead of disabling all generics.
flowchart LR
subgraph MOVE["Move / Sui"]
MS["Public generic source"] --> MB["Generic bytecode<br/>handles, constraints, instantiations"]
MB --> MV["Bytecode verifier and Move VM"]
end
subgraph CELL["CellScript 0.25"]
CS["Generic source template"] --> CM["Deterministic bounded<br/>monomorphization before IR"]
CM --> CI["Concrete IR and CKB-VM artifact"]
end
Loading
Move keeps generic definitions and instantiations as first-class bytecode concepts. CellScript deliberately specializes them before IR and emits concrete CKB-VM code. Consequently, a CellScript public generic template also commits to source availability, package-instance identity, owning-module specialization, specialization budgets, concrete layout, and artifact evidence.
Move also has foundational public-generic use cases such as Coin<phantom T>, Balance<phantom T>, Option<T>, and vector<T>. CellScript's user-defined generics are restricted to non-Cell values, so the need for third-party public generic libraries must be demonstrated separately.
Lesson for this issue
Move supports the direction of Proposal A, but the reusable lesson is not “expose every constraint.” It is:
keep the source-level property vocabulary small and closed;
infer structural properties where the result is deterministic;
treat public generic bounds as ABI commitments;
keep the complete representation in compiler-owned metadata;
apply additional restrictions at authority-sensitive operations;
let tooling, rather than a second handwritten file, enforce compatibility.
Proposal A: restricted public generics with a compact source surface
Public generic templates remain available across packages, but the common source form describes intent instead of repeating the expanded property set.
The name remains an RFC choice; fixed_value is illustrative:
public struct Pair<T: fixed_value> {
left: T,
right: T,
}
The compiler would normalize that profile to the precise accepted properties, for example:
copy + drop + store + fixed + serializable + non_linear
Where safe, result abilities are derived structurally from fields. The profile and derivation algorithm must be closed, versioned, deterministic, non-overridable, and independently checkable. Compact and expanded spellings must produce the same semantic interface identity.
public struct Pair<T: fixed_value>
public fn first<T: fixed_value>(Pair<T>) -> T
Detailed or JSON output would expose the expanded abilities, phantom status, layouts, ABI/profile identities, builder contracts, and deployment identities.
Benefits
Preserves cross-package generic library reuse.
Retains the existing monomorphization and interface work.
Keeps common source and review output concise.
Preserves complete audit evidence in the machine representation.
Risks
fixed_value becomes a versioned semantic contract.
Public generic bounds become long-term compatibility commitments.
Structural derivation must be specified for structs, enums, tuples, arrays, and future fixed values.
Cross-package specialization remains coupled to package and owning-module identity.
Gate for choosing A
Choose Proposal A only if all of the following are demonstrated before stabilization:
at least one concrete 0.25 use case requires cross-package user-defined generics;
a closed profile can be specified without creating an open trait system;
all equivalent spellings normalize to one interface identity;
the default human interface remains concise;
package-instance and owning-module identities are sufficient for safe specialization;
compatibility behavior for relaxing and tightening every bound is specified and tested.
Proposal B: keep user-defined generics package-local in 0.25
Keep the generic engine and safety work, but defer dependency-facing user-defined templates.
User-defined generic structs, enums, and pure functions may be private or public(package).
A public generic declaration is rejected with a targeted diagnostic.
Built-in Option<T> and fixed arrays remain supported.
Concrete applied types such as Option<u64> may appear in public signatures.
External APIs use concrete exported types or wrapper functions.
Internal instantiations remain in typed evidence but stay out of the dependency interface.
Benefits
Keeps the stable public language and interface smaller.
Preserves most of the implemented generic machinery.
Leaves room for a cleaner public-generic design in a later schema/version transition.
Risks
Third-party packages cannot publish generic value libraries in the 0.25 line.
Some package boundaries may need concrete wrappers or duplicated declarations.
Existing nightly packages with public generic templates require migration.
Compatibility rules required by either decision
Change
Required treatment
Remove or rename a public export
Breaking
Change generic parameter count or phantom status
Breaking
Tighten a public generic constraint
Breaking
Relax a public constraint
Compatible only if all layout, runtime, effect, builder, and deployment dimensions remain valid
Change a private/package-local instantiation
Must not change the public interface hash
Add a public export
Compatible, but changes the exact interface identity
Change compact spelling without changing normalized semantics
Must retain the same semantic interface identity
Unlike Move, CellScript cannot assume that relaxing a bound is automatically safe: a larger accepted type set may cross fixed-layout, serialization, code-size, specialization-budget, builder, or deployment boundaries. All six compatibility dimensions still apply.
Evidence requested before resolution
Please contribute concrete examples rather than syntax preference alone:
Which package requires user-defined generics rather than built-in Option<T> or arrays?
Which use case specifically requires cross-package specialization?
Which exported template cannot reasonably be represented by concrete wrappers?
Which ability combinations occur in real packages?
Does a real package require phantom identity for a non-Cell value?
What should a maintainer see in the default human interface view?
API signatures versus cryptographic signatures
Here, signature means a public type or callable API signature: type parameters, parameter types, return types, effects, and ABI-relevant qualifiers.
Cryptographic signatures are a separate security boundary. Neither proposal introduces implicit signers, hidden sighash defaults, or new signature-verification syntax. Transaction digest/domain, Script group, witness placement, identity binding, verifier/CellDep identity, replay policy, and authorization policy remain explicit.
Acceptance criteria
One proposal is selected in an accepted language-design decision.
Source syntax, visibility, and normalization are documented normatively.
Generic Cell-backed types and generic entries remain rejected.
Equivalent source forms produce one canonical semantic interface identity.
Private generic changes do not change the public interface hash.
Human output is concise and canonical JSON remains complete.
Interface diffs classify generic changes in the correct compatibility dimensions.
Registry admission and the independent verifier enforce the selected boundary.
Typed semantics and the artifact checker retain complete instantiation evidence.
Parser, formatter, type checker, resolver, monomorphization, IR, codegen, metadata, LSP, VS Code, Playground, docs, and syntax-combination tests agree.
Migration from the current nightly surface is explicit and tested.
Release notes describe the accepted boundary without presenting CellScript as a general-purpose generic language.
Decision
Before CellScript 0.25 is stabilized, decide whether user-defined value generics are part of the dependency-facing language or remain a package-local implementation mechanism.
This is a bounded language-design decision. It is not a proposal for generic Cells, generic entry points, dynamic dispatch, traits, or runtime type reflection.
At a glance
Option<T>and fixed arraysfixed_valueflowchart TD NEED{"Does 0.25 have a concrete cross-package<br/>user-defined generic requirement?"} PROFILE{"Can a closed constraint profile,<br/>derivation rules, and canonical identity<br/>be specified completely?"} A["Proposal A<br/>Stabilize restricted public generics"] B["Proposal B<br/>Keep user generics package-local"] NEED -- "No" --> B NEED -- "Yes" --> PROFILE PROFILE -- "Yes" --> A PROFILE -- "No" --> BWhy this needs an explicit decision
The existing implementation has strong safety properties, but its ordinary source form exposes a large amount of compiler vocabulary:
The author's intent is much simpler:
Three costs currently leak into the user experience:
Current 0.25 baseline
The implementation already provides:
Option<T>and generic fixed arrays;Non-negotiable safety boundary under either proposal
Reference comparison: Move and Sui Move
Move is the closest mature reference design, but its execution and package model differ materially from CellScript.
What Move does
copy,drop,store, andkey.phantom Tcarries type identity without participating in datatype ability derivation.Primary implementation references:
Why the precedent is only partial
flowchart LR subgraph MOVE["Move / Sui"] MS["Public generic source"] --> MB["Generic bytecode<br/>handles, constraints, instantiations"] MB --> MV["Bytecode verifier and Move VM"] end subgraph CELL["CellScript 0.25"] CS["Generic source template"] --> CM["Deterministic bounded<br/>monomorphization before IR"] CM --> CI["Concrete IR and CKB-VM artifact"] endMove keeps generic definitions and instantiations as first-class bytecode concepts. CellScript deliberately specializes them before IR and emits concrete CKB-VM code. Consequently, a CellScript public generic template also commits to source availability, package-instance identity, owning-module specialization, specialization budgets, concrete layout, and artifact evidence.
Move also has foundational public-generic use cases such as
Coin<phantom T>,Balance<phantom T>,Option<T>, andvector<T>. CellScript's user-defined generics are restricted to non-Cell values, so the need for third-party public generic libraries must be demonstrated separately.Lesson for this issue
Move supports the direction of Proposal A, but the reusable lesson is not “expose every constraint.” It is:
Proposal A: restricted public generics with a compact source surface
Public generic templates remain available across packages, but the common source form describes intent instead of repeating the expanded property set.
The name remains an RFC choice;
fixed_valueis illustrative:The compiler would normalize that profile to the precise accepted properties, for example:
Where safe, result abilities are derived structurally from fields. The profile and derivation algorithm must be closed, versioned, deterministic, non-overridable, and independently checkable. Compact and expanded spellings must produce the same semantic interface identity.
Layered interface presentation
flowchart TD SRC["Source<br/>Pair<T: fixed_value>"] --> NORM["Canonical normalization<br/>expanded abilities + layouts"] NORM --> HUMAN["Default human view<br/>exports, concise signatures, breaking changes"] NORM --> JSON["Canonical JSON<br/>full constraints, ABI, builders, deployment"] JSON --> CHECK["Registry + standalone checker<br/>hash and compatibility enforcement"]The default human view could be:
Detailed or JSON output would expose the expanded abilities, phantom status, layouts, ABI/profile identities, builder contracts, and deployment identities.
Benefits
Risks
fixed_valuebecomes a versioned semantic contract.Gate for choosing A
Choose Proposal A only if all of the following are demonstrated before stabilization:
Proposal B: keep user-defined generics package-local in 0.25
Keep the generic engine and safety work, but defer dependency-facing user-defined templates.
privateorpublic(package).publicgeneric declaration is rejected with a targeted diagnostic.Option<T>and fixed arrays remain supported.Option<u64>may appear in public signatures.Benefits
Risks
Compatibility rules required by either decision
Unlike Move, CellScript cannot assume that relaxing a bound is automatically safe: a larger accepted type set may cross fixed-layout, serialization, code-size, specialization-budget, builder, or deployment boundaries. All six compatibility dimensions still apply.
Evidence requested before resolution
Please contribute concrete examples rather than syntax preference alone:
Option<T>or arrays?API signatures versus cryptographic signatures
Here, signature means a public type or callable API signature: type parameters, parameter types, return types, effects, and ABI-relevant qualifiers.
Cryptographic signatures are a separate security boundary. Neither proposal introduces implicit signers, hidden sighash defaults, or new signature-verification syntax. Transaction digest/domain, Script group, witness placement, identity binding, verifier/CellDep identity, replay policy, and authorization policy remain explicit.
Acceptance criteria
dev,ci, andbackendgates pass.Related work
Sincedomains.CellScript references