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 @@ -35,7 +35,6 @@ generic std gap is planned here even when moq never calls it.
- [A vector's exact capacity as it shrinks](/quest/m3/ts-vec-exact-capacity.md) - a deque made from a `Vec` splits its slices where std's does
- [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
- [Popping a String that is reassigned elsewhere](/quest/m3/ts-reassigned-pop.md) - `pop`, `remove`, and `split_off` of a local some other path assigns whole translate
- [Whether a type needs drop](/quest/m3/ts-needs-drop.md) - `mem::needs_drop::<T>()` translates as rustc's constant for each instance
- [Operator trait methods called by path](/quest/m3/ts-operator-paths.md) - `<u8 as AddAssign>::add_assign` and every other `std::ops` operator method translate called by path or as a value
- [The rest of a vector's methods](/quest/m3/ts-vec-rest.md) - `append`, `resize`, `split_off`, `try_reserve`, and `Vec::from(VecDeque)` translate
Expand Down
30 changes: 0 additions & 30 deletions quest/m3/ts-reassigned-pop.md

This file was deleted.

3 changes: 2 additions & 1 deletion ts/fixtures/lang/pointers/expected/pointers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,9 @@ export function cells(data: rt.ByteSlice, out: rt.ByteVec): void {
_67._1 = _67._1 ^ 128;
rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(before2._0, before2._1, between._0, between._1, pair.v._0, pair.v._1)), undefined, true);
} else if (_23 === 3) {
const _85: rt.char = rt.u8Add(97, rt.u8Rem(n, 26)) as rt.char;
const _83: rt.Place<string> = text;
_83.v = _83.v + String.fromCodePoint(rt.u8Add(97, rt.u8Rem(n, 26)) as rt.char);
_83.v = _83.v + String.fromCodePoint(_85);
const _91: rt.Place<string> = text;
_91.v = _91.v + "!";
rt.iterExtendBytes(out, rt.iterSlice(rt.byteSliceView(rt.stringAsBytes(text.v))), undefined, true);
Expand Down
64 changes: 41 additions & 23 deletions ts/fixtures/lang/strs/expected/strs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,25 +678,41 @@ export function edits(kind: rt.u8, dataData: Uint8Array, dataStart: number, data
const b: rt.u8 = _25[2];
const _39: rt.u8 = rt.u8Div(op, 64);
if (_39 === 0) {
edit(rt.place(() => named.name, (value2) => named.name = value2), op, a, b, out);
edit(rt.place(() => named.name, (value10) => named.name = value10), op, a, b, out);
} else if (_39 === 1) {
const _42: rt.u8 = rt.u8Rem(op, 6);
const _42: rt.u8 = rt.u8Rem(op, 8);
if (_42 === 0) {
s = s + "é/";
const _44: rt.Place<string> = rt.place(() => s, (value9) => s = value9);
_44.v = _44.v + "é/";
} else if (_42 === 1) {
const _47: rt.usize = offset(s, a);
s = rt.stringTruncate(s, _47);
const _46: rt.Place<string> = rt.place(() => s, (value8) => s = value8);
_46.v = rt.stringTruncate(_46.v, _47);
} else if (_42 === 2) {
const edit2 = rt.stringPop(s);
s = edit2[0];
putChar(out, edit2[1]);
const _51: rt.Place<string> = rt.place(() => s, (value7) => s = value7);
const edit4 = rt.stringPop(_51.v);
_51.v = edit4[0];
putChar(out, edit4[1]);
} else if (_42 === 3) {
const _53: rt.usize = offset(s, a);
s = rt.stringInsertStr(s, _53, "😀");
const _56: string = "😀";
const _52: rt.Place<string> = rt.place(() => s, (value6) => s = value6);
_52.v = rt.stringInsertStr(_52.v, _53, _56);
} else if (_42 === 4) {
const _60: rt.Place<string> = rt.place(() => s, (value5) => s = value5);
const _61: rt.usize = offset(s, a);
const edit_ = rt.stringSplitOff(s, _61);
s = edit_[0];
const edit3 = rt.stringSplitOff(_60.v, _61);
_60.v = edit3[0];
put(out, edit3[1]);
} else if (_42 === 5) {
const _66: rt.Place<string> = rt.place(() => s, (value4) => s = value4);
const edit2 = rt.stringRemove(_66.v, 0);
_66.v = edit2[0];
putChar(out, edit2[1]);
} else if (_42 === 6) {
const _70: rt.Place<string> = rt.place(() => s, (value3) => s = value3);
const edit_ = rt.stringSplitOff(_70.v, 1);
_70.v = edit_[0];
put(out, edit_[1]);
} else {
s = "";
Expand All @@ -707,7 +723,8 @@ export function edits(kind: rt.u8, dataData: Uint8Array, dataStart: number, data
put(out, s);
put(out, named.name);
}
put(out, s + "😀" + named.name);
s = s + "😀" + named.name;
put(out, s);
}

/**
Expand Down Expand Up @@ -1447,8 +1464,8 @@ export function hinted(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
const m: rt.u32 = _7[1];
const sub: rt.usize = rt.usizeDiv(option_unwrapOr$0r2bmpr(rt.byteSliceGet(data, 1), 0) as rt.usize, [0, 5, 8, 9, 2147483645, 2147483648, 4294967295].length);
let t: string = "aé";
const _25: rt.Place<string> = rt.place(() => t, (value) => t = value);
const _26: string = text(option_unwrapOr$1rbuegs(rt.byteSliceGetRange(data, 2), rt.byteSliceFrom(Uint8Array.of())));
const _25: rt.Place<string> = rt.place(() => t, (value) => t = value);
_25.v = _25.v + _26;
const calls: rt.Cell<rt.usize> = new rt.Cell(0);
const f: (a0: rt.u32) => rt.char = (_2: rt.u32): rt.char => {
Expand All @@ -1465,20 +1482,20 @@ export function hinted(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
};
const _38: rt.u8 = rt.u8Rem(kind, 10);
if (_38 === 0) {
const _40: rt.Place<string> = rt.place(() => t, (value13) => t = value13);
const _41: rt.Iter<rt.char> = rt.iterMap(new rt.Range(0, n), f);
const _40: rt.Place<string> = rt.place(() => t, (value13) => t = value13);
_40.v = rt.stringExtendChars(_40.v, _41);
} else if (_38 === 1) {
t = rt.stringExtendChars("", rt.iterMap(rt.iterChain(new rt.RangeInclusive(0, n, rt.u32Step), new rt.Range(0, n)), f));
} else if (_38 === 2) {
const _48: rt.Place<string> = rt.place(() => t, (value12) => t = value12);
const _49: rt.Iter<rt.char> = rt.iterSkip(rt.iterMap(new rt.Range(0, rt.u64Or(rt.u64Shl(n as rt.u64, 8), m as rt.u64), rt.u64Step), (i4: rt.u64): rt.char => {
return f(rt.u64Low(i4));
}), m as rt.usize);
const _48: rt.Place<string> = rt.place(() => t, (value12) => t = value12);
_48.v = rt.stringExtendChars(_48.v, _49);
} else if (_38 === 3) {
const _61: rt.Place<string> = rt.place(() => t, (value11) => t = value11);
const _62: rt.Iter<rt.char> = rt.iterTake(rt.iterMap(new rt.Range(0, n), f), m as rt.usize, undefined, true);
const _61: rt.Place<string> = rt.place(() => t, (value11) => t = value11);
_61.v = rt.stringExtendChars(_61.v, _62);
} else if (_38 === 4) {
const _66: rt.Place<string> = rt.place(() => t, (value10) => t = value10);
Expand All @@ -1492,54 +1509,55 @@ export function hinted(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
_66.v = rt.stringExtendChars(_66.v, _67);
} else if (_38 === 5) {
if (rt.u32Rem(m, 2) === 0) {
const _78: rt.Place<string> = rt.place(() => t, (value9) => t = value9);
const _79: rt.Iter<rt.char> = rt.iterChain(rt.iterMap(new rt.Range(0, n), f), rt.iterMap(new rt.Range(0, m), f));
const _78: rt.Place<string> = rt.place(() => t, (value9) => t = value9);
_78.v = rt.stringExtendChars(_78.v, _79);
} else {
const _84: rt.Place<string> = rt.place(() => t, (value8) => t = value8);
const _85: rt.Iter<rt.char> = rt.iterMap(rt.iterZip(new rt.Range(0, n), new rt.Range(0, m), [false, false]), (_211: [rt.u32, rt.u32]): rt.char => {
return f(_211[0]);
});
const _84: rt.Place<string> = rt.place(() => t, (value8) => t = value8);
_84.v = rt.stringExtendChars(_84.v, _85);
}
} else if (_38 === 6) {
const _91: rt.Place<string> = rt.place(() => t, (value7) => t = value7);
const _92: rt.Iter<rt.char> = rt.iterFlatMap(new rt.Range(0, n), (i2: rt.u32): rt.char[] => {
return [f(i2), f(i2)];
}, (value: rt.char[]) => rt.iterSlice(value), false, 2);
const _91: rt.Place<string> = rt.place(() => t, (value7) => t = value7);
_91.v = rt.stringExtendChars(_91.v, _92);
} else if (_38 === 7) {
const _96: rt.Place<string> = rt.place(() => t, (value6) => t = value6);
const _97: rt.Iter<rt.char> = rt.iterChain(rt.iterChain(rt.iterChain(rt.iterChain(rt.iterMap(new rt.Range(0, rt.u32SaturatingSub(n, 5)), f), rt.iterOnce(120)), rt.iterOption(121)), rt.strChars("é😀")), rt.iterSlice([122]));
const _96: rt.Place<string> = rt.place(() => t, (value6) => t = value6);
_96.v = rt.stringExtendChars(_96.v, _97);
} else if (_38 === 8) {
const _112: rt.usize = rt.usizeRem(sub, 3);
if (_112 === 0) {
const _114: rt.Place<string> = rt.place(() => t, (value5) => t = value5);
const _115: rt.Iter<rt.char> = rt.iterMap(new rt.Range({ hi: 0x10000000, lo: 0 } as rt.u64, rt.u64Add({ hi: 0x10000000, lo: 0 } as rt.u64, n as rt.u64), rt.u64Step), (_210: rt.u64): rt.char => {
return f(0);
});
const _114: rt.Place<string> = rt.place(() => t, (value5) => t = value5);
_114.v = rt.stringExtendChars(_114.v, _115);
} else if (_112 === 1) {
const _128: rt.Place<string> = rt.place(() => t, (value4) => t = value4);
const _129: rt.Iter<rt.char> = rt.iterMap(new rt.Range(rt.i128Neg(rt.i128Shl(1, 100)), rt.i128Add(rt.i128Neg(rt.i128Shl(1, 100)), n as rt.i128), rt.i128Step), (_27: rt.i128): rt.char => {
return f(0);
});
const _128: rt.Place<string> = rt.place(() => t, (value4) => t = value4);
_128.v = rt.stringExtendChars(_128.v, _129);
} else {
const _146: rt.Place<string> = rt.place(() => t, (value3) => t = value3);
const _147: rt.Iter<rt.char> = rt.iterMap(new rt.RangeInclusive({ hi: 0x10000000, lo: 0 } as rt.u64, rt.u64Add({ hi: 0x10000000, lo: 0 } as rt.u64, n as rt.u64), rt.u64Step), (_24: rt.u64): rt.char => {
return f(0);
});
const _146: rt.Place<string> = rt.place(() => t, (value3) => t = value3);
_146.v = rt.stringExtendChars(_146.v, _147);
}
} else {
const chars: rt.Peekable<rt.char> = rt.iterPeekable(rt.iterFuse(rt.iterRev(rt.iterMap(rt.iterEnumerate(rt.iterMap(new rt.Range(0, n), f)), (_23: [rt.usize, rt.char]): rt.char => {
return _23[1];
}))));
putChar(out, rt.peekablePeek(chars));
const _173: rt.Peekable<rt.char> = chars;
const _172: rt.Place<string> = rt.place(() => t, (value2) => t = value2);
_172.v = rt.stringExtendChars(_172.v, chars);
_172.v = rt.stringExtendChars(_172.v, _173);
}
put(out, t);
}
Expand Down
9 changes: 6 additions & 3 deletions ts/fixtures/lang/strs/src/strs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,13 +497,16 @@ pub fn edits(kind: u8, data: &[u8], out: &mut Vec<u8>) {
let [op, a, b] = [op[0], *op.get(1).unwrap_or(&0), *op.get(2).unwrap_or(&0x10)];
match op / 64 {
0 => edit(&mut named.name, op, a, b, out),
// On the local itself, with no `&mut` between.
1 => match op % 6 {
// On the local itself, with no `&mut` between, which the `+` after the loop assigns whole.
1 => match op % 8 {
0 => s.push_str("é/"),
1 => s.truncate(offset(&s, a)),
2 => put_char(out, s.pop()),
3 => s.insert_str(offset(&s, a), "😀"),
4 => put(out, &s.split_off(offset(&s, a))),
// Of a constant offset, which reads nothing between the borrow and the edit.
5 => put_char(out, Some(s.remove(0))),
6 => put(out, &s.split_off(1)),
_ => s.clear(),
},
_ => edit(&mut s, op, a, b, out),
Expand All @@ -512,7 +515,7 @@ pub fn edits(kind: u8, data: &[u8], out: &mut Vec<u8>) {
put(out, &named.name);
}
// `+` of the local itself, moved.
let s = s + "😀" + &named.name;
s = s + "😀" + &named.name;
put(out, &s);
}

Expand Down
21 changes: 10 additions & 11 deletions ts/src/lower/mir/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,6 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
// A `Cow<[T]>` that borrows takes a clone of its slice, whose `Vec` the `&mut` lends.
("Cow", "to_mut") if let ty::Slice(elem) = targ(0)?.kind() => {
let place = self.borrowed_place(&args[0].node, span, out)?;
// Read twice, by the clone and by the store.
self.materialize(&place.0, out);
let owned = library::cow_cloned(self.b, "IntoOwned", place.0.clone(), *elem, span);
let owned = self.path(owned, "owned", out);
self.set_borrowed(&place, owned.clone(), span, out);
Expand Down Expand Up @@ -1187,7 +1185,8 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
/// reference, which a store resolves: an alias of a borrowed place, not a copy of a
/// reference, which holds the object it points at, or an `rt.Place`, whose `v` it is,
/// or else the object it points at, written in place. A `[u8; N]`'s is a copy of its
/// bytes instead, which the store writes in place.
/// bytes instead, which the store writes in place. What it reads that is held back is
/// emitted, as an edit reads it and then writes it, where MIR reads it once.
fn borrowed_place(&mut self, op: &Operand<'tcx>, span: Span, out: &mut Vec<Stmt>) -> Option<Borrowed<'tcx>> {
let (Operand::Copy(place) | Operand::Move(place)) = op else {
return None;
Expand All @@ -1202,23 +1201,25 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
let slice = self.slice_path(slice, out);
return Some((Expr::rt("byteSliceToArray", vec![slice]), Some(deref)));
}
match &self.slots[place.local] {
let borrowed = match &self.slots[place.local] {
Slot::Alias(Some(target)) if assignable(target) && self.alias_of_place(place.local) => {
Some((target.clone(), Some(deref)))
(target.clone(), Some(deref))
}
_ if self.b.t.place_pointee(self.mir.local_decls[place.local].ty).is_some() => {
Some((self.place_expr(deref, span, out), Some(deref)))
(self.place_expr(deref, span, out), Some(deref))
}
_ if self.in_object(deref) => {
let target = self.place_expr(deref, span, out);
Some((self.path(target, "object", out), Some(deref)))
(self.path(target, "object", out), Some(deref))
}
_ => {
let pointee = self.mir.local_decls[place.local].ty.peel_refs();
let err = self.err(span, format!("replacing the value behind a reference to `{pointee}`"));
Some((err, None))
(err, None)
}
}
};
self.materialize(&borrowed.0, out);
Some(borrowed)
}

/// `slice::from_mut`, `array::from_mut`, or with `cell`, `Cell::from_mut` of `op`, a
Expand Down Expand Up @@ -1449,8 +1450,6 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> {
let Some(payload) = payload else {
return Some(Some((target, true)));
};
// The test reads it before either branch, so what it reads is set before both.
self.materialize(&target, out);
let whole = tcx.mk_place_deref(args[0].node.place()?);
let option_ty = whole.ty(&self.mir.local_decls, tcx).ty;
// What it inserts, made before the `Option` is read, as Rust makes the argument.
Expand Down