hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
fn strip_repo_cfg<'a, I>(tokens: I) -> Vec<&'a str>
where
    I: Iterator<Item = &'a str>,
{
    let mut filtered = Vec::new();
    let mut parts = tokens.peekable();
    while let Some(part) = parts.next() {
        if part == "--cfg" && parts.peek() == Some(&"hibana_repo_tests") {
            let _ = parts.next();
            continue;
        }
        if part == "--cfg=hibana_repo_tests" {
            continue;
        }
        filtered.push(part);
    }
    filtered
}

fn normalise_trybuild_rustflags() {
    let rustflags = std::env::var("RUSTFLAGS").ok();
    let encoded = std::env::var("CARGO_ENCODED_RUSTFLAGS").ok();
    unsafe {
        // SAFETY: this test binary has a single test, and the environment is
        // normalised before trybuild spawns compiler subprocesses.
        if let Some(flags) = rustflags {
            let filtered = strip_repo_cfg(flags.split_whitespace()).join(" ");
            if filtered.is_empty() {
                std::env::remove_var("RUSTFLAGS");
            } else {
                std::env::set_var("RUSTFLAGS", filtered);
            }
        }
        if let Some(flags) = encoded {
            let filtered = strip_repo_cfg(flags.split('\x1f')).join("\x1f");
            if filtered.is_empty() {
                std::env::remove_var("CARGO_ENCODED_RUSTFLAGS");
            } else {
                std::env::set_var("CARGO_ENCODED_RUSTFLAGS", filtered);
            }
        }
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustup_toolchain = std::env::var("RUSTUP_TOOLCHAIN").ok();
    if let Some(minor) = rustup_toolchain
        .as_deref()
        .and_then(parse_rustc_minor_version)
    {
        return Some(minor);
    }

    let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
    let output = std::process::Command::new(rustc)
        .arg("--version")
        .output()
        .ok()?;
    let stdout = String::from_utf8(output.stdout).ok()?;
    parse_rustc_minor_version(&stdout)
}

fn parse_rustc_minor_version(version: &str) -> Option<u32> {
    let version = version.trim_start_matches("rustc ").trim();
    let mut parts = version.split('.');
    match (parts.next(), parts.next()) {
        (Some("1"), Some(minor)) => minor.parse().ok(),
        _ => None,
    }
}

const RUSTC_1_95_STDERR_CASES: &[&str] = &[
    "tests/ui/g-self-send-non-unit.rs",
    "tests/ui/g-roleprogram-witness-mismatch.rs",
    "tests/ui/g-receive-lane-multiple-senders.rs",
    "tests/ui/g-receive-lane-parallel-false-causality.rs",
    "tests/ui/g-receive-lane-route-false-causality.rs",
    "tests/ui/g-roll-reentry-false-causality.rs",
    "tests/ui/g-roll-route-cross-iteration-causality.rs",
    "tests/ui/g-roll-same-label-distinct-inbound-evidence.rs",
    "tests/ui/g-route-one-sided-observer.rs",
    "tests/ui/g-route-passive-outbound-without-evidence.rs",
    "tests/ui/g-route-roll-one-sided-observer.rs",
    "tests/ui/g-par-ambiguous-endpoint-op.rs",
    "tests/ui/g-roll-ambiguous-reentry-exit-outbound.rs",
    "tests/ui/g-route-passive-first-visible-ambiguous.rs",
    "tests/ui/g-route-controller-mismatch.rs",
    "tests/ui/g-route-resolved-cross-arm-distinct-senders.rs",
    "tests/ui/g-route-roll-before-resolve.rs",
    "tests/ui/g-route-unprojectable.rs",
    "tests/ui/g-typed-route-duplicate-label-project.rs",
    "tests/ui/resolver-decision-fn-removed.rs",
];

fn compile_fail(t: &trybuild::TestCases, path: &'static str) {
    t.compile_fail(path);
}

struct StderrSwap {
    originals: Vec<(std::path::PathBuf, std::path::PathBuf, String)>,
}

impl StderrSwap {
    fn for_rustc_1_95(rustc_minor: Option<u32>) -> Option<Self> {
        if rustc_minor != Some(95) {
            return None;
        }

        let mut originals = Vec::new();
        for source in RUSTC_1_95_STDERR_CASES {
            let stem = source
                .strip_prefix("tests/ui/")
                .and_then(|path| path.strip_suffix(".rs"))
                .expect("versioned trybuild fixture path must be tests/ui/*.rs");
            let path = std::path::PathBuf::from(format!("tests/ui/{stem}.stderr"));
            let versioned_path =
                std::path::PathBuf::from(format!("tests/ui-rustc-1-95/{stem}.stderr"));
            let original =
                std::fs::read_to_string(&path).expect("failed to read base trybuild stderr");
            let replacement = std::fs::read_to_string(&versioned_path)
                .expect("failed to read rustc 1.95 trybuild stderr");
            let replacement = replacement.replace("tests/ui-rustc-1-95/", "tests/ui/");
            std::fs::write(&path, replacement).expect("failed to install rustc 1.95 stderr");
            originals.push((path, versioned_path, original));
        }

        Some(Self { originals })
    }
}

impl Drop for StderrSwap {
    fn drop(&mut self) {
        let overwrite = std::env::var_os("TRYBUILD").is_some_and(|value| value == "overwrite");
        for (path, versioned_path, original) in self.originals.drain(..).rev() {
            if overwrite {
                let blessed = std::fs::read_to_string(&path)
                    .expect("failed to read blessed rustc 1.95 stderr");
                std::fs::write(versioned_path, blessed)
                    .expect("failed to persist blessed rustc 1.95 stderr");
            }
            std::fs::write(path, original).expect("failed to restore base trybuild stderr");
        }
    }
}

#[test]
fn g_compile_fails() {
    normalise_trybuild_rustflags();
    let rustc_minor = rustc_minor_version();
    let stderr_swap = StderrSwap::for_rustc_1_95(rustc_minor);
    let t = trybuild::TestCases::new();
    compile_fail(&t, "tests/ui/g-efflist-deref.rs");
    compile_fail(&t, "tests/ui/g-resolver-data-send.rs");
    compile_fail(&t, "tests/ui/g-self-send-non-unit.rs");
    compile_fail(&t, "tests/ui/g-roleprogram-witness-mismatch.rs");
    compile_fail(&t, "tests/ui/g-receive-lane-multiple-senders.rs");
    compile_fail(&t, "tests/ui/g-receive-lane-parallel-false-causality.rs");
    compile_fail(&t, "tests/ui/g-receive-lane-route-false-causality.rs");
    compile_fail(&t, "tests/ui/g-roll-reentry-false-causality.rs");
    compile_fail(&t, "tests/ui/g-roll-route-cross-iteration-causality.rs");
    compile_fail(
        &t,
        "tests/ui/g-roll-same-label-distinct-inbound-evidence.rs",
    );
    compile_fail(&t, "tests/ui/g-par-ambiguous-endpoint-op.rs");
    compile_fail(&t, "tests/ui/g-roll-ambiguous-reentry-exit-outbound.rs");
    compile_fail(&t, "tests/ui/g-route-passive-first-visible-ambiguous.rs");
    compile_fail(&t, "tests/ui/g-route-one-sided-observer.rs");
    compile_fail(&t, "tests/ui/g-route-passive-outbound-without-evidence.rs");
    compile_fail(&t, "tests/ui/g-route-roll-one-sided-observer.rs");
    compile_fail(&t, "tests/ui/g-route-controller-mismatch.rs");
    compile_fail(
        &t,
        "tests/ui/g-route-resolved-cross-arm-distinct-senders.rs",
    );
    compile_fail(&t, "tests/ui/g-route-roll-before-resolve.rs");
    compile_fail(&t, "tests/ui/g-route-unprojectable.rs");
    compile_fail(&t, "tests/ui/g-typed-route-duplicate-label-project.rs");
    compile_fail(&t, "tests/ui/g-message-without-wire-contract.rs");
    t.pass("tests/ui-pass/g-par-many.rs");
    t.pass("tests/ui-pass/g-par-same-role-auto-lanes.rs");
    t.pass("tests/ui-pass/g-par-same-label-distinct-local-endpoints.rs");
    t.pass("tests/ui-pass/g-par-same-label-distinct-outbound-schema.rs");
    t.pass("tests/ui-pass/g-par-same-label-distinct-inbound-evidence.rs");
    t.pass("tests/ui-pass/g-par-same-label-distinct-inbound-same-endpoint.rs");
    t.pass("tests/ui-pass/g-session-template-instances.rs");
    t.pass("tests/ui-pass/g-receive-lane-causal-handoff.rs");
    t.pass("tests/ui-pass/g-roll-reentry-causal-handoff.rs");
    t.pass("tests/ui-pass/g-roll-route-cross-iteration-handoff.rs");
    t.pass("tests/ui-pass/g-route-first-visible-passive-dispatch.rs");
    t.pass("tests/ui-pass/g-route-intrinsic-passive-same-label-frame-evidence.rs");
    t.pass("tests/ui-pass/g-route-merged.rs");
    t.pass("tests/ui-pass/g-route-resolver-scope-nested-par.rs");
    t.pass("tests/ui-pass/g-route-resolved-cross-arm-same-label.rs");
    t.pass("tests/ui-pass/g-route-resolved-cross-arm-same-endpoint-op.rs");
    t.pass("tests/ui-pass/g-route-resolved-cross-arm-overlap-after-left-par.rs");
    t.pass("tests/ui-pass/g-route-resolved-intra-arm-distinct-inbound-evidence.rs");
    t.pass("tests/ui-pass/g-route-resolved-nested-roll-same-endpoint-op.rs");
    t.pass("tests/ui-pass/g-route-static-basic.rs");
    t.pass("tests/ui-pass/g-route-static-prefix-local.rs");
    t.pass("tests/ui-pass/g-route-static-prefix-send.rs");
    t.pass("tests/ui-pass/local_let_program_inference.rs");
    t.pass("tests/ui-pass/local_let_prefix_facade_composition.rs");
    t.pass("tests/ui-pass/local_project_without_public_steps.rs");
    t.pass("tests/ui-pass/role_program_lifetime_free.rs");
    t.pass("tests/ui-pass/readme-route-example.rs");
    t.pass("tests/ui-pass/runtime-transport-recv-frame.rs");
    t.pass("tests/ui-pass/endpoint_transport_erased.rs");
    t.pass("tests/ui-pass/g-generic-role-ids.rs");
    t.pass("tests/ui-pass/g-full-role-domain.rs");
    t.pass("tests/ui-pass/resolver-state-unit.rs");
    t.pass("tests/ui-pass/resolver-wrapper-decide.rs");

    compile_fail(&t, "tests/ui/runtime-storage-removed.rs");
    compile_fail(&t, "tests/ui/runtime-config-removed.rs");
    compile_fail(&t, "tests/ui/runtime-eff-index-removed.rs");
    compile_fail(&t, "tests/ui/runtime-session-id-field-private.rs");
    compile_fail(&t, "tests/ui/runtime-ingress-evidence-private.rs");
    compile_fail(&t, "tests/ui/runtime-received-frame-evidence-private.rs");
    compile_fail(&t, "tests/ui/runtime-decision-arm-index-private.rs");
    compile_fail(&t, "tests/ui/runtime-tap-event-fields-private.rs");
    compile_fail(&t, "tests/ui/runtime-tap-derived-helpers-private.rs");
    compile_fail(&t, "tests/ui/runtime-frame-header-peer-role-removed.rs");
    compile_fail(&t, "tests/ui/runtime-frame-label-new-private.rs");
    compile_fail(
        &t,
        "tests/ui/runtime-transport-error-associated-type-removed.rs",
    );
    compile_fail(
        &t,
        "tests/ui/runtime-transport-custom-error-return-removed.rs",
    );
    compile_fail(&t, "tests/ui/runtime-outgoing-peer-removed.rs");
    compile_fail(&t, "tests/ui/runtime-session-kit-storage-max-rv-removed.rs");
    compile_fail(&t, "tests/ui/runtime-fluent-session-removed.rs");
    compile_fail(&t, "tests/ui/runtime-fluent-role-removed.rs");
    compile_fail(&t, "tests/ui/runtime-fluent-witness-types-removed.rs");
    compile_fail(&t, "tests/ui/public_step_name_import.rs");
    compile_fail(&t, "tests/ui/public_compile_link_boundary.rs");
    compile_fail(&t, "tests/ui/public_fragment_boundary.rs");
    compile_fail(&t, "tests/ui/port-open-constructor.rs");
    compile_fail(&t, "tests/ui/route-branch-decode-removed.rs");
    compile_fail(&t, "tests/ui/route-recv-borrow-endpoint-alias.rs");
    compile_fail(&t, "tests/ui/recv-borrow-endpoint-alias.rs");
    compile_fail(&t, "tests/ui/route-branch-double-recv.rs");
    compile_fail(&t, "tests/ui/send-future-endpoint-alias.rs");
    compile_fail(&t, "tests/ui/endpoint-result-removed.rs");
    compile_fail(&t, "tests/ui/endpoint-error-operation-removed.rs");
    compile_fail(&t, "tests/ui/attach-error-operation-removed.rs");
    compile_fail(&t, "tests/ui/resolver-error-operation-removed.rs");
    compile_fail(&t, "tests/ui/resolver-decision-fn-removed.rs");
    compile_fail(&t, "tests/ui/resolver-decision-resolution-removed.rs");
    compile_fail(&t, "tests/ui/resolver-evaluate-removed.rs");
    compile_fail(&t, "tests/ui/resolver-resolve-decision-private.rs");
    drop(t);
    drop(stderr_swap);
}