Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions design/mvp/Binary.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ Notes:
rejects any transitive use of `borrow` in an exported value type.
* Validation of `stream` and `future` rejects element types that transitively
contain a `borrow`.
* Validation of `map` rejects value types that transitively contain an `own`,
`borrow`, `future`, `stream` or `error-context`.
* Validation of `stream` rejects `(stream char)` as a temporary
[TODO](Concurrency.md#TODO).
* Validation of `resourcetype` requires the destructor (if present) to have
Expand Down
6 changes: 5 additions & 1 deletion design/mvp/Explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,11 @@ original list defines the final value of the key. However, bindings generators
are not *required* to deduplicate keys and may instead simply present the
original list to guest code. To simplify bindings generation, `<keytype>` is a
conservative subset of `<valtype>`, but this subset could be expanded over time
based on use cases.
based on use cases. Similarly, validation currently rejects `(map K V)` when `V`
transitively contains an `own`, `borrow`, `future`, `stream` or
`error-context`, since dropping the value of a duplicate key would otherwise
require bindings generators to correctly dispose of the contained handles. This
restriction could be relaxed in the future.

Note that, at least initially, variants must have a non-empty list of
cases. This could be relaxed in the future to allow an empty list of cases, with
Expand Down
2 changes: 2 additions & 0 deletions design/mvp/WIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,8 @@ meanings though so they're also provided as first-class types.
values but is meant to be represented by bindings generators in the source
language as a mapping from keys to values (e.g., as an associative array or or
hash table) where, in the case of duplicate keys, the last key's value is used.
Currently, the value type of a `map` may not transitively contain an owned or
borrowed handle, `future`, `stream` or `error-context`.

The `future` and `stream` types are described as part of the [concurrency
explainer](Concurrency.md#streams-and-futures).
Expand Down
1 change: 1 addition & 0 deletions test/nyi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
./values/post-return.wast
./async/big-interleaving-test.wast
./async/forward.wast
./validation/map.wast
85 changes: 85 additions & 0 deletions test/validation/map.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
;; (map K V) validation

(component definition
(type (map bool u8))
(type (map s8 u8))
(type (map u8 u8))
(type (map s16 u8))
(type (map u16 u8))
(type (map s32 u8))
(type (map u32 u8))
(type (map s64 u8))
(type (map u64 u8))
(type (map char u8))
(type (map string u8))
(type (map string f64))
(type (map string string))
(type (map string (list u8)))
(type (map string (tuple u8 string)))
(type (map string (record (field "a" u32) (field "b" string))))
(type (map string (variant (case "a") (case "b" u32))))
(type (map string (enum "x" "y")))
(type (map string (flags "p" "q")))
(type (map string (option string)))
(type (map string (result u32 (error string))))
(type (map string (map u32 (list string))))
(type (list (map string u32)))
(type (option (map u32 string)))
(type (stream (map string u32)))
(type (future (map string u32)))
(type (func (param "m" (map string u32)) (result (map u32 string))))
)

(assert_invalid
(component (type (map f32 u8)))
"invalid map key type")
(assert_invalid
(component (type (map (list u8) u8)))
"invalid map key type")
(assert_invalid
(component (type (map (tuple u8 u8) u8)))
"invalid map key type")
(assert_invalid
(component
(type $R (resource (rep i32)))
(type (map (own $R) u8)))
"invalid map key type")
(assert_invalid
(component
(type $R (resource (rep i32)))
(type (map u32 (own $R))))
"map value type cannot contain a handle")
(assert_invalid
(component
(type $R (resource (rep i32)))
(type (map string (option (borrow $R)))))
"map value type cannot contain a handle")
(assert_invalid
(component
(type (map string (record (field "f" (future u8))))))
"map value type cannot contain a handle")
(assert_invalid
(component
(type (map u8 (list (stream u8)))))
"map value type cannot contain a handle")
(assert_invalid
(component
(type $FT (future))
(type (map char (variant (case "a") (case "b" $FT)))))
"map value type cannot contain a handle")
(assert_invalid
(component
(type $R (resource (rep i32)))
(type $Rec (record (field "r" (own $R))))
(type (map u32 $Rec)))
"map value type cannot contain a handle")
(assert_invalid
(component
(type $R (resource (rep i32)))
(type (map string (map string (tuple u32 (own $R))))))
"map value type cannot contain a handle")
(assert_invalid
(component
(import "r" (type $R (sub resource)))
(import "f" (func (param "m" (map string (own $R))))))
"map value type cannot contain a handle")
Loading