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: 1 addition & 1 deletion quest/m0/checks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ Each child reports its CPU saved, cold and warm, against `origin/main`.
## Required

- [A warm gate](/quest/m0/checks/cache.md) - the land gate builds through mbx, as moq's does
- [Stable names on a small fixture](/quest/m0/checks/stable-names.md) - `stable_names` runs on a small fixture with generic instances and trait impls
- [Fixtures that merge](/quest/m0/checks/fixture-layout.md) - `lang` splits by module, and `reject`'s snapshots key by item, not line
- [A result slot's name stays as translation reaches more](/quest/m0/checks/ts-stable-slots.md) - reaching another function sharing a slot renames nothing
15 changes: 0 additions & 15 deletions quest/m0/checks/stable-names.md

This file was deleted.

21 changes: 21 additions & 0 deletions quest/m0/checks/ts-stable-slots.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# [S] A result slot's name stays as translation reaches more

## Goal

Reaching another function that shares a result slot renames neither the slot nor any line
that reads or writes it, and `stable_names` covers it on the `names` fixture.

## Plan

Decided with the maintainer on 2026-11-02: m0, since unstable names churn snapshots and
conflict merges, which this epic exists to cut.

Found while moving `stable_names` to its own fixture on 2026-11-02. A slot of `Ok` parts is
named for the first function in source order among those translation reaches that share
it, so a root reaching an earlier one renames it: with `read` reached, `readOut`; once
`lead`, declared above it with the same payload type, is reached too, every `readOut` in
`read` and its callers becomes `leadOut`. `place_slot` in `ts/src/lower/mir/scalar.rs` picks
the name. Name it by what the slot holds, or by every function of the crate that could
share it as the import census does, rather than by what translation reached.

Public API: the translator's output.
4 changes: 4 additions & 0 deletions ts/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,11 @@ built natively for wasm32 and run beside its translation on the same inputs by
with products of those values at 128 bits, 128-bit quotients by divisors below 2^32,
and their halves joined back.
`brands.ts`, another caller, mixes integer types where `tsc` must refuse them.
- `names` is translated from `run`, then with `added` as its first root, which reaches
another instance of what `run` reaches one of, each sorting before it: a generic method's,
a closure's, an impl's of another trait, a std function's that merges with `run`'s, and
an impl's over a deeper `&mut`, beside a trait object's module named as a type's that
`run` imports. Every line of the first must stay, in order.
- `share` holds a `Copy` aggregate whose only write in the crate makes it copied, where
`lang`'s other writes into the same type would hide a write the analysis misses: a
byte array overwritten whole through a type parameter, or, under its features, by std
Expand Down
2 changes: 1 addition & 1 deletion ts/fixtures/lang/expected/fmt.Padded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import * as rt from "./rt.ts";

/** `Display` through `pad`, which keeps the options. Only `added` prints its `Debug`. */
/** `Display` through `pad`, which keeps the options. */
export interface Padded {
_0: string;
}
Expand Down
18 changes: 1 addition & 17 deletions ts/fixtures/lang/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,7 @@ impl fmt::Debug for Hex {
}
}

/// `Display` through `pad`, which keeps the options. Only `added` prints its `Debug`.
#[derive(Debug)]
/// `Display` through `pad`, which keeps the options.
pub struct Padded(&'static str);

impl fmt::Display for Padded {
Expand Down Expand Up @@ -992,21 +991,6 @@ pub fn printed(data: &[u8]) -> Vec<u8> {
format!("{fault}|{fault:>16}|{fault:?}|{fault:#?}").into_bytes()
}

/// A root only the `stable_names` test adds, reaching another instance of what `run`
/// reaches one of: a generic method's, a closure's, an impl's of another trait, a std
/// function's that merges with one `run` reaches and sorts before it, and an impl's over a
/// deeper `&mut` than `run`'s, which sorts before its others. Its trait object's module shares its name with a type's this
/// module imports, and sorts first.
pub fn added(out: &mut Vec<u8>) {
out.push(Wrap::new(1u8).into_inner());
out.push(1u8.partial_cmp(&2).map_or(7, |o| o as i8 as u8));
let mapped = Wrap::new(2u8).map(|b| Pair(b, 0));
put(out, &format!("{mapped:?} {:?}", Padded("added")));
let shape: &dyn crate::dyns::Shape = &3u32;
out.push(shape.sides());
out.extend_from_slice(&crate::refs::deeper(4).to_be_bytes());
}

/// A writer of the crate's own that fails a `write_str` past `cap` bytes, and counts each.
pub struct Capped {
text: String,
Expand Down
7 changes: 0 additions & 7 deletions ts/fixtures/lang/src/refs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,6 @@ fn tally_all<T: Tally>(t: &mut T, data: &[u8]) -> u32 {
t.total()
}

/// A tally through more `&mut`s than `run`'s, which only the `stable_names` test reaches:
/// its impls' instances spell their suffixes alike but for the references, and sort first.
pub(crate) fn deeper(n: u32) -> u32 {
let mut count = n;
tally_all(&mut &mut &mut &mut count, &[1])
}

/// A reader keeping a `&mut` to the slice it reads, which it lends on.
struct Reader<'a, 'b> {
rest: &'b mut &'a [u8],
Expand Down
10 changes: 10 additions & 0 deletions ts/fixtures/names/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "names-fixture"
description = "Names rust2-ts keeps as translation reaches more instances"
version = "0.0.0"
edition.workspace = true
license.workspace = true
publish = false

[lints]
workspace = true
19 changes: 19 additions & 0 deletions ts/fixtures/names/expected/core/option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "../rt.ts";

export function unwrapOr$0r2bmpr(self: rt.u8 | undefined, default_: rt.u8): rt.u8 {
if (self === undefined) {
return default_;
}
return self;
}

export function mapOr$1e4a1e0(self: rt.Ordering | undefined, default_: rt.u8, f: (a0: rt.Ordering) => rt.u8): rt.u8 {
if (self === undefined) {
return default_;
}
return f(self);
}

//# sourceMappingURL=option.ts.map
38 changes: 38 additions & 0 deletions ts/fixtures/names/expected/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "./rt.ts";
import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, mapOr$1e4a1e0 as option_mapOr$1e4a1e0 } from "./core/option.ts";
import * as shapes_Shape from "./shapes.Shape.ts";
import { run as tally_run } from "./tally.ts";
import type * as Pair from "./wrap.Pair.ts";
import * as Wrap from "./wrap.Wrap.ts";

/** One instance of each generic item it reaches. */
export function run(data: rt.ByteSlice): rt.ByteVec {
let shape!: shapes_Shape.Shape;
const first: rt.u8 = option_unwrapOr$0r2bmpr(rt.byteSliceFirst(data), 0);
const pair: Pair.Pair = Wrap.intoInner$wrap_Pair(Wrap.new$wrap_Pair({ _0: first, _1: 1 }));
const out: rt.ByteVec = rt.byteVecFrom(Uint8Array.of(Wrap.intoInner$u8(Wrap.map$wrap_Pair_u8_run_closure1(Wrap.new$wrap_Pair(pair), (p: Pair.Pair): rt.u8 => {
return p._0;
}))));
const _15: rt.u8 = option_mapOr$1e4a1e0(rt.cmp(data.length, 4), 9, (o: rt.Ordering): rt.u8 => {
return o & 0xff;
});
rt.byteVecPush(out, _15);
const part = Wrap.new$wrap_Pair(pair);
const args2: rt.Fmt[] = [(f: rt.Formatter) => Wrap.fmt$fmt_Display_wrap_Pair(part, f)];
const _22: rt.ByteSlice = rt.stringAsBytes(rt.fmtFormat([args2[0]]));
rt.byteVecExtendFromSlice(out, _22);
if (!(first === 0)) {
shape = "Line" as shapes_Shape.Shape;
} else {
shape = "Dot" as shapes_Shape.Shape;
}
const _38: rt.u8 = shapes_Shape.sides(shape);
rt.byteVecPush(out, _38);
const _42: rt.ByteSlice = rt.byteSliceFrom(rt.u32ToBeBytes(tally_run(data)));
rt.byteVecExtendFromSlice(out, _42);
return out;
}

//# sourceMappingURL=lib.ts.map
15 changes: 15 additions & 0 deletions ts/fixtures/names/expected/shapes.Shape.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "./rt.ts";

/** A type named as `dyns::Shape` is. */
export type Shape = "Dot" | "Line";

export function sides(self: Shape): rt.u8 {
if (self === "Dot") {
return 0;
}
return 1;
}

//# sourceMappingURL=shapes.Shape.ts.map
38 changes: 38 additions & 0 deletions ts/fixtures/names/expected/tally.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "./rt.ts";

export function tally$tally_Tally_u32(self: rt.Place<rt.u32>, n: rt.u8): void {
self.v = rt.u32Add(self.v, n as rt.u32);
}

export function total$tally_Tally_u32(self: rt.u32): rt.u32 {
return self;
}

export function tally$tally_Tally_mut_u32(self: rt.Place<rt.Place<rt.u32>>, n: rt.u8): void {
tally$tally_Tally_u32(self.v, n);
}

export function total$tally_Tally_mut_mut_u32(self: rt.Place<rt.Place<rt.u32>>): rt.u32 {
return total$tally_Tally_mut_u32(self.v);
}

export function total$tally_Tally_mut_u32(self: rt.Place<rt.u32>): rt.u32 {
return total$tally_Tally_u32(self.v);
}

export function tallyAll$mut_u32(t: rt.Place<rt.Place<rt.u32>>, data: rt.ByteSlice): rt.u32 {
for (const _5 of rt.byteSliceView(data)) {
tally$tally_Tally_mut_u32(t, _5);
}
return total$tally_Tally_mut_mut_u32(t);
}

export function run(data: rt.ByteSlice): rt.u32 {
let count: rt.u32 = 0;
let _4: rt.Place<rt.u32> = rt.place(() => count, (value) => count = value);
return tallyAll$mut_u32(rt.place(() => _4, (value2) => _4 = value2), data);
}

//# sourceMappingURL=tally.ts.map
19 changes: 19 additions & 0 deletions ts/fixtures/names/expected/wrap.Pair.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "./rt.ts";

/** Printed by `Display` in `run`, and by `Debug` only in `added`. */
export interface Pair {
_0: rt.u8;
_1: rt.u8;
}

export function fmt$fmt_Display(self: Pair, f: rt.Formatter): rt.Result<undefined, rt.FmtError> {
const arg = self._0;
const _8: rt.Fmt = (f: rt.Formatter) => rt.u8Display(arg, f);
const arg2 = self._1;
const args2: rt.Fmt[] = [_8, (f: rt.Formatter) => rt.u8Display(arg2, f)];
return rt.fmtWriteFmt(f, [args2[0], "-", args2[1]]);
}

//# sourceMappingURL=wrap.Pair.ts.map
37 changes: 37 additions & 0 deletions ts/fixtures/names/expected/wrap.Wrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Generated by rust2-ts. Do not edit.

import * as rt from "./rt.ts";
import * as Pair from "./wrap.Pair.ts";

/** A generic type, with a method generic over a closure. */
export class Wrap<T> {
_0: T;

constructor(_0: T) {
this._0 = _0;
}
}

export function new$wrap_Pair(value: Pair.Pair): Wrap<Pair.Pair> {
return new Wrap(value);
}

export function intoInner$u8(self: Wrap<rt.u8>): rt.u8 {
return self._0;
}

export function intoInner$wrap_Pair(self: Wrap<Pair.Pair>): Pair.Pair {
return self._0;
}

export function map$wrap_Pair_u8_run_closure1(self: Wrap<Pair.Pair>, f: (a0: Pair.Pair) => rt.u8): Wrap<rt.u8> {
return new Wrap(f(self._0));
}

export function fmt$fmt_Display_wrap_Pair(self: Wrap<Pair.Pair>, f: rt.Formatter): rt.Result<undefined, rt.FmtError> {
const arg = self._0;
const args2: rt.Fmt[] = [(f: rt.Formatter) => Pair.fmt$fmt_Display(arg, f)];
return rt.fmtWriteFmt(f, ["[", args2[0], "]"]);
}

//# sourceMappingURL=wrap.Wrap.ts.map
10 changes: 10 additions & 0 deletions ts/fixtures/names/src/dyns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// A trait named as `shapes::Shape` is, whose object only `added` makes.
pub trait Shape {
fn sides(&self) -> u8;
}

impl Shape for u32 {
fn sides(&self) -> u8 {
3
}
}
37 changes: 37 additions & 0 deletions ts/fixtures/names/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Names that stay as translation reaches more: `stable_names` translates `run`, then `added`
//! and `run`, and checks that every line of the first stays, in order.

mod dyns;
mod shapes;
mod tally;
mod wrap;

use shapes::Shape;
use wrap::{Pair, Wrap};

/// One instance of each generic item it reaches.
pub fn run(data: &[u8]) -> Vec<u8> {
let first = data.first().copied().unwrap_or(0);
let pair = Wrap::new(Pair(first, 1)).into_inner();
let mut out = vec![Wrap::new(pair).map(|p| p.0).into_inner()];
out.push(data.len().partial_cmp(&4).map_or(9, |o| o as i8 as u8));
out.extend_from_slice(format!("{}", Wrap::new(pair)).as_bytes());
let shape = if first == 0 { Shape::Dot } else { Shape::Line };
out.push(shape.sides());
out.extend_from_slice(&tally::run(data).to_be_bytes());
out
}

/// Another instance of what `run` reaches one of, each sorting before it: a generic method's,
/// a closure's, an impl's of another trait, a std function's that merges with `run`'s, and an
/// impl's over a deeper `&mut`. Its trait object's module shares its name with a type's this
/// module imports, and sorts first.
pub fn added(out: &mut Vec<u8>) {
out.push(Wrap::new(1u8).into_inner());
out.push(1u8.partial_cmp(&2).map_or(7, |o| o as i8 as u8));
let mapped = Wrap::new(2u8).map(|b| Pair(b, 0));
out.extend_from_slice(format!("{mapped:?}").as_bytes());
let shape: &dyn dyns::Shape = &3u32;
out.push(shape.sides());
out.extend_from_slice(&tally::deeper(4).to_be_bytes());
}
14 changes: 14 additions & 0 deletions ts/fixtures/names/src/shapes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// A type named as `dyns::Shape` is.
pub enum Shape {
Dot,
Line,
}

impl Shape {
pub fn sides(&self) -> u8 {
match self {
Self::Dot => 0,
Self::Line => 1,
}
}
}
Loading