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
1 change: 0 additions & 1 deletion quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ generic std gap is planned here even when moq never calls it.
- [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
- [std::iter::zip](/quest/m3/ts-iter-zip.md) - the free `zip` translates as `Iterator::zip` does
- [std's sorts call their tests in std's order](/quest/m3/ts-sort-order.md) - `slice::sort` and a B-tree's `collect` call `lt` or `cmp` as std's driftsort does past 16 elements
- [A B-tree's searches call Ord as std's do](/quest/m3/ts-btree-search-order.md) - a B-tree's lookups and inserts call a key's own `Ord` in std's order and number
- [Rc and Arc of a slice](/quest/m3/ts-shared-slices.md) - `Rc<[T]>` and `Arc<[T]>` from a `Vec`, a slice, or an iterator translate
Expand Down
14 changes: 0 additions & 14 deletions quest/m3/ts-iter-zip.md

This file was deleted.

366 changes: 243 additions & 123 deletions ts/fixtures/lang/expected/arrays.ts

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions ts/fixtures/lang/expected/core/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,13 @@ export function map$0po44cb(self: undefined[] | undefined, f: (a0: undefined[])
return f(self);
}

export function map$0p6o7wa(self: Uint8Array | undefined, f: (a0: Uint8Array) => Uint8Array): Uint8Array | undefined {
if (self === undefined) {
return undefined;
}
return f(self);
}

export function map$1iekgsb(self: bounds_Item.Item | undefined, f: (a0: bounds_Item.Item) => rt.u8): rt.u8 | undefined {
if (self === undefined) {
return undefined;
Expand Down
21 changes: 19 additions & 2 deletions ts/fixtures/lang/src/arrays.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,8 @@ where
}

/// Arrays of bytes reached through the iterator std makes of each item: of an `Option`, a
/// nested one, a `Vec`, a slice, and an array, by `flatten`, `flat_map`, `chain`, `zip`,
/// `extend`, `from_iter`, and `DebugList::entries`, read from both ends and written through.
/// nested one, a `Vec`, a slice, and an array, by `flatten`, `flat_map`, `chain`, `zip`
/// and the free `zip`, `extend`, `from_iter`, and `DebugList::entries`, read from both ends and written through.
/// Of no bytes, one, and many.
pub fn flattened(kind: u8, data: &[u8], out: &mut Vec<u8>) {
match kind % 3 {
Expand Down Expand Up @@ -497,6 +497,23 @@ fn flattened_n<const N: usize>(data: &[u8], out: &mut Vec<u8>) {
for (a, b) in options.iter_mut().flatten().zip(&mut other) {
std::mem::swap(a, b);
}
// The free `zip` takes each side as `IntoIterator`, a `&mut` to a collection lending its places.
for (b, a) in std::iter::zip(&other, options.iter().flatten()) {
out.extend_from_slice(b);
out.extend_from_slice(a);
}
for (b, a) in std::iter::zip(&mut other, &mut options) {
b.rotate_left(N.min(1));
*a = a.map(|mut a| {
a.fill(b.first().copied().unwrap_or(0x33));
a
});
}
let mut sums: Vec<u16> = data.iter().map(|&b| u16::from(b)).collect();
for (x, (i, y)) in std::iter::zip(&mut sums, data.iter().enumerate().rev()) {
*x = x.wrapping_mul(31) ^ u16::from(*y) << (i % 8);
}
out.extend(sums.iter().flat_map(|x| x.to_le_bytes()));
for a in other.iter_mut().chain(&mut options[3]) {
a.fill(0x5a);
}
Expand Down
54 changes: 38 additions & 16 deletions ts/src/lower/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,12 @@ pub fn call<'tcx>(
return Some(Expr::rt("iterOnce", tail(args, vec![dropper])));
}
["iter", "sources", "empty", "empty"] => return Some(Expr::rt("iterEmpty", Vec::new())),
// `a.into_iter().zip(b)`, as std's is.
["iter", "adapters", "zip", "zip"] => {
let [a, other] = <[Expr; 2]>::try_from(args).ok()?;
let a = into_iter(b, targ(0)?, a, span)?;
return zip(b, a, targ(1)?, other, b.t.sig(call.def_id, gargs).output(), span);
}
// A closure that owns a value that drops is refused as any std mapping refuses one
// it calls but never drops.
// Each takes its closure's `None` last, where that is `rt.None`.
Expand Down Expand Up @@ -657,22 +663,14 @@ pub fn call<'tcx>(
let other = into_iter(b, targ(1)?, rest.into_iter().next()?, span)?;
method(name, vec![other])
}
"zip" => {
let other_ty = targ(1)?;
let other = into_iter(b, other_ty, rest.into_iter().next()?, span)?;
let zip = b.t.sig(call.def_id, gargs).output();
let ty::Adt(_, sides) = zip.kind() else {
return None;
};
let (a, other_iter) = (sides.type_at(0), sides.type_at(1));
let other_item = b.t.iter_item(other_iter)?;
let droppers = vec![
zip_trusted(b, a, other_iter, span),
b.t.dropper(item, span),
b.t.dropper(other_item, span),
];
method(name, tail(vec![other], droppers))
}
"zip" => zip(
b,
recv,
targ(1)?,
rest.into_iter().next()?,
b.t.sig(call.def_id, gargs).output(),
span,
),
// `flat_map::<U, F>`, of the source mapped by `F`, which drops as the source does.
"flat_map" => {
let inner = iter_of(b.t, targ(1)?)?;
Expand Down Expand Up @@ -1128,6 +1126,30 @@ fn flattens<'tcx>(b: &mut Body<'_, '_, 'tcx>, inner: Ty<'tcx>, span: Span) {
}
}

/// `rt.iterZip` of `a`, an iterator, and `other`, of type `other_ty`, into `zip`, the `Zip`
/// of their iterators.
fn zip<'tcx>(
b: &mut Body<'_, '_, 'tcx>,
a: Expr,
other_ty: Ty<'tcx>,
other: Expr,
zip: Ty<'tcx>,
span: Span,
) -> Option<Expr> {
let other = into_iter(b, other_ty, other, span)?;
let ty::Adt(_, sides) = zip.kind() else {
return None;
};
let (a_iter, other_iter) = (sides.type_at(0), sides.type_at(1));
let (item, other_item) = (b.t.iter_item(a_iter)?, b.t.iter_item(other_iter)?);
let droppers = vec![
zip_trusted(b, a_iter, other_iter, span),
b.t.dropper(item, span),
b.t.dropper(other_item, span),
];
Some(Expr::rt("iterZip", tail(vec![a, other], droppers)))
}

/// `rt.Trusted`, how std's `Zip` of `a` and `b` reads them, by the traits it specializes
/// on: by index if both are `TrustedRandomAccess`, as whether each may have side effects,
/// and folded by its size hint if both are `TrustedLen`, or `TrustedRandomAccessNoCoerce`,
Expand Down
3 changes: 2 additions & 1 deletion ts/src/lower/mir/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
// item a `Peekable` peeked, the place a `&mut dyn Any` wraps, a `RefCell` key's value,
// a `Result`'s payload, the value of an `Arc`, a lock, or a cell, what a write guard
// lends its map or its leak, or what `zip` makes of the collection it is given by
// `into_iter`.
// `into_iter`, as the free `zip` does of either.
let lends = match library::key(tcx, def_id) {
Some((owner, name)) => match (owner.as_str(), name.as_str()) {
("slice", "get_mut" | "first_mut" | "last_mut" | "iter_mut" | "split_first_mut" | "split_last_mut")
Expand All @@ -383,6 +383,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
) => true,
("IntoIterator", "into_iter") => gargs.types().next().is_some_and(into_places),
("Iterator", "zip") => gargs.types().nth(1).is_some_and(into_places),
("zip", "zip") => gargs.types().take(2).any(into_places),
_ => false,
},
None => false,
Expand Down