Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

crates/mimir-driver/tests/fixture_dump.rs

//! Integration: run `cargo mimir-dump` on the two-crate fixture (tests/fixture)
//! and assert the graph. b calls a's fn (two versions of a), a trait impl, a
//! method call through a trait (static + dyn), a std call, an extern "C" fn.

use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::path::{Path, PathBuf};
use std::process::Command;

use mimir_driver::read_tables;

fn copy_dir(from: &Path, to: &Path) {
    std::fs::create_dir_all(to).unwrap();
    for e in std::fs::read_dir(from).unwrap().flatten() {
        let p = e.path();
        let name = e.file_name();
        if name == "target" || name == "Cargo.lock" {
            continue;
        }
        if p.is_dir() {
            copy_dir(&p, &to.join(&name));
        } else {
            std::fs::copy(&p, to.join(&name)).unwrap();
        }
    }
}

struct Graph {
    nodes: BTreeMap<String, BTreeMap<String, String>>, // id -> col -> value (defined_here preferred)
    edges: HashSet<(String, String, String)>,          // (kind, from, to)
}

fn load(out: &Path) -> Graph {
    let n = read_tables(out, "nodes").unwrap();
    let e = read_tables(out, "edges").unwrap();
    let mut nodes: BTreeMap<String, BTreeMap<String, String>> = BTreeMap::new();
    let (id, here) = (n.col("id"), n.col("defined_here"));
    for r in &n.rows {
        let row: BTreeMap<String, String> =
            n.columns.iter().cloned().zip(r.iter().cloned()).collect();
        let keep = match nodes.get(&r[id]) {
            None => true,
            Some(old) => old["defined_here"] != "true" && r[here] == "true",
        };
        if keep {
            nodes.insert(r[id].clone(), row);
        }
    }
    let (f, t, k) = (e.col("from"), e.col("to"), e.col("kind"));
    let edges = e.rows.iter().map(|r| (r[k].clone(), r[f].clone(), r[t].clone())).collect();
    Graph { nodes, edges }
}

const A: &str = "rust-analyzer cargo a 0.1.0 ";
const A_OLD: &str = "rust-analyzer cargo a 0.0.9 ";
const B: &str = "rust-analyzer cargo b 0.2.0 ";

#[test]
fn fixture_graph() {
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .args(["--out", out.to_str().unwrap(), "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success(), "cargo mimir-dump failed");
    assert!(!out.join(".errors").exists(), "walk errors: {:?}", std::fs::read_dir(out.join(".errors")).ok().map(|d| d.flatten().map(|e| e.path()).collect::<Vec<_>>()));

    let g = load(&out);
    let m = |p: &str, d: &str| format!("{p}{d}");
    let mut results: Vec<(String, bool)> = Vec::new();
    let mut check = |name: String, ok: bool| results.push((name, ok));
    let has_edge = |k: &str, f: &str, t: &str| g.edges.contains(&(k.to_string(), f.to_string(), t.to_string()));
    let node = |id: &str| g.nodes.get(id);

    let run = m(B, "run().");
    // the headline: b → a CALLS carries a's real moniker WITH version
    check(format!("CALLS {run} -> {A}add()."), has_edge("CALLS", &run, &m(A, "add().")));
    check(format!("CALLS {run} -> {A_OLD}add()."), has_edge("CALLS", &run, &m(A_OLD, "add().")));
    check("CALLS run -> b Dog#Greet#greet() (static dispatch resolved to impl)".into(), has_edge("CALLS", &run, &m(B, "impl#[Dog][Greet]greet().")));
    check("CALLS run -> a Greet#greet() (dyn dispatch, trait method)".into(), has_edge("CALLS", &run, &m(A, "Greet#greet().")));
    check("CALLS run -> a Point#norm1() (inherent method)".into(), has_edge("CALLS", &run, &m(A, "impl#[Point]norm1().")));
    check("CALLS run -> a Point#new() (assoc fn path call)".into(), has_edge("CALLS", &run, &m(A, "impl#[Point]new().")));
    let std_len = g.edges.iter().any(|(k, f, t)| {
        k == "CALLS" && *f == run && t.starts_with("rust-analyzer cargo alloc ") && t.ends_with(" string/impl#[String]len().")
    });
    check("CALLS run -> alloc String#len() (std, origin lang)".into(), std_len);
    let alloc_len = g.nodes.iter().find(|(id, _)| id.starts_with("rust-analyzer cargo alloc ") && id.ends_with("string/impl#[String]len()."));
    check("alloc String#len node origin=lang, defined_here=false".into(), alloc_len.is_some_and(|(_, r)| r["origin"] == "lang" && r["defined_here"] == "false"));
    check("CALLS run -> a abs() (extern \"C\")".into(), has_edge("CALLS", &run, &m(A, "abs().")));
    check("CALLS by_value -> a tiny() (a fn named as a value, called through a generic)".into(), has_edge("CALLS", &m(B, "by_value()."), &m(A, "tiny().")));
    check("a abs() kind=ffi".into(), node(&m(A, "abs().")).is_some_and(|r| r["kind"] == "ffi"));
    check("IMPLEMENTS b impl#[Dog][Greet] -> a Greet#".into(), has_edge("IMPLEMENTS", &m(B, "impl#[Dog][Greet]"), &m(A, "Greet#")));
    check("FOR_TYPE b impl#[Dog][Greet] -> b Dog#".into(), has_edge("FOR_TYPE", &m(B, "impl#[Dog][Greet]"), &m(B, "Dog#")));
    check("CONTAINS b impl#[Dog][Greet] -> Dog#Greet#greet()".into(), has_edge("CONTAINS", &m(B, "impl#[Dog][Greet]"), &m(B, "impl#[Dog][Greet]greet().")));
    check("CONTAINS b crate/ -> Dog#".into(), has_edge("CONTAINS", &m(B, "crate/"), &m(B, "Dog#")));
    check("READS_FIELD run -> a Point#x.".into(), has_edge("READS_FIELD", &run, &m(A, "Point#x.")));
    check("USES_TYPE run -> a Point#".into(), has_edge("USES_TYPE", &run, &m(A, "Point#")));
    check("DEPENDS_ON b crate/ -> a 0.1.0 crate/".into(), has_edge("DEPENDS_ON", &m(B, "crate/"), &m(A, "crate/")));
    check("DEPENDS_ON b crate/ -> a 0.0.9 crate/".into(), has_edge("DEPENDS_ON", &m(B, "crate/"), &m(A_OLD, "crate/")));
    check("EXPANDS a impl#[Point][Debug] -> core Debug: derive".into(), g.edges.iter().any(|(k, f, t)| k == "EXPANDS" && *f == m(A, "impl#[Point][Debug]") && t.ends_with("Debug:")));
    check("a tests/adds() is_test".into(), node(&m(A, "tests/adds().")).is_some_and(|r| r["is_test"] == "true"));
    check("TESTS a tests/adds() -> a add()".into(), has_edge("TESTS", &m(A, "tests/adds()."), &m(A, "add().")));
    check("a tests/ cfg = cfg(test)".into(), node(&m(A, "tests/")).is_some_and(|r| r["cfg"] == "cfg(test)"));
    check("param a add().(x) ty=i32".into(), node(&m(A, "add().(x)")).is_some_and(|r| r["ty"] == "i32" && r["kind"] == "param" && r["level"] == "part"));
    // what the 🏛 code room hangs under a function head: its return type and its
    // `let` bindings (a shadowed name is two locals, one per line)
    let ret = m(B, "run().`->`.");
    check("ret b run() -> i32: a part node under run()".into(), node(&ret).is_some_and(|r| r["ty"] == "i32" && r["kind"] == "ret" && r["level"] == "part" && r["parent"] == run));
    check("CONTAINS run -> its ret".into(), has_edge("CONTAINS", &run, &ret));
    let local = |name: &str, line: u32| m(B, &format!("run().`{name}@{line}`."));
    check("local b run() s@18 ty=String".into(), node(&local("s", 18)).is_some_and(|r| r["ty"] == "String" && r["kind"] == "local" && r["level"] == "part" && r["start_line"] == "18" && r["file"] == "b/src/lib.rs" && r["name"] == "s"));
    check("locals v@21 and v@22 (shadowing: two)".into(), node(&local("v", 21)).is_some() && node(&local("v", 22)).is_some());
    check("local g@19 ty=&dyn Greet".into(), node(&local("g", 19)).is_some_and(|r| r["ty"].contains("dyn Greet")));
    check("CONTAINS run -> local q@25".into(), has_edge("CONTAINS", &run, &local("q", 25)));
    check("no local for `let _`".into(), !g.nodes.keys().any(|id| id.starts_with(&run) && id.contains("`_@")));
    check("no ret for a unit fn".into(), !g.nodes.keys().any(|id| id.ends_with("`->`.") && g.nodes[id]["ty"] == "()"));
    check("field a Point#x. ty=i32 level=part".into(),node(&m(A, "Point#x.")).is_some_and(|r| r["ty"] == "i32" && r["level"] == "part"));
    check("bin b `bin=bctl`:main() (target-prefixed)".into(), node(&m(B, "`bin=bctl`:main().")).is_some_and(|r| r["defined_here"] == "true"));
    check("bin b's crate root `bin=bctl`:crate/, not the lib's crate/".into(), node(&m(B, "`bin=bctl`:crate/")).is_some_and(|r| r["kind"] == "crate" && r["file"] == "b/src/bin/bctl.rs"));
    check("a add() span a/src/lib.rs".into(), node(&m(A, "add().")).is_some_and(|r| r["file"] == "a/src/lib.rs" && r["start_line"] != ""));
    check("a/b nodes origin=local, repo set".into(), node(&run).is_some_and(|r| r["origin"] == "local" && !r["repo"].is_empty()));
    check("a 0.0.9 add() origin=library (excluded path dep)".into(), node(&m(A_OLD, "add().")).is_some_and(|r| r["origin"] == "library"));
    check("no version '?' anywhere".into(), g.nodes.values().all(|r| r["version"] != "?"));
    check("provenance = source_only everywhere".into(), g.nodes.values().all(|r| r["provenance"] == "source_only"));

    // Semantic edges: one row per (from, to, kind), `count` = distinct sites;
    // the sites themselves are `code_spans` rows, not edge identity.
    let e = read_tables(&out, "edges").unwrap();
    let (ef, et, ek, ec) = (e.col("from"), e.col("to"), e.col("kind"), e.col("count"));
    // Unique WITHIN each crate's dump (a lib and its test harness each dump
    // their own copy of shared edges).
    let mut unique = true;
    for f in std::fs::read_dir(&out).unwrap().flatten().map(|e| e.path()) {
        if !f.to_string_lossy().ends_with(".edges.arrow") {
            continue;
        }
        let one = f.with_extension("").with_extension("").file_name().unwrap().to_string_lossy().into_owned();
        let dir = out.join(".uniq").join(&one);
        std::fs::create_dir_all(&dir).unwrap();
        std::fs::copy(&f, dir.join(f.file_name().unwrap())).unwrap();
        let t = read_tables(&dir, "edges").unwrap();
        let mut seen = HashSet::new();
        unique &= t.rows.iter().all(|r| seen.insert((r[ef].clone(), r[et].clone(), r[ek].clone())));
    }
    check("edges unique per (from, to, kind) in every crate dump".into(), unique);
    let add = m(A, "add().");
    check("CALLS b run() -> a add() count = 2 (two sites)".into(), e.rows.iter().any(|r| r[ek] == "CALLS" && r[ef] == run && r[et] == add && r[ec] == "2"));
    let sp = read_tables(&out, "spans").unwrap();
    let (st, sk, sf, ss) = (sp.col("target"), sp.col("key"), sp.col("file"), sp.col("start_line"));
    let site_key = mimir_schema::edge_key(&run, &add, mimir_schema::EdgeKind::Calls);
    let sites: BTreeSet<String> = sp.rows.iter().filter(|r| r[st] == "edge" && r[sk] == site_key).map(|r| format!("{}:{}", r[sf], r[ss])).collect();
    check(format!("2 edge-site spans for run -> add ({sites:?})"), sites.len() == 2);
    check("node span a add() in code_spans".into(), sp.rows.iter().any(|r| r[st] == "node" && r[sk] == add && r[sf] == "a/src/lib.rs"));

    let mut kinds: BTreeMap<&str, usize> = BTreeMap::new();
    for (k, _, _) in &g.edges {
        *kinds.entry(k.as_str()).or_default() += 1;
    }
    eprintln!("fixture: {} nodes, {} edges {:?}", g.nodes.len(), g.edges.len(), kinds);
    eprintln!("| check | result |\n|---|---|");
    for (n, ok) in &results {
        eprintln!("| {n} | {} |", if *ok { "PASS" } else { "FAIL" });
    }
    let failed: Vec<_> = results.iter().filter(|(_, ok)| !ok).map(|(n, _)| n).collect();
    assert!(failed.is_empty(), "failed: {failed:#?}");
}

/// Schema 2 (producer gaps P1 + P2) on the same fixture: visibility as rustc
/// resolves it (nominal + effective), doc summary / `has_doc`, feature nodes
/// with ENABLES / ENABLES_WEAK, GATED_BY from kept items (rustc's `CfgTrace`)
/// and from `cfg_gated_out` stubs (the token scan — items rustc never saw).
#[test]
fn fixture_visibility_docs_features_and_gates() {
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-s2-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .args(["--out", out.to_str().unwrap(), "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success(), "cargo mimir-dump failed");
    assert!(!out.join(".errors").exists(), "walk errors");

    let g = load(&out);
    let m = |p: &str, d: &str| format!("{p}{d}");
    let mut results: Vec<(String, bool)> = Vec::new();
    let mut check = |name: String, ok: bool| results.push((name, ok));
    let has_edge = |k: &str, f: &str, t: &str| g.edges.contains(&(k.to_string(), f.to_string(), t.to_string()));
    let col = |id: &str, c: &str| g.nodes.get(id).map(|r| r[c].clone()).unwrap_or_else(|| "<no node>".into());
    const C: &str = "rust-analyzer cargo c 0.3.0 ";

    // ---- P1: visibility — (item, nominal, effective)
    for (d, vis, eff) in [
        ("add().", "pub", "direct"),
        ("private_fn().", "private", "internal"),
        // at the crate root `pub(crate)` IS the item's own module: one meaning
        ("crate_root_scoped().", "private", "internal"),
        ("inner/", "private", "internal"),
        ("inner/crate_wide().", "pub(crate)", "internal"),
        // `pub(super)` one level down resolves to the crate
        ("inner/for_parent().", "pub(crate)", "internal"),
        ("inner/deep/scoped().", "pub(in crate::inner)", "internal"),
        ("inner/deep/up().", "pub(in crate::inner)", "internal"),
        // `pub`, but nothing outside the crate can reach it
        ("inner/hidden_pub().", "pub", "internal"),
        ("inner/deep/", "pub", "internal"),
        // nameable only through `pub use inner::reexported`
        ("inner/reexported().", "pub", "reexported"),
        // not nameable, leaks through `leak()`'s signature
        ("inner/Leaked#", "pub", "reachable"),
        ("leak().", "pub", "direct"),
        ("Point#", "pub", "direct"),
        ("Point#x.", "pub", "direct"),
        ("Greet#greet().", "pub", "direct"),
        ("impl#[Point]new().", "pub", "direct"),
        ("abs().", "pub", "direct"),
        ("twice!", "private", "internal"),
        ("crate/", "pub", "direct"),
        ("tests/adds().", "private", "internal"),
    ] {
        let id = m(A, d);
        let got = (col(&id, "visibility"), col(&id, "effective_visibility"));
        check(format!("visibility a {d} = {vis} / {eff} (got {} / {})", got.0, got.1), got == (vis.to_string(), eff.to_string()));
    }
    for d in ["impl#[Point]", "ident().[T]", "add().(x)"] {
        let id = m(A, d);
        check(format!("no visibility on a {d} (impl block / generic / param)"), col(&id, "visibility").is_empty() && col(&id, "effective_visibility").is_empty());
    }
    let alloc_len = g.nodes.iter().find(|(id, _)| id.starts_with("rust-analyzer cargo alloc ") && id.ends_with("string/impl#[String]len()."));
    check(
        "reference stub (alloc String#len): visibility / doc / has_doc all NULL".into(),
        alloc_len.is_some_and(|(_, r)| r["visibility"].is_empty() && r["effective_visibility"].is_empty() && r["doc"].is_empty() && r["has_doc"].is_empty()),
    );

    // ---- P1: docs — (item, has_doc, summary)
    for (d, has, doc) in [
        ("tiny().", "true", "always inlined: a source node with no linked symbol of its own."),
        // only the FIRST line of a multi-line doc comment
        ("ident().", "true", "generic + `#[inline(never)]`: b instantiates it twice (`u32`, `&str`) →"),
        ("abs().", "true", "libc `abs` — the extern \"C\" border."),
        ("inner/reexported().", "true", "Re-exported from a private module."),
        ("crate/", "true", "fixture crate a 0.1.0"),
        // `//` comments are not docs
        ("add().", "false", ""),
        ("Point#", "false", ""),
        ("impl#[Point]", "false", ""),
    ] {
        let id = m(A, d);
        let got = (col(&id, "has_doc"), col(&id, "doc"));
        check(format!("doc a {d}: has_doc={has} doc={doc:?} (got {} {:?})", got.0, got.1), got == (has.to_string(), doc.to_string()));
    }
    check("has_doc NULL on a param / generic".into(), col(&m(A, "add().(x)"), "has_doc").is_empty() && col(&m(A, "ident().[T]"), "has_doc").is_empty());

    // ---- schema 3: attributes — `ignored` on tests only, `doc_hidden` on the
    // item that carries the attribute
    for (d, ignored) in [("tests/adds().", "false"), ("tests/slow().", "true"), ("tests/slow_with_reason().", "true"), ("add().", ""), ("tests/", ""), ("Point#", "")] {
        let id = m(A, d);
        check(format!("ignored a {d} = {ignored:?} (got {:?})", col(&id, "ignored")), col(&id, "ignored") == ignored);
    }
    for (d, hidden) in [
        ("hidden_api().", "true"),
        ("hidden_mod/", "true"),
        // its module is hidden, the fn itself carries nothing
        ("hidden_mod/inside().", "false"),
        ("add().", "false"),
        ("crate/", "false"),
        ("impl#[Point]", "false"),
        ("tests/slow().", "false"),
        // no doc notion: a param, a generic param
        ("add().(x)", ""),
        ("ident().[T]", ""),
    ] {
        let id = m(A, d);
        check(format!("doc_hidden a {d} = {hidden:?} (got {:?})", col(&id, "doc_hidden")), col(&id, "doc_hidden") == hidden);
    }
    check(
        "reference stub (alloc String#len): ignored / doc_hidden NULL".into(),
        alloc_len.is_some_and(|(_, r)| r["ignored"].is_empty() && r["doc_hidden"].is_empty()),
    );
    let stub = g.nodes.values().find(|r| r["kind"] == "cfg_gated_out");
    check("a cfg_gated_out stub: ignored / doc_hidden NULL (nothing resolved)".into(), stub.is_some_and(|r| r["ignored"].is_empty() && r["doc_hidden"].is_empty()));

    // ---- schema 4: the link name of a foreign item (rustc's symbol name of
    // it: its own name here, no `#[link_name]` in the fixture); null on
    // everything that is not a foreign item
    for (d, link) in [("abs().", "abs"), ("getpid().", "getpid"), ("add().", ""), ("Point#", "")] {
        let id = m(A, d);
        check(format!("link_name a {d} = {link:?} (got {:?})", col(&id, "link_name")), col(&id, "link_name") == link);
    }
    check("reference stub (alloc String#len): link_name NULL".into(), alloc_len.is_some_and(|(_, r)| r["link_name"].is_empty()));

    // ---- P2: feature nodes, one per crate@version feature
    let f = |p: &str, name: &str| format!("{p}`feature={name}`:");
    for (id, here, what) in [
        (f(A, "default"), "true", "a default (declared)"),
        (f(A, "on"), "true", "a on (declared)"),
        (f(A, "extra"), "true", "a extra (declared, never built)"),
        (f(A, "ghost"), "false", "a ghost (in a cfg, no manifest declares it)"),
        (f(A_OLD, "legacy"), "true", "a 0.0.9 legacy (its own node: per crate@VERSION)"),
        (f(B, "fast"), "true", "b fast"),
        (f(B, "c-turbo"), "true", "b c-turbo"),
        (f(C, "turbo"), "false", "c turbo (c is never compiled: a reference)"),
    ] {
        check(
            format!("feature node {what}: kind=feature defined_here={here}"),
            g.nodes.get(&id).is_some_and(|r| r["kind"] == "feature" && r["level"] == "item" && r["defined_here"] == here && r["cfg"].is_empty()),
        );
    }
    check("feature a on: file a/Cargo.toml + line, parent = a crate/".into(), g.nodes.get(&f(A, "on")).is_some_and(|r| r["file"] == "a/Cargo.toml" && r["start_line"] == "10" && r["parent"] == m(A, "crate/")));
    check("CONTAINS a crate/ -> feature on".into(), has_edge("CONTAINS", &m(A, "crate/"), &f(A, "on")));
    check("c 0.3.0 crate/ is a reference stub (off: no rustc compiled it)".into(), g.nodes.get(&m(C, "crate/")).is_some_and(|r| r["kind"] == "crate" && r["defined_here"] == "false"));

    // ---- P2: ENABLES — what switching something on switches on
    check("ENABLES a extra -> a on (feature -> feature)".into(), has_edge("ENABLES", &f(A, "extra"), &f(A, "on")));
    check("ENABLES a default -> a on".into(), has_edge("ENABLES", &f(A, "default"), &f(A, "on")));
    check("ENABLES b fast -> a 0.1.0 extra (`a/extra`: the dep's feature)".into(), has_edge("ENABLES", &f(B, "fast"), &f(A, "extra")));
    check("ENABLES b fast -> a 0.1.0 crate/ (`a/extra`: and the dep)".into(), has_edge("ENABLES", &f(B, "fast"), &m(A, "crate/")));
    check("ENABLES b old -> a 0.0.9 legacy (renamed dep `a_old` -> package a 0.0.9)".into(), has_edge("ENABLES", &f(B, "old"), &f(A_OLD, "legacy")));
    check("ENABLES b with-c -> c 0.3.0 crate/ (`dep:c`, version from Cargo.lock)".into(), has_edge("ENABLES", &f(B, "with-c"), &m(C, "crate/")));
    check("ENABLES_WEAK b c-turbo -> c turbo (`c?/turbo`)".into(), has_edge("ENABLES_WEAK", &f(B, "c-turbo"), &f(C, "turbo")));
    check("`c?/turbo` is NOT a plain ENABLES and does not pull c".into(), !has_edge("ENABLES", &f(B, "c-turbo"), &f(C, "turbo")) && !has_edge("ENABLES", &f(B, "c-turbo"), &m(C, "crate/")));
    // the build's own selection: crate -> the features it was compiled with
    check("ENABLES a crate/ -> default, on (compiled in)".into(), has_edge("ENABLES", &m(A, "crate/"), &f(A, "default")) && has_edge("ENABLES", &m(A, "crate/"), &f(A, "on")));
    let built = |feature: &str| g.edges.iter().any(|(k, from, to)| k == "ENABLES" && to == feature && from.ends_with("crate/"));
    check("a extra / b fast: no crate ENABLES them = never built".into(), !built(&f(A, "extra")) && !built(&f(B, "fast")) && built(&f(A, "on")));

    // ---- P2 (a): GATED_BY from items rustc KEPT
    let e = read_tables(&out, "edges").unwrap();
    let (ef, et, ek, en, ep, ec) = (e.col("from"), e.col("to"), e.col("kind"), e.col("negated"), e.col("partial"), e.col("count"));
    // `negated` of the GATED_BY edge from -> to (the lib and its test harness
    // both dump it: they must agree)
    let gate_col = |from: &str, to: &str, c: usize| -> String {
        let mut v: Vec<&str> = e.rows.iter().filter(|r| r[ek] == "GATED_BY" && r[ef] == from && r[et] == to).map(|r| r[c].as_str()).collect();
        v.sort();
        v.dedup();
        if v.is_empty() { "<no edge>".into() } else { v.join("|") }
    };
    let negated = |from: &str, to: &str| gate_col(from, to, en);
    // (partial, negated, count)
    let gate = |from: &str, to: &str| (gate_col(from, to, ep), gate_col(from, to, en), gate_col(from, to, ec));
    for (d, feature, neg) in [
        ("gated_on().", "on", "false"),
        ("not_extra().", "extra", "true"),
        ("on_not_extra().", "on", "false"),
        ("on_not_extra().", "extra", "true"),
        ("pick().", "extra", "true"),
        ("Config#on_field.", "on", "false"),
    ] {
        let got = negated(&m(A, d), &f(A, feature));
        check(format!("GATED_BY a {d} -> {feature} negated={neg} (got {got})"), got == neg);
    }
    check("kept item: cfg column is the canonical predicate".into(), col(&m(A, "on_not_extra()."), "cfg") == "cfg(all(feature = \"on\", not(feature = \"extra\")))");
    check("kept item: a resolved node (kind fn, defined, no stub twin)".into(), col(&m(A, "gated_on()."), "kind") == "fn" && !g.nodes.contains_key(&m(A, "gated_on().`cfg(feature = \"on\")`:")));
    check("negated / partial are NULL on every edge that is not GATED_BY, set on every GATED_BY".into(), e.rows.iter().all(|r| (r[ek] == "GATED_BY") != r[en].is_empty() && (r[ek] == "GATED_BY") != r[ep].is_empty()));
    check("an item's OWN gate is not partial".into(), gate(&m(A, "gated_on()."), &f(A, "on")) == ("false".into(), "false".into(), "1".into()));

    // ---- P2: a gate INSIDE an item — partial = true, the item is a resolved
    // node with no cfg of its own
    let t = |p: &str, n: &str, c: &str| (p.to_string(), n.to_string(), c.to_string());
    check("partial: body_gate() -> extra (`cfg!(feature = \"extra\")` in its body)".into(), gate(&m(A, "body_gate()."), &f(A, "extra")) == t("true", "false", "1"));
    check("partial: stmt_gates() -> on (one gated block)".into(), gate(&m(A, "stmt_gates()."), &f(A, "on")) == t("true", "false", "1"));
    check("partial: stmt_gates() -> extra, 2 sites, NOT negated (one `not`, one plain)".into(), gate(&m(A, "stmt_gates()."), &f(A, "extra")) == t("true", "false", "2"));
    check("partial gate: stmt_gates() itself has no cfg and is a plain fn".into(), col(&m(A, "stmt_gates()."), "cfg").is_empty() && col(&m(A, "stmt_gates()."), "kind") == "fn");
    check("partial: a crate/ -> extra (the gated `use` is a part of the module it stands in)".into(), gate(&m(A, "crate/"), &f(A, "extra")) == t("true", "false", "1"));
    check("own gate + a gate inside, same feature: ONE edge, not partial, 2 sites".into(), gate(&m(A, "own_and_inside()."), &f(A, "on")) == t("false", "false", "2"));
    let ewi = format!("{A}extra_with_inside().`cfg(feature = \"extra\")`:");
    check("inside a compiled-out item: stub -> extra is its own gate, stub -> on is partial".into(), gate(&ewi, &f(A, "extra")) == t("false", "false", "1") && gate(&ewi, &f(A, "on")) == t("true", "false", "1"));
    check("cfg_attr switches an attribute: attr_only() has no GATED_BY".into(), !e.rows.iter().any(|r| r[ek] == "GATED_BY" && r[ef] == m(A, "attr_only().")));
    let stmt_site = mimir_schema::edge_key(&m(A, "stmt_gates()."), &f(A, "extra"), mimir_schema::EdgeKind::GatedBy);
    let sp = read_tables(&out, "spans").unwrap();
    let (st_, sk, sf) = (sp.col("target"), sp.col("key"), sp.col("file"));
    let gate_site = mimir_schema::edge_key(&m(A, "gated_on()."), &f(A, "on"), mimir_schema::EdgeKind::GatedBy);
    check("GATED_BY site (the attribute's line) is a code_spans row".into(), sp.rows.iter().any(|r| r[st_] == "edge" && r[sk] == gate_site && r[sf] == "a/src/lib.rs"));
    let stmt_lines: BTreeSet<&str> = sp.rows.iter().filter(|r| r[st_] == "edge" && r[sk] == stmt_site).map(|r| r[sp.col("start_line")].as_str()).collect();
    check(format!("the two partial sites of stmt_gates() -> extra are two span rows ({stmt_lines:?})"), stmt_lines.len() == 2);

    // ---- P2 (b): items the build compiled OUT — stubs from the token scan
    let stub = |d: &str, pred: &str| format!("{A}{d}`{pred}`:");
    let x = "cfg(feature = \"extra\")";
    let extra = stub("extra().", x);
    check(
        "stub a extra(): kind=cfg_gated_out ty=fn cfg=predicate file+line, parent a crate/".into(),
        g.nodes.get(&extra).is_some_and(|r| {
            r["kind"] == "cfg_gated_out" && r["ty"] == "fn" && r["cfg"] == x && r["file"] == "a/src/lib.rs" && !r["start_line"].is_empty() && r["parent"] == m(A, "crate/") && r["name"] == "extra"
        }),
    );
    check("stub a extra(): what the source says — written visibility + doc line, nothing resolved".into(), g.nodes.get(&extra).is_some_and(|r| r["visibility"] == "pub" && r["effective_visibility"].is_empty() && r["doc"] == "Compiled OUT: nothing enables `extra`." && r["is_test"] == "false"));
    check("the compiled-out extra() has NO resolved node".into(), !g.nodes.contains_key(&m(A, "extra().")));
    check("GATED_BY stub extra() -> extra, not negated".into(), negated(&extra, &f(A, "extra")) == "false");
    check("CONTAINS a crate/ -> stub extra()".into(), has_edge("CONTAINS", &m(A, "crate/"), &extra));
    // the on/off pair: the resolved pick() (not(extra)) AND the stub pick() (extra)
    let pick = stub("pick().", x);
    check("pair: resolved pick() + stub pick() are two ids".into(), g.nodes.get(&m(A, "pick().")).is_some_and(|r| r["kind"] == "fn") && g.nodes.get(&pick).is_some_and(|r| r["kind"] == "cfg_gated_out"));
    check("stub field Config#extra_field (ty=field, level part), parent the REAL Config#".into(), g.nodes.get(&stub("Config#extra_field.", x)).is_some_and(|r| r["ty"] == "field" && r["level"] == "part" && r["parent"] == m(A, "Config#")));
    check("stub method impl#[Config]extra_method (ty=method), parent the REAL impl".into(), g.nodes.get(&stub("impl#[Config]extra_method().", x)).is_some_and(|r| r["ty"] == "method" && r["parent"] == m(A, "impl#[Config]")));
    // a module FILE rustc never loaded
    let extra_mod = stub("extra_mod/", x);
    check("stub mod extra_mod (ty=mod, level module)".into(), g.nodes.get(&extra_mod).is_some_and(|r| r["ty"] == "mod" && r["level"] == "module" && r["file"] == "a/src/lib.rs"));
    let on_inside = format!("{extra_mod}on_inside().`cfg(feature = \"on\")`:");
    check(
        "stub in the never-loaded file a/src/extra_mod.rs, parent = the mod's stub".into(),
        g.nodes.get(&on_inside).is_some_and(|r| r["kind"] == "cfg_gated_out" && r["file"] == "a/src/extra_mod.rs" && r["parent"] == extra_mod),
    );
    check("its own feature `on` is ON, yet it is compiled out: still a stub, GATED_BY on".into(), negated(&on_inside, &f(A, "on")) == "false");
    check("an item WITHOUT a cfg inside the compiled-out file is no stub (the mod's stub contains it)".into(), !g.nodes.keys().any(|id| id.contains("in_file")));
    let ghost = stub("ghost().", "cfg(feature = \"ghost\")");
    check("stub ghost() -> undeclared feature ghost (visibility private)".into(), negated(&ghost, &f(A, "ghost")) == "false" && col(&ghost, "visibility") == "private");
    check("stubs never carry CALLS / USES_TYPE (nothing resolved)".into(), g.edges.iter().all(|(k, from, to)| matches!(k.as_str(), "CONTAINS" | "GATED_BY") || !(from.contains("`cfg(") || to.contains("`cfg("))));
    check("no stub for a `use` (it is a partial gate of its module)".into(), !g.nodes.keys().any(|id| id.contains("_gated_use")));

    // ---- the lower bound is a NUMBER: a's lib unit
    let stats: Vec<mimir_driver::CrateStats> = std::fs::read_dir(&out)
        .unwrap()
        .flatten()
        .filter(|e| e.path().to_string_lossy().ends_with(".stats.json"))
        .map(|e| serde_json::from_slice(&std::fs::read(e.path()).unwrap()).unwrap())
        .collect();
    let a_lib = stats.iter().find(|s| s.package == "a" && s.version == "0.1.0" && !s.test_harness).expect("a lib stats");
    check(format!("a lib: 3 declared features, 2 compiled in, 1 referenced ({} {} {})", a_lib.feature_nodes, a_lib.features_active, a_lib.feature_refs), (a_lib.feature_nodes, a_lib.features_active, a_lib.feature_refs) == (3, 2, 1));
    check(
        format!("a lib: 7 own gates of kept items, 8 stubs with 8 own gates, 5 partial ({} {} {} {})", a_lib.gated_by_active, a_lib.gated_out_stubs, a_lib.gated_by_stubs, a_lib.gated_by_partial),
        (a_lib.gated_by_active, a_lib.gated_out_stubs, a_lib.gated_by_stubs, a_lib.gated_by_partial) == (7, 8, 8, 5),
    );
    check(format!("a lib: scanned lib.rs + the never-loaded extra_mod.rs, none failed ({})", a_lib.cfg_scan_files), a_lib.cfg_scan_files == 2 && a_lib.cfg_scan_failed.is_empty() && a_lib.cfg_scan_unresolved_mods.is_empty());
    check(
        format!(
            "a lib: {} feature mentions = {} on an item's own cfg + {} inside an item + 1 that is no edge (the cfg_attr)",
            a_lib.feature_cfg_mentions, a_lib.feature_cfg_attributed, a_lib.feature_cfg_partial
        ),
        (a_lib.feature_cfg_mentions, a_lib.feature_cfg_attributed, a_lib.feature_cfg_partial) == (23, 15, 7),
    );
    check(format!("a lib: api items {} / documented {}", a_lib.api_items, a_lib.api_documented), a_lib.api_items == 30 && a_lib.api_documented == 9);
    // a 0.0.9 is a dependency (origin library): features and kept-item gates
    // are written, the token scan is not run on it by default
    let legacy_stub = format!("{A_OLD}legacy().`cfg(feature = \"legacy\")`:");
    check("dependency a 0.0.9: compiled-out legacy() is NOT scanned by default (MIMIR_CFG_SCAN=local)".into(), !g.nodes.contains_key(&legacy_stub));
    let old_lib = stats.iter().find(|s| s.package == "a" && s.version == "0.0.9").expect("a-old stats");
    check("dependency a 0.0.9: scan did not run (0 files), its feature node is there".into(), old_lib.cfg_scan_files == 0 && old_lib.gated_out_stubs == 0 && old_lib.feature_nodes == 1);
    let b_lib = stats.iter().find(|s| s.package == "b" && s.crate_name == "b" && !s.test_harness).expect("b lib stats");
    check("b lib: every [features] entry resolved (c from Cargo.lock)".into(), b_lib.feature_enables_unresolved.is_empty() && b_lib.feature_nodes == 4 && b_lib.features_active == 0);

    eprintln!("| check | result |\n|---|---|");
    for (n, ok) in &results {
        eprintln!("| {n} | {} |", if *ok { "PASS" } else { "FAIL" });
    }
    let failed: Vec<_> = results.iter().filter(|(_, ok)| !ok).map(|(n, _)| n).collect();
    assert!(failed.is_empty(), "failed: {failed:#?}");
}

/// `MIMIR_CFG_SCAN=all`: the token scan also covers dependencies (the
/// universe ring) — a 0.0.9's compiled-out `legacy()` becomes a stub.
#[test]
fn fixture_cfg_scan_all_covers_dependencies() {
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-scanall-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .env(mimir_driver::ENV_CFG_SCAN, "all")
        .args(["--out", out.to_str().unwrap(), "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success());
    let g = load(&out);
    let stub = format!("{A_OLD}legacy().`cfg(feature = \"legacy\")`:");
    let row = g.nodes.get(&stub).unwrap_or_else(|| panic!("no stub {stub}"));
    assert_eq!((row["kind"].as_str(), row["origin"].as_str(), row["ty"].as_str()), ("cfg_gated_out", "library", "fn"));
    // the same file spelling as the crate's resolved items
    assert_eq!(row["file"], g.nodes[&format!("{A_OLD}add().")]["file"]);
    assert!(row["file"].ends_with("src/lib.rs"), "{}", row["file"]);
    assert!(g.edges.contains(&("GATED_BY".into(), stub, format!("{A_OLD}`feature=legacy`:"))));
}

/// `--workspace-wrapper` (clippy's RUSTC_WORKSPACE_WRAPPER): only members go
/// through the driver, deps are plain rustc → no sidecars for a-old. The name
/// `a` is ambiguous in the metadata map (0.1.0 and 0.0.9); b's direct dep
/// `a_old` must still resolve via `--extern a_old=…` ↔ cargo's resolve graph.
#[test]
fn fixture_workspace_wrapper_resolves_two_versions_via_extern_argv() {
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-ww-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .args(["--out", out.to_str().unwrap(), "--workspace-wrapper", "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success());
    let g = load(&out);
    let run = format!("{B}run().");
    assert!(g.edges.contains(&("CALLS".into(), run.clone(), format!("{A_OLD}add()."))), "a_old::add not resolved to a 0.0.9");
    assert!(g.edges.contains(&("CALLS".into(), run, format!("{A}add()."))));
    assert!(g.nodes.values().all(|r| r["version"] != "?"), "unresolved version in workspace-wrapper mode");
    // a-old is not a member → not dumped, only referenced
    assert!(g.nodes.get(&format!("{A_OLD}add().")).is_some_and(|r| r["defined_here"] == "false"));
}

/// Symbols in a SCIP index file, read without a protobuf dependency: every
/// length-delimited string that starts with `rust-analyzer cargo `.
fn scip_symbols(bytes: &[u8]) -> HashSet<String> {
    let pat = b"rust-analyzer cargo ";
    let mut out = HashSet::new();
    let mut i = 0;
    while i + pat.len() <= bytes.len() {
        if &bytes[i..i + pat.len()] == pat {
            // 1- or 2-byte varint length prefix right before the string
            let mut cands = Vec::new();
            if i >= 1 && bytes[i - 1] < 0x80 {
                cands.push(bytes[i - 1] as usize);
            }
            if i >= 2 && bytes[i - 2] >= 0x80 && bytes[i - 1] < 0x80 {
                cands.push(((bytes[i - 2] & 0x7f) as usize) | ((bytes[i - 1] as usize) << 7));
            }
            for len in cands {
                if len >= pat.len() && i + len <= bytes.len() {
                    if let Ok(s) = std::str::from_utf8(&bytes[i..i + len]) {
                        if !s.chars().any(|c| c.is_control()) {
                            out.insert(s.to_string());
                        }
                    }
                }
            }
            i += pat.len();
        } else {
            i += 1;
        }
    }
    out
}

/// One package with a lib, a bin, a test, a bench and an example ALL called
/// `twin`, plus a test and a bench called `same` (tests/fixture-targets), each
/// defining `helper()`: no two TARGETS share a node id. The lib has
/// rust-analyzer's ids; a target's `--test` harness has its target's.
#[test]
fn targets_of_one_package_share_no_id() {
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture-targets"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-targets-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .args(["--out", out.to_str().unwrap(), "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success(), "cargo mimir-dump failed");
    assert!(!out.join(".errors").exists(), "walk errors");

    // every unit's dump on its own; a unit's TARGET is told by its crate
    // root's file (one root file per target)
    const TWIN: &str = "rust-analyzer cargo twin 0.1.0 ";
    let mut by_target: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
    let mut units = 0;
    for f in std::fs::read_dir(&out).unwrap().flatten().map(|e| e.path()) {
        if !f.to_string_lossy().ends_with(".nodes.arrow") {
            continue;
        }
        let dir = out.join(".unit").join(f.file_name().unwrap());
        std::fs::create_dir_all(&dir).unwrap();
        std::fs::copy(&f, dir.join(f.file_name().unwrap())).unwrap();
        let t = read_tables(&dir, "nodes").unwrap();
        let (id, kind, here, file) = (t.col("id"), t.col("kind"), t.col("defined_here"), t.col("file"));
        let own: Vec<&Vec<String>> = t.rows.iter().filter(|r| r[here] == "true" && r[id].starts_with(TWIN)).collect();
        let Some(root) = own.iter().find(|r| r[kind] == "crate") else { continue };
        units += 1;
        by_target.entry(root[file].clone()).or_default().extend(own.iter().map(|r| r[id].clone()));
    }
    let targets: Vec<&str> = by_target.keys().map(String::as_str).collect();
    assert_eq!(
        targets,
        vec!["twin/benches/same.rs", "twin/benches/twin.rs", "twin/examples/twin.rs", "twin/src/lib.rs", "twin/src/main.rs", "twin/tests/same.rs", "twin/tests/twin.rs"],
        "every target was dumped"
    );
    assert!(units >= 9, "7 targets + the harness of the lib and of the bin: {units} units");

    // THE property: an id belongs to one target
    let mut owner: BTreeMap<&String, &String> = BTreeMap::new();
    let mut shared = Vec::new();
    for (target, ids) in &by_target {
        for id in ids {
            if let Some(other) = owner.insert(id, target) {
                shared.push(format!("{id}  ({other} and {target})"));
            }
        }
    }
    assert!(shared.is_empty(), "ids shared between two targets of one package: {shared:#?}");

    // and the ids are these
    let has = |target: &str, d: &str| by_target[target].contains(&format!("{TWIN}{d}"));
    for d in ["crate/", "helper().", "run().", "Config#", "tests/helps()."] {
        assert!(has("twin/src/lib.rs", d), "the lib (and its harness) keeps rust-analyzer's id `{d}`");
    }
    for (target, prefix) in [
        ("twin/src/main.rs", "`bin=twin`:"),
        ("twin/tests/twin.rs", "`test=twin`:"),
        ("twin/tests/same.rs", "`test=same`:"),
        ("twin/benches/twin.rs", "`bench=twin`:"),
        ("twin/benches/same.rs", "`bench=same`:"),
        ("twin/examples/twin.rs", "`example=twin`:"),
    ] {
        assert!(by_target[target].iter().all(|id| id[TWIN.len()..].starts_with(prefix)), "{target}: every id starts with {prefix}: {:#?}", by_target[target]);
        assert!(has(target, &format!("{prefix}crate/")) && has(target, &format!("{prefix}helper().")), "{target}");
    }
    // the bin's own harness is the bin target
    assert!(has("twin/src/main.rs", "`bin=twin`:tests/helps().") && has("twin/src/main.rs", "`bin=twin`:Config#"));
}

/// BYTE-IDENTITY against `rust-analyzer scip` on the same fixture: every
/// symbol rust-analyzer emits for an item of a / b (params and locals aside)
/// must be a node id of ours, byte for byte. Skips (with a message) when the
/// pinned toolchain has no rust-analyzer component.
#[test]
fn matches_rust_analyzer_scip() {
    let ra_ok = Command::new("rust-analyzer")
        .env("RUSTUP_TOOLCHAIN", mimir_driver::MIMIR_NIGHTLY)
        .arg("--version")
        .output()
        .is_ok_and(|o| o.status.success());
    if !ra_ok {
        eprintln!("SKIP: no rust-analyzer for {} (rustup component add rust-analyzer)", mimir_driver::MIMIR_NIGHTLY);
        return;
    }
    let src = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixture"));
    let work = PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(format!("fixture-ra-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&work);
    copy_dir(&src, &work);
    let scip = work.join("index.scip");
    let st = Command::new("rust-analyzer")
        .env("RUSTUP_TOOLCHAIN", mimir_driver::MIMIR_NIGHTLY)
        .current_dir(&work)
        .args(["scip", ".", "--output"])
        .arg(&scip)
        .status()
        .unwrap();
    assert!(st.success(), "rust-analyzer scip failed");
    let ra = scip_symbols(&std::fs::read(&scip).unwrap());
    assert!(ra.len() > 10, "too few symbols parsed from index.scip: {ra:?}");

    let out = work.join("out");
    let st = Command::new(env!("CARGO_BIN_EXE_cargo-mimir-dump"))
        .current_dir(&work)
        .args(["--out", out.to_str().unwrap(), "--driver", env!("CARGO_BIN_EXE_mimir-driver")])
        .status()
        .unwrap();
    assert!(st.success());
    let g = load(&out);

    let ours: HashSet<&String> = g.nodes.keys().collect();
    let mut compared = Vec::new();
    let mut missing = Vec::new();
    for s in &ra {
        let Some((pkg, _ver, desc)) = mimir_schema::moniker::parse(s) else { continue };
        if !matches!(pkg, "a" | "b") || desc.ends_with(')') {
            continue; // params / locals: rust-analyzer writes them as `local N`
        }
        // rust-analyzer gives the bin's main() / crate/ the lib's id (its own
        // duplicate-symbol warning); ours are target-prefixed `` `bin=bctl`: ``.
        if pkg == "b" && (desc == "main()." || desc == "crate/") && !ours.contains(s) {
            continue;
        }
        compared.push(s.clone());
        if !ours.contains(s) {
            missing.push(s.clone());
        }
    }
    compared.sort();
    eprintln!("rust-analyzer symbols compared ({}):", compared.len());
    for c in &compared {
        eprintln!("  {} {c}", if missing.contains(c) { "MISSING" } else { "ok     " });
    }
    // also std / core references we resolved: same spelling?
    let ra_lang: Vec<&String> = ra.iter().filter(|s| s.contains("github.com/rust-lang/rust/library")).collect();
    let both: usize = ra_lang.iter().filter(|s| ours.contains(*s)).count();
    eprintln!("lang symbols: rust-analyzer {} / also ours {}", ra_lang.len(), both);
    for l in &ra_lang {
        eprintln!("  {} {l}", if ours.contains(*l) { "ours   " } else { "not-ref" });
    }
    assert!(compared.len() >= 12, "compared too few: {compared:?}");
    assert!(missing.is_empty(), "rust-analyzer symbols we do not produce: {missing:#?}");
}