dtype-descriptors Specification¶
Purpose¶
Define the public descriptor model that names StrideWeave dtypes, relates them through categories, preserves their process identity, and permits cooperative extensions without changing the built-in namespace.
Terminology¶
| Term | Meaning |
|---|---|
| descriptor | An immutable, canonically registered DType singleton that is the process-local identity of one dtype category or representation and is compared by object identity. |
| registered name | The unique non-empty string by which a descriptor is discovered. |
| category | A DTypeCategory descriptor that places dtypes in a supertype hierarchy and defines neither a fixed-width scalar encoding nor a compound physical representation; whether a carrier accepts a descriptor as storage is defined separately by carrier-storage. |
| simple dtype | A SimpleDType descriptor for one fixed-width scalar encoding; being simple classifies the encoding and does not imply that any carrier can store or execute it. |
| structure | The immutable canonical identity record captured at descriptor finalization, recursively incorporating every representation-defining field, referenced descriptor structure, and extension contribution; it determines pickle compatibility and any kind-specific structural uniqueness. |
| extension descriptor | A non-built-in descriptor registered after the built-in graph is installed, discoverable through registry APIs without adding an attribute to the frozen DType namespace. |
| ## Requirements | |
| ### Requirement: Every dtype has one registered descriptor identity |
Constructing a concrete descriptor SHALL atomically register that descriptor
under its name. name names the descriptor's unique registry key. name
SHALL be a non-empty string and SHALL be unique within the process. When
name is empty or is not a string, construction SHALL fail with ValueError;
when name is already registered, construction SHALL fail with ValueError.
A failed construction SHALL publish neither a registry entry nor a partially
usable descriptor.
Descriptors SHALL compare and hash by object identity. name SHALL return the
registered string, and the read-only compatibility property value SHALL
return that same string.
Scenario: Register a descriptor¶
- WHEN a caller constructs a valid concrete descriptor under an unused name
- THEN the returned object is the sole descriptor registered under that
name and its
nameandvalueproperties return the supplied string
Scenario: Reject a duplicate name atomically¶
- WHEN a caller constructs a descriptor under a name that is already registered
- THEN construction fails with
ValueErrorand the original descriptor remains the registry identity for that name
Requirement: Descriptor kinds and hierarchy are explicit¶
DType and CompoundDType SHALL be abstract, as SHALL a descriptor subclass
that does not declare abstract=False. In a descriptor subclass declaration,
abstract states whether the subclass remains non-constructible. abstract
SHALL be optional and SHALL default to True; abstract=False SHALL declare
the subclass concrete. Attempting to instantiate an abstract descriptor class
SHALL fail with TypeError. Every constructible descriptor SHALL be a
DTypeCategory, SimpleDType, or concrete CompoundDType.
For every descriptor, is_category(), is_simple(), and is_compound() SHALL
identify its representation kind. supertype SHALL return its immediately
enclosing category or None; supertypes() SHALL return all enclosing
categories from nearest to outermost. is_subtype_of(other) SHALL return
True when the descriptor is other or reaches other through that category
chain, and SHALL fail with TypeError when other is not a DType.
The public descriptor surface SHALL provide no is_opaque_storage attribute.
Reading or calling that removed attribute SHALL fail with AttributeError.
Carrier-specific storage support remains defined by carrier-storage rather
than by a descriptor kind or category property.
Scenario: Query a hierarchy¶
- WHEN a caller queries
DType.Float32 - THEN it is simple, its immediate supertype is
DType.Floating, its supertypes includeDType.Floatingfollowed byDType.Any, and it is a subtype of each of those identities
Scenario: Reject a non-descriptor subtype query¶
- WHEN
is_subtype_ofreceives an object that is not aDType - THEN it fails with
TypeError
Scenario: Observe removal of the opaque-storage query¶
- WHEN a caller reads
is_opaque_storagefrom any descriptor - THEN the read fails with
AttributeError
Requirement: Simple dtypes declare one exact positive width¶
SimpleDType(name, *, bits, supertype) SHALL construct and return a simple
descriptor. name names the simple dtype's unique registry key and SHALL
satisfy the registered-name contract. bits names the encoding width in bits
and SHALL be an integer other than bool greater than zero. supertype names
the category immediately enclosing the encoding and SHALL be a
DTypeCategory. When bits is invalid, construction SHALL fail with
ValueError; when supertype is invalid, construction SHALL fail with
TypeError. Either failure SHALL occur before name is registered.
The bits property SHALL return the exact integer width. is_simple() SHALL
describe the representation and SHALL remain True even when no carrier
supports that encoding.
Scenario: Construct a simple extension¶
- WHEN a caller constructs
SimpleDType("Float16", bits=16, supertype=DType.Floating)under an unused name - THEN the result is a registered 16-bit simple dtype beneath the Floating and Any categories
Scenario: Reject an invalid width¶
- WHEN
bitsis a boolean, non-integer, zero, or negative - THEN construction fails with
ValueErrorand registers nothing
Requirement: The built-in descriptor graph is stable¶
The built-in categories SHALL be Any, Floating, and Integer. Any SHALL
be the root; Floating and Integer SHALL have Any as their supertype. All
three SHALL remain relationship-only categories that may serve as supertypes
for registered simple or compound descriptors.
The built-in simple dtypes and widths SHALL be:
| Supertype | Simple dtype widths |
|---|---|
DType.Any |
Bool: 8 bits |
DType.Integer |
Int32: 32 bits; Int8: 8 bits |
DType.Floating |
Float32: 32 bits; Float64: 64 bits; E8M0: 8 bits; E5M2: 8 bits; E4M3: 8 bits; E3M2: 6 bits; E2M3: 6 bits; E2M1: 4 bits |
Each built-in SHALL be available as DType.<name> and SHALL be identical to
the object returned by DType.from_name(<name>).
Scenario: Resolve a built-in through both surfaces¶
- WHEN a caller reads
DType.Float32and callsDType.from_name("Float32") - THEN both expressions return the same descriptor object
Scenario: Retain categories as extension supertypes¶
- WHEN a caller registers a valid
SimpleDTypewhose supertype isDType.Floating - THEN the descriptor joins the Floating and Any hierarchy even though those categories are not physical storage representations
Requirement: Registry discovery is class-narrowed¶
DType.registered() SHALL return an immutable snapshot of all registered
descriptors. Calling registered() on a descriptor subclass SHALL return only
registered instances of that subclass.
DType.from_name(name) SHALL return the registered identity whose exact name
matches name; calling it on a subclass SHALL additionally require the result
to be an instance of that subclass. A non-string name SHALL fail with
TypeError. An unknown name or a name registered to a different descriptor
kind SHALL fail with LookupError.
Scenario: Discover extension dtypes¶
- WHEN a caller registers a new
SimpleDType - THEN it appears in both
DType.registered()andSimpleDType.registered()and resolves from both classes by name
Scenario: Reject a class-mismatched lookup¶
- WHEN
SimpleDType.from_namereceives the name of a category - THEN it fails with
LookupError
Requirement: Published descriptors are immutable¶
After successful construction, assigning or deleting descriptor attributes
SHALL fail with AttributeError. Shallow copy and deep copy SHALL return the
same descriptor identity. repr(descriptor) SHALL identify its descriptor
kind and registered name.
The descriptor model SHALL own the state and accessors that determine its
kind, hierarchy, structure, planes, and representation. A descriptor subclass
that shadows model-owned members directly or through a base class SHALL fail
with TypeError when the class is defined. Assigning or deleting a model-owned
class member later SHALL fail with AttributeError.
Scenario: Preserve identity through copying¶
- WHEN a caller shallow-copies or deep-copies a registered descriptor
- THEN each result is the original object
Scenario: Refuse an extension that shadows descriptor identity¶
- WHEN a descriptor subclass defines a model-owned accessor such as
name,bits,simple_types, orstructure - THEN class creation fails with
TypeError
Requirement: Descriptor structure is canonical and extensible¶
structure() SHALL return the immutable structure recorded once at successful
finalization. It SHALL include the descriptor contracts, the complete
structures of every referenced descriptor, and the result of
structure_extension(). Referenced descriptors SHALL already be canonical
registered identities. A category's canonical contract structure SHALL
describe its relationship kind and supertype and SHALL contain no storage
disposition field or value.
structure_extension() SHALL default to (). An extension implementation MAY
override it to return a tuple of exact strings, numbers, None, Whole, and
nested tuples of those values. A non-tuple result SHALL fail with TypeError;
an unsupported value within the tuple SHALL fail with TypeError. A structure
extension SHALL participate in pickle compatibility and in every structural
uniqueness rule imposed by the descriptor kind.
Scenario: Distinguish extension representations¶
- WHEN two extension descriptors have different permitted values in their
structure_extension()tuples - THEN their recorded structures are different even if their inherited descriptor fields otherwise agree
Scenario: Reject an unregistered reference¶
- WHEN a descriptor attempts to use an unfinished or rejected descriptor as its supertype or representation component
- THEN construction fails with
ValueErrorand registers nothing
Scenario: Record a category without storage disposition¶
- WHEN a caller reads
structure()fromDType.Any,DType.Floating, or an extension category - THEN the returned canonical structure contains its category hierarchy and no opaque-storage field or value
Requirement: Pickle reconstruction preserves receiving-process identity¶
Serializing a descriptor SHALL record its registered name and complete structure, not a new descriptor definition. Deserializing SHALL return the receiving process's already registered descriptor with that name when its complete structure matches.
If the name is not registered in the receiving process, deserialization SHALL
fail with LookupError. If the name is registered to a descriptor with a
different structure, deserialization SHALL fail with ValueError rather than
substituting that descriptor. A payload whose category structure contains the
removed opaque-storage disposition SHALL therefore be incompatible with the
new relationship-only category structure and SHALL fail with ValueError.
Scenario: Unpickle a registered extension¶
- WHEN the receiving process has registered a structurally matching extension under the serialized name
- THEN deserialization returns that receiving-process descriptor identity
Scenario: Reject a mismatched receiving definition¶
- WHEN the receiving process registered the serialized name with a different width, hierarchy, plane, rule, scale, or extension structure
- THEN deserialization fails with
ValueError
Scenario: Reject a legacy category structure¶
- WHEN a serialized descriptor recursively contains a category structure with the removed opaque-storage disposition
- THEN deserialization against the relationship-only registered graph
fails with
ValueErrorrather than substituting a descriptor
Requirement: The DType class namespace contains only built-ins¶
Successful extension registration SHALL leave the attributes of DType
unchanged; extensions SHALL be reached through registered() and
from_name(). Reassigning or deleting a built-in DType binding SHALL fail
with AttributeError. Assigning an extension descriptor as a new DType
attribute SHALL fail with AttributeError.
Scenario: Register without extending the class namespace¶
- WHEN a caller registers an extension named
Float16 - THEN
DType.from_name("Float16")returns it andDType.Float16remains unavailable
Requirement: Categories describe hierarchy relationships¶
Within the dtype descriptor model, a category SHALL mean a DTypeCategory
that organizes descriptors in an abstract supertype hierarchy. A category
SHALL be a relationship identity rather than a physical storage
representation; DType.Any, DType.Floating, DType.Integer, and registered
extension categories SHALL all follow that same definition.
DTypeCategory(name, *, supertype=None) SHALL construct and return a category
descriptor. name names the category's unique registry key and SHALL satisfy
the registered-name contract. supertype names the category's immediately
enclosing category; it SHALL be optional, SHALL default to None for a root
category, and when provided SHALL be a registered DTypeCategory. When
supertype is neither None nor a DTypeCategory, construction SHALL fail
with TypeError before registering name. When supertype is a
DTypeCategory object but is unfinished, was rejected during registration, or
is not the canonical identity registered under its name, construction SHALL
fail with ValueError before registering name.
The constructor SHALL accept supertype only as a keyword argument. Supplying
the removed opaque_storage keyword SHALL fail with TypeError identifying an
unexpected keyword and SHALL register nothing.
Scenario: Construct a category extension¶
- WHEN a caller constructs a category with a unique name and a registered
category as its
supertype - THEN the result is registered, reports
is_category() == True, and joins the supplied category chain
Scenario: Reject the removed storage disposition¶
- WHEN a caller supplies
opaque_storagetoDTypeCategory - THEN construction fails with
TypeErrorbefore the requested name is registered
Scenario: Reject a non-category supertype¶
- WHEN a caller supplies a non-category descriptor or another non-category
value as
supertype - THEN construction fails with
TypeErrorbefore the requested name is registered
Scenario: Reject a noncanonical category supertype¶
- WHEN a caller supplies an unfinished, rejected, or noncanonical
DTypeCategoryobject assupertype - THEN construction fails with
ValueErrorbefore the requested name is registered