@@ -258,40 +258,38 @@ defined by its parent component).
258
258
The ` HandleTable ` class is defined in terms of a collection of supporting
259
259
runtime bookkeeping classes that we'll go through first.
260
260
261
- The ` Resource ` class represents a runtime instance of a resource type:
261
+ The ` Resource ` class represents a runtime instance of a resource type, storing
262
+ the core representation value (which is currently fixed to ` i32 ` ):
262
263
``` python
264
+ @dataclass
263
265
class Resource :
264
- t: ResourceType
265
266
rep: int
266
-
267
- def __init__ (self , t , rep ):
268
- self .t = t
269
- self .rep = rep
270
267
```
271
- The ` t ` field points to the [ ` resourcetype ` ] ( Explainer.md#type-definitions )
272
- used to create this ` Resource ` and is used to perform dynamic type checking
273
- below. The ` rep ` field stores the representation value of this ` Resource ` whose
274
- type is currently fixed to ` i32 ` as described in the Explainer.
275
268
276
269
The ` OwnHandle ` and ` BorrowHandle ` classes represent runtime handle values of
277
270
` own ` and ` borrow ` type, resp:
278
271
``` python
279
272
class Handle :
280
273
resource: Resource
274
+ rt: ResourceType
281
275
lend_count: int
282
276
283
- def __init__ (self , resource ):
277
+ def __init__ (self , resource , rt ):
284
278
self .resource = resource
279
+ self .rt = rt
285
280
self .lend_count = 0
286
281
287
282
class OwnHandle (Handle ): pass
288
283
class BorrowHandle (Handle ): pass
289
284
```
290
285
The ` resource ` field points to the resource instance this handle refers to. The
291
- ` lend_count ` field maintains a count of the outstanding handles that were lent
292
- from this handle (by calls to ` borrow ` -taking functions). This count is used
293
- below to dynamically enforce the invariant that a handle cannot be dropped
294
- while it has currently lent out a ` borrow ` .
286
+ ` rt ` field points to a runtime value representing the static
287
+ [ ` resourcetype ` ] ( Explainer.md#type-definitions ) of this handle and is used by
288
+ dynamic type checking below. Lastly, the ` lend_count ` field maintains a count
289
+ of the outstanding handles that were lent from this handle (by calls to
290
+ ` borrow ` -taking functions). This count is used below to dynamically enforce the
291
+ invariant that a handle cannot be dropped while it has currently lent out a
292
+ ` borrow ` .
295
293
296
294
The ` Call ` class represents a single runtime call (activation) of a
297
295
component-level function. A ` Call ` is finished in two steps by ` finish_lift `
@@ -368,13 +366,16 @@ use-after-free:
368
366
def get (self , i , rt ):
369
367
trap_if(i >= len (self .array))
370
368
trap_if(self .array[i] is None )
371
- trap_if(self .array[i].resource.t is not rt)
369
+ trap_if(self .array[i].rt is not rt)
372
370
return self .array[i]
373
371
```
374
372
Additionally, the ` get ` method takes the runtime resource type tag and checks
375
- a tag match before returning the handle with this new-valid resource type. Note
376
- that this is a non-structural, pointer-equality-based check to implement the
377
- [ type-checking rules] ( Explainer.md ) of resource types.
373
+ a tag match before returning the handle with this new-valid resource type. This
374
+ check is a non-structural, pointer-equality-based test used to enforce the
375
+ [ type-checking rules] ( Explainer.md ) of resource types at runtime. Importantly,
376
+ this check keeps type imports abstract, considering each type import to have a
377
+ unique ` rt ` value distinct from every other type import even if the two imports
378
+ happen to be instantiated with the same resource type at runtime.
378
379
379
380
The ` lend ` method is called when borrowing a handle. ` lend ` uses ` Call.lenders `
380
381
to decrement the handle's ` lend_count ` at the end of the call.
@@ -978,16 +979,18 @@ Finally, `own` and `borrow` handles are lowered by inserting them into the
978
979
current component instance's ` HandleTable ` :
979
980
``` python
980
981
def lower_own (cx , resource , rt ):
981
- assert (resource.t is rt)
982
- h = OwnHandle(resource)
982
+ h = OwnHandle(resource, rt)
983
983
return cx.inst.handles.insert(cx, h)
984
984
985
985
def lower_borrow (cx , resource , rt ):
986
- assert (resource.t is rt)
987
- h = BorrowHandle(resource)
986
+ h = BorrowHandle(resource, rt)
988
987
return cx.inst.handles.insert(cx, h)
989
988
```
990
- The assertions are ensured by validation.
989
+ Note that the ` rt ` value that is stored in the runtime ` Handle ` captures what
990
+ is statically known about the handle right before losing this information in
991
+ the homogeneous ` HandleTable ` . Moreoever, as described above, distinct type
992
+ imports are given distinct ` rt ` values so that handles produced by lowering
993
+ different type imports are never interchangeable.
991
994
992
995
### Flattening
993
996
@@ -1564,7 +1567,7 @@ Calling `$f` invokes the following function, which creates a resource object
1564
1567
and inserts it into the current instance's handle table:
1565
1568
``` python
1566
1569
def canon_resource_new (cx , rt , rep ):
1567
- h = OwnHandle(Resource(rt, rep))
1570
+ h = OwnHandle(Resource(rep), rt )
1568
1571
return cx.inst.handles.insert(cx, h)
1569
1572
```
1570
1573
0 commit comments