The JIT that runs makepad apps from source: lexer, front end, type checker, lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and warm/cold caches keyed by compiler stamp, provided crates bound late, startup images, live patching. User-facing name is `makepad run` (binary `makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal library name. `makepad check` reports rustc-style diagnostics with rustc error codes and checks a whole workspace (`--workspace`). Runs on macOS, Linux, Windows and Android. makepad-remote: one tool schema for apps and the WM (app/1): grabs, captures, traces, frame profiles and tweaks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
129 lines
3.4 KiB
Rust
129 lines
3.4 KiB
Rust
// A `const` used by value is a fresh copy at each use (Reference: constant items are inlined
|
|
// wherever they are used); only `&CONST` may share promoted storage, and that cannot be written.
|
|
// A local initialised from a const and then mutated must never write through to the const:
|
|
// sha256 copies its IV into its state and mutates it, and every hash after the first in a
|
|
// process came out wrong. rustc prints the same lines.
|
|
use std::hint::black_box;
|
|
|
|
const IV: [u32; 8] = [
|
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
];
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
struct State {
|
|
a: u64,
|
|
b: [u16; 4],
|
|
c: u8,
|
|
}
|
|
|
|
const START: State = State { a: 7, b: [1, 2, 3, 4], c: 9 };
|
|
|
|
struct Hasher;
|
|
impl Hasher {
|
|
const INIT: [u64; 4] = [11, 22, 33, 44];
|
|
}
|
|
|
|
// the sha256 pattern: copy the const into the state, mutate it in a loop, return it
|
|
fn rounds(n: u32) -> [u32; 8] {
|
|
let mut s = IV;
|
|
for i in 0..n {
|
|
let t = s[7].wrapping_add(i).rotate_left(5) ^ s[0];
|
|
for j in (1..8).rev() {
|
|
s[j] = s[j - 1].wrapping_add(t);
|
|
}
|
|
s[0] = t;
|
|
}
|
|
s
|
|
}
|
|
|
|
fn struct_copy() -> State {
|
|
let mut s = START;
|
|
s.a += 1;
|
|
s.b[2] = 100;
|
|
s.c = s.c.wrapping_mul(3);
|
|
s
|
|
}
|
|
|
|
fn assoc_copy() -> [u64; 4] {
|
|
let mut h = Hasher::INIT;
|
|
h[0] = h[0].wrapping_add(1);
|
|
h[3] *= 2;
|
|
h
|
|
}
|
|
|
|
fn bump(h: &mut [u32; 8]) {
|
|
for x in h.iter_mut() {
|
|
*x = x.wrapping_add(1);
|
|
}
|
|
}
|
|
|
|
mod inner {
|
|
// a const reached through a module path, written through `&mut` in a callee
|
|
pub fn through_mut() -> [u32; 8] {
|
|
let mut h = super::IV;
|
|
super::bump(&mut h);
|
|
h
|
|
}
|
|
}
|
|
|
|
fn borrowed() -> &'static [u32; 8] {
|
|
&IV
|
|
}
|
|
|
|
#[test]
|
|
fn const_by_value_copy() {
|
|
// (a) array const copied into a mut local and mutated, then the const read again
|
|
let mut h = IV;
|
|
h[0] = h[0].wrapping_add(1);
|
|
black_box(&mut h);
|
|
assert_eq!(h[0], 0x6a09e668);
|
|
assert_eq!(IV[0], 0x6a09e667);
|
|
let again = IV;
|
|
assert_eq!(again[0], 0x6a09e667);
|
|
|
|
// (b) a struct const the same way
|
|
let s1 = struct_copy();
|
|
let s2 = struct_copy();
|
|
assert_eq!(s1, s2);
|
|
assert_eq!(s1, State { a: 8, b: [1, 2, 100, 4], c: 27 });
|
|
assert_eq!(START, State { a: 7, b: [1, 2, 3, 4], c: 9 });
|
|
|
|
// (c) a mutated copy in a loop, called twice: the same result both times
|
|
let r1 = rounds(black_box(64));
|
|
let r2 = rounds(black_box(64));
|
|
assert_eq!(r1, r2);
|
|
assert_eq!(IV[7], 0x5be0cd19);
|
|
|
|
// (d) an associated const
|
|
let a1 = assoc_copy();
|
|
let a2 = assoc_copy();
|
|
assert_eq!(a1, a2);
|
|
assert_eq!(a1, [12, 22, 33, 88]);
|
|
assert_eq!(Hasher::INIT, [11, 22, 33, 44]);
|
|
|
|
// (c') the IV written through `&mut` in a callee, reached through a module path
|
|
let m1 = inner::through_mut();
|
|
let m2 = inner::through_mut();
|
|
assert_eq!(m1, m2);
|
|
assert_eq!(m1[0], 0x6a09e668);
|
|
assert_eq!(IV[0], 0x6a09e667);
|
|
|
|
// `&mut CONST` borrows a fresh temporary
|
|
#[allow(const_item_mutation)]
|
|
{
|
|
let t = &mut IV;
|
|
t[0] = 5;
|
|
bump(&mut IV);
|
|
assert_eq!(t[0], 5);
|
|
}
|
|
assert_eq!(IV[0], 0x6a09e667);
|
|
|
|
// (e) `&CONST` borrows still work (and may share storage: they cannot be written)
|
|
let b = borrowed();
|
|
assert_eq!(b, &IV);
|
|
assert_eq!(b[0], 0x6a09e667);
|
|
let r = &IV;
|
|
assert_eq!(r[3], 0xa54ff53a);
|
|
|
|
println!("{:08x} {:08x} {:?} {:?} {:?}", r1[0], r1[7], s1, a1, b[0]);
|
|
}
|