Skip to content
Merged
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 quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ generic std gap is planned here even when moq never calls it.
- [Waiting: type-check in process with tsrs](/quest/m3/ts-tsrs.md) - rust2-ts checks bindings through tsrs instead of `tsc` once it is a stable library
- [Drop order in std's folds and iterators](/quest/m3/ts-drop-order.md) - the values that drop still refused in std's consumers, flattens, and collects drop as std's do
- [A slice of one value behind any &mut](/quest/m3/ts-slice-of-one.md) - `slice::from_mut` and `array::from_mut` of a `&mut u8`, or of an object no place names, translate
- [std's calls of a closure that have no mapping](/quest/m3/ts-closure-calls.md) - `try_fold`, `partition`, `repeat_with`, `sort_by_cached_key`, and `LazyCell::new` translate, dropping what their closures own as std's do
- [A closure that drops given to a string's edit or search](/quest/m3/ts-string-closures.md) - `String::retain` and `str`'s searches by a closure that owns a value that drops translate
- [Waiting: a slice object for a mutable part of other values](/quest/m3/ts-slice-object.md) - waits on a moq profile showing the `Proxy` view's traps matter, then decides on an `rt.ByteSlice`-like form
- [Port the workflow guard to kixelated/quest](/quest/m3/quest-workflow-guard.md) - quest's environment guard parses YAML as this repository's does
- [A deque's two slices](/quest/m3/ts-deque-slices.md) - `VecDeque::as_slices` and `{:?}` of a deque's `Iter`, `IterMut`, and `Drain` translate, split where std's are
Expand Down
26 changes: 26 additions & 0 deletions quest/m3/ts-closure-calls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# [M] std's calls of a closure that have no mapping

## Goal

[rust2-ts](/ts/README.md) translates std's functions that take a closure and are refused
as "unsupported call" whatever the closure holds, each calling it and dropping what it
owns as std's does, proven by the task fixture's differential tests against native Rust.

## Plan

Found probing std's consumers for [drop order](/quest/m3/ts-drop-order.md) in
[#438](https://github.com/moq-dev/rust2/pull/438). Of a closure that owns nothing, each of
these is refused today:

- `Iterator::try_fold`, `try_for_each`, and `partition`. Folds from the back, `rfold` and
`try_rfold`, are [#436](https://github.com/moq-dev/rust2/pull/436)'s
[`ts-iter-back-folds`](https://github.com/moq-dev/rust2/blob/quest/m2/ts-model/iter-traits/quest/m3/ts-iter-back-folds.md).
- `iter::repeat_with`, and `Iterator::scan` of a state JS copies, which is refused as a
`&mut` its mapping would copy.
- `slice::sort_by_cached_key`.
- `LazyCell::new`, `Cell::update`, and `RefCell::replace_with` of a value JS copies.

Each `rt.Iter` has a `fold` and `rfold` that drop what it holds where std's do: a consumer
that takes the iterator by value builds on them, as `rt.iterFold` does.

Public API: the translator's output, and the runtime's functions each needs.
12 changes: 4 additions & 8 deletions quest/m3/ts-drop-order.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@ drop refusal left ([#139](https://github.com/moq-dev/rust2/pull/139)). `DebugLis
ranges of bounds that drop, a drain or a B-tree's `range` of a range that drops, a hash
map's `into_keys` and `into_values`, and the closures `for_each` and `fold` own landed in
[#307](https://github.com/moq-dev/rust2/pull/307), with the task fixture's `inside` step.
The closures `reduce`, `max_by`, `min_by`, their `_by_key` forms, `is_sorted_by_key`, and
a map's entries' `or_insert_with`, `or_insert_with_key`, and `and_modify` own landed in
[#438](https://github.com/moq-dev/rust2/pull/438), with its `released` step.
Each left is refused with a span where std's order is one JS's can't follow yet:

- A closure that owns a value that drops given to a std function that takes another
value that drops by value, other than `for_each` and `fold` (`iter::releases`), such as
`reduce`, `max_by_key`, or `partition` of items that drop; one that keeps it other
than in an adaptor; or one that calls it through `FnOnce` other than where `discards`
in `library.rs` says, as `or_insert_with` does (`called_closures`). Each consumer whose
std folds takes a `release` the way `rt.iterFold` does. The reject fixture's
`called_closure` reproduces `or_insert_with`.
- A `skip` of a `zip` of two `TrustedRandomAccess` iterators of items that drop, as the
reject fixture's `skipped_zip`: std's `Skip` read by index, as a zip by index or `take`'s
fold reads it, makes and drops each skipped pair whole, where its `next` skips through
Expand All @@ -42,7 +38,7 @@ Each left is refused with a span where std's order is one JS's can't follow yet:
impls, as `v.into_iter().collect::<BTreeSet<O>>()` of an `O` whose `Ord`, `PartialOrd`,
or `PartialEq` is its own: one that panics or disagrees with itself leaves equal keys
in the order [std's sort](/quest/m3/ts-sort-order.md) does, which decides which of them
drop.
drop. It follows that port of std's sorts, whose plan names it.

Each `rt.Iter` has a `fold` and `rfold` that drop what it holds where std's do, and the
by-value consumers std folds go through it: build on those rather than `rt.drop`.
Expand Down
18 changes: 18 additions & 0 deletions quest/m3/ts-string-closures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# [S] A closure that drops given to a string's edit or search

## Goal

[rust2-ts](/ts/README.md) translates a closure that owns a value that drops given to
`String::retain`, or to `str`'s searches that map as a `Pattern`, such as `contains` and
`split`, dropping it where std's does, proven by the task fixture's differential tests
against native Rust.

## Plan

Found beside [drop order](/quest/m3/ts-drop-order.md) in
[#438](https://github.com/moq-dev/rust2/pull/438). The reject fixture's `string_retained`
and `pattern_closure` reproduce them. `String::retain` borrows the string and drops its
closure as it returns. A search that returns an iterator, such as `split`, holds the
pattern until the iterator drops; one that returns a value drops it before returning.

Public API: the translator's output.
3 changes: 3 additions & 0 deletions ts/MIGRATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- `rt.iterReduce`, `rt.iterMaxBy`, `rt.iterMinBy`, `rt.iterMaxByKey`, and
`rt.iterMinByKey` take whether they own their closure, which they drop where std's do,
before the `rt.None` they take last, as in `rt.iterReduce(it, f, drops, owns, none)`.
- `rt.Hasher` has `Hasher`'s methods, `write`, `u8` to `isize`, `prefix`
(`write_length_prefix`), and `str`, and `ints`, an integer slice's `hash_slice`, in
place of `word`. A binding's `hash$Hash` writes a signed or pointer-sized integer
Expand Down
6 changes: 3 additions & 3 deletions ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -849,9 +849,9 @@ behind `&`, `&mut`, `Box`, or `Arc` ([trait objects](/quest/m3/ts-dyn.md)), fail
hand-written TS ([bindings](#bindings)).

These fail translation: `f16` and `f128`, a `Poll` of a `Poll` of a `Poll`, a future whose output can be pending, an instance of a generic type whose field is a `Poll` of a type parameter that can be pending, a closure that owns a value
that drops given to a std function that drops it beside another value that drops, other
than `for_each` and `fold`, as `reduce` of items that drop does, or keeps it other than in
an iterator adaptor, and values that drop in some iterators ([drop order](/quest/m3/ts-drop-order.md)), a `Cow` of other than `str` or a slice, a std
that drops given to a std function that keeps it other than in an iterator or a
`poll_fn`, or whose mapping doesn't drop it where std's does, and values that drop in some
iterators ([drop order](/quest/m3/ts-drop-order.md)), a `Cow` of other than `str` or a slice, a std
function without a mapping of its own that makes or reads an `Option` whose `None` is
`rt.None`, as `Iterator::scan` of `Option`s does, an `Option` of an `Option` of `()` or another
`Option`, an instance of a generic type whose field is an `Option` of a type parameter
Expand Down
16 changes: 8 additions & 8 deletions ts/fixtures/lang/expected/nested.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,22 +285,22 @@ export function consumers(data: rt.ByteSlice, out: rt.ByteVec): void {
return option_map$0cs071d(o2, (b4: rt.u8): rt.u8 => {
return rt.u8Rem(b4, 4);
});
}, rt.cmpLt(rt.cmpOption(rt.cmp)), undefined, undefined, rt.None)));
}, rt.cmpLt(rt.cmpOption(rt.cmp)), undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterMinByKey(it(), (o3: rt.u8 | undefined): rt.u8 | undefined => {
return option_map$0cs071d(o3, (b5: rt.u8): rt.u8 => {
return rt.u8Rem(b5, 4);
});
}, rt.cmpLt(rt.cmpOption(rt.cmp)), undefined, undefined, rt.None)));
}, rt.cmpLt(rt.cmpOption(rt.cmp)), undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterMaxByKey(it(), (o4: rt.u8 | undefined): rt.u8 | undefined | rt.None => {
return option_map$0rbsrz6(o4, (b6: rt.u8): rt.u8 | undefined => {
return thenSome$0d5am30(rt.u8Rem(b6, 4) !== 0, rt.u8Rem(b6, 3));
});
}, rt.cmpLt(rt.cmpOption(rt.cmpOption(rt.cmp), rt.None)), undefined, undefined, rt.None)));
}, rt.cmpLt(rt.cmpOption(rt.cmpOption(rt.cmp), rt.None)), undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterMinByKey(it(), (o5: rt.u8 | undefined): rt.u8 | undefined | rt.None => {
return option_map$0rbsrz6(o5, (b7: rt.u8): rt.u8 | undefined => {
return thenSome$0d5am30(rt.u8Rem(b7, 4) !== 0, rt.u8Rem(b7, 3));
});
}, rt.cmpLt(rt.cmpOption(rt.cmpOption(rt.cmp), rt.None)), undefined, undefined, rt.None)));
}, rt.cmpLt(rt.cmpOption(rt.cmpOption(rt.cmp), rt.None)), undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterFind(rt.iterSlice(items), (o6: rt.u8 | undefined): boolean => {
return o6 === undefined;
}, undefined, rt.None)));
Expand All @@ -322,16 +322,16 @@ export function consumers(data: rt.ByteSlice, out: rt.ByteVec): void {
return rt.u8Rem(b10, 4);
});
return rt.cmpOption(rt.cmp)(_511, _8);
}, undefined, undefined, rt.None)));
}, undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterMinBy(it(), (a03: rt.u8 | undefined, a1: rt.u8 | undefined): rt.Ordering => {
return rt.cmpOption(rt.cmp)(a03, a1);
}, undefined, undefined, rt.None)));
}, undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterMaxBy(it(), (_27: rt.u8 | undefined, _318: rt.u8 | undefined): rt.Ordering => {
return 0;
}, undefined, undefined, rt.None)));
}, undefined, undefined, undefined, rt.None)));
rt.byteVecPush(out, code(rt.iterReduce(it(), (a2: rt.u8 | undefined, b11: rt.u8 | undefined): rt.u8 | undefined => {
return xor$0kctyix(a2, b11);
}, undefined, rt.None)));
}, undefined, undefined, rt.None)));
const written: rt.Peekable<rt.u8 | undefined> = rt.iterPeekable(it());
const _139: rt.Place<rt.u8 | undefined> | undefined = rt.peekablePeekMut(written, true);
if (_139 !== undefined) {
Expand Down
5 changes: 2 additions & 3 deletions ts/fixtures/lang/expected/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,13 @@ export function sorted(data: rt.ByteSlice, out: rt.ByteVec): void {
}), true, rt.drop, rt.drop) ? 1 : 0);
const _108: rt.Iter<orders_Item.Item> = items();
const captured3 = k;
const _110: (a0: orders_Item.Item) => rt.u8 = rt.closure((x4: orders_Item.Item): rt.u8 => {
rt.byteVecPush(out, rt.iterIsSortedBy(rt.iterMap(_108, rt.closure((x4: orders_Item.Item): rt.u8 => {
const _012: rt.u8 = rt.u8Add(x4.key, captured3.key);
x4[Symbol.dispose]();
return _012;
}, (): void => {
captured3[Symbol.dispose]();
});
rt.byteVecPush(out, rt.dropAfter(_110, () => rt.iterIsSortedBy(rt.iterMap(_108, _110), rt.le)) ? 1 : 0);
})), rt.le, true) ? 1 : 0);
const captured4 = l;
const key: (a0: orders_Item.Item) => rt.u8 = rt.closure((x5: orders_Item.Item): rt.u8 => {
const _013: rt.u8 = rt.u8Add(x5.key, captured4.key);
Expand Down
Loading