makepad/libs/relax/compiler/tests/generic_call_traits.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
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>
2026-10-13 12:26:21 +02:00

54 lines
2.9 KiB
Rust

use relax_compiler::{program::DefId, tcx::{EvalCx, EvalState, Tcx, TypingEnv}, typeck};
fn check_fixture(file: &str, reject: bool) {
let session = std::sync::Arc::new(relax_compiler::Session::default());
let path = format!("{}/tests/borrowck/{file}.rs", env!("CARGO_MANIFEST_DIR"));
let (prog, _, _) = relax_compiler::load_with_std(&session, &path, file, true).unwrap();
let mut tcx = Tcx::new();
tcx.collect(&prog);
assert!(tcx.errors.is_empty(), "{:?}", tcx.errors);
let state = EvalState::new();
let cx = EvalCx::new(&prog, &tcx, TypingEnv::fully_monomorphized(&prog), &state);
let main = (0..prog.defs.len()).map(|i| DefId(i as u32)).find(|&d| prog.name(d) == "main").unwrap();
let body = typeck::instantiate_body(&cx, &prog, &tcx, main, &[]);
assert!(body.errors.is_empty(), "{:?}", body.errors);
let mut checked = 0;
for (e, args) in &body.res_args {
let Some(typeck::Res::Def(d)) = body.res.get(e) else { continue };
if !matches!(prog.name(*d), "once" | "field" | "deref" | "shared" | "bad") { continue; }
let instance = typeck::instantiate_body(&cx, &prog, &tcx, *d, args);
assert!(instance.errors.is_empty(), "{}: {:?}", prog.name(*d), instance.errors);
if prog.name(*d) == "field" {
assert_eq!(instance.min_captures.values().next().unwrap().kind, relax_compiler::upvar::ClosureKind::FnOnce);
}
let verdict = relax_compiler::borrowck::check_body(&cx, &prog, &tcx, &instance);
assert!(verdict.unchecked.is_empty(), "{}: {:?}", prog.name(*d), verdict.unchecked);
if reject {
assert!(verdict.errors.iter().any(|e| e.code == "E0596"), "{}: {:?}", prog.name(*d), verdict.errors);
} else {
assert!(verdict.errors.is_empty(), "{}: {:?}", prog.name(*d), verdict.errors);
}
checked += 1;
}
assert_eq!(checked, if reject { 2 } else { 6 });
// Exercise the actual std body from the live failure with both closure kinds.
let mut std_checked = 0;
for method in body.methods.values().filter(|m| prog.name(m.def) == "get_or_init") {
let parent = prog.def(method.def).parent;
let initialize = (0..prog.defs.len()).map(|i| DefId(i as u32))
.find(|&d| prog.def(d).parent == parent && prog.name(d) == "initialize").unwrap();
let instance = typeck::instantiate_body(&cx, &prog, &tcx, initialize, &method.args);
assert!(instance.errors.is_empty(), "{:?}", instance.errors);
let verdict = relax_compiler::borrowck::check_body(&cx, &prog, &tcx, &instance);
assert!(verdict.unchecked.is_empty(), "{:?}", verdict.unchecked);
assert!(verdict.errors.is_empty(), "{:?}", verdict.errors);
std_checked += 1;
}
assert_eq!(std_checked, if reject { 0 } else { 2 });
}
#[test]
fn generic_once_instances() { check_fixture("generic_call_once_accept", false); }
#[test]
fn generic_mut_instances_reject() { check_fixture("generic_call_mut_reject", true); }