Goal
Integration test exercising the full C.9 pipeline: walk lifts a real Rust source with lifetime relations, marriage classifies the LLBC-emitted Outlives predicates, the substrate verifier composes a caller-callee pair where region demands either match (composition succeeds) or mismatch (composition refuses with RegionCompositionFailure).
Files affected
- Create:
implementations/rust/provekit-walk/tests/region_composition.rs — new integration test file.
- Create:
implementations/rust/provekit-walk/tests/fixtures/region_caller_satisfied.rs — fixture: a caller whose region facts satisfy the callee's pre-condition.
- Create:
implementations/rust/provekit-walk/tests/fixtures/region_caller_unsatisfied.rs — fixture: a caller whose region facts do NOT satisfy the callee's pre-condition.
- Create:
implementations/rust/provekit-walk/tests/fixtures/region_callee.rs — fixture: the callee both fixtures above will compose against.
- Create the corresponding
.llbc files (run charon as needed; existing fixtures show the pattern).
What to ship
- Fixture
region_callee.rs:
fn callee<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32 {
let _ = y;
x
}
(Callee demands Outlives('b, 'a) per its where-clause.)
- Fixture
region_caller_satisfied.rs:
fn caller<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32 {
callee(x, y)
}
(Caller has the same where 'b: 'a clause, so it can discharge callee's demand.)
- Fixture
region_caller_unsatisfied.rs:
fn caller<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 {
callee(x, y)
}
(Caller has NO where-clause, so 'a and 'b are unrelated. Callee's demand Outlives('b, 'a) cannot be discharged.)
- Integration test
region_composition_succeeds_when_where_clause_matches in tests/region_composition.rs:
use provekit_walk::*;
#[test]
fn region_composition_succeeds_when_where_clause_matches() {
let krate = LlbcCrate::from_path(fixture_path("region_caller_satisfied.llbc")).unwrap();
let registry = lift_llbc_crate(&krate, Some("region_caller_satisfied.rs")).unwrap();
let caller = registry.get("caller").expect("caller must lift");
let callee = registry.get("callee").expect("callee must lift");
let composition = compose_function_contracts_checked(caller, callee, &caller.callsites[0]);
assert!(composition.is_ok(), "composition must succeed; got {:?}", composition.err());
}
- Integration test
region_composition_refuses_when_unrelated:
#[test]
fn region_composition_refuses_when_unrelated() {
let krate = LlbcCrate::from_path(fixture_path("region_caller_unsatisfied.llbc")).unwrap();
let registry = lift_llbc_crate(&krate, Some("region_caller_unsatisfied.rs")).unwrap();
let caller = registry.get("caller").expect("caller must lift");
let callee = registry.get("callee").expect("callee must lift");
let composition = compose_function_contracts_checked(caller, callee, &caller.callsites[0]);
match composition {
Err(CompositionError::RegionCompositionFailure { demands }) => {
assert_eq!(demands.len(), 1, "expected exactly one region failure");
// The demand should be Outlives('b, 'a) after substitution into caller's region vocabulary.
// (Substitution is identity here since both sides use the same names, but the demand
// remains undischarged because caller has no where-clause.)
}
other => panic!("expected RegionCompositionFailure, got {:?}", other),
}
}
- Integration test
region_marriage_classifies_outlives_as_lifetime_relative:
#[test]
fn region_marriage_classifies_outlives_as_lifetime_relative() {
let krate = LlbcCrate::from_path(fixture_path("region_callee.llbc")).unwrap();
let llbc_contract = lift_llbc_function(krate.function_by_name("callee").unwrap(), None).unwrap();
let ast_source = std::fs::read_to_string(fixture_path("region_callee.rs")).unwrap();
let ast_contract = lift_function_postcondition(&syn::parse_file(&ast_source).unwrap().items[0]);
let agreement = marry(&ast_contract, &llbc_contract);
match agreement {
LayerAgreement::LlbcExtra(LlbcExtraCategory::LifetimeRelative) |
LayerAgreement::Both(LlbcExtraCategory::LifetimeRelative) => { /* expected */ }
other => panic!("expected LifetimeRelative classification, got {:?}", other),
}
}
Tests required
(All three tests above are the deliverables. Naming + assertions per items 4, 5, 6.)
Acceptance criteria (boolean)
Out of scope
- Cross-kit conformance fixture (separate issue).
- Per-kit IR types regen (separate sweep).
- Late-bound region (HRTB) fixtures.
Dependencies
Single-PR scope
Yes. Three fixtures + one test file.
Goal
Integration test exercising the full C.9 pipeline: walk lifts a real Rust source with lifetime relations, marriage classifies the LLBC-emitted Outlives predicates, the substrate verifier composes a caller-callee pair where region demands either match (composition succeeds) or mismatch (composition refuses with
RegionCompositionFailure).Files affected
implementations/rust/provekit-walk/tests/region_composition.rs— new integration test file.implementations/rust/provekit-walk/tests/fixtures/region_caller_satisfied.rs— fixture: a caller whose region facts satisfy the callee's pre-condition.implementations/rust/provekit-walk/tests/fixtures/region_caller_unsatisfied.rs— fixture: a caller whose region facts do NOT satisfy the callee's pre-condition.implementations/rust/provekit-walk/tests/fixtures/region_callee.rs— fixture: the callee both fixtures above will compose against..llbcfiles (run charon as needed; existing fixtures show the pattern).What to ship
region_callee.rs:(Callee demands
Outlives('b, 'a)per its where-clause.)region_caller_satisfied.rs:(Caller has the same
where 'b: 'aclause, so it can discharge callee's demand.)region_caller_unsatisfied.rs:(Caller has NO where-clause, so 'a and 'b are unrelated. Callee's demand
Outlives('b, 'a)cannot be discharged.)region_composition_succeeds_when_where_clause_matchesintests/region_composition.rs:region_composition_refuses_when_unrelated:region_marriage_classifies_outlives_as_lifetime_relative:Tests required
(All three tests above are the deliverables. Naming + assertions per items 4, 5, 6.)
Acceptance criteria (boolean)
cargo test -p provekit-walk --test region_compositionruns and 3 tests passcargo check --workspacecleanmake conformanceexits 0region_factsorformal_regions(verifies the lifter is actually emitting region structure)RegionCompositionFailuretest (5) catches the unsatisfied case before any predicate-level composition is attemptedOut of scope
Dependencies
Single-PR scope
Yes. Three fixtures + one test file.