Skip to content

Implement stub sets for reusable stub groups#4594

Open
feliperodri wants to merge 4 commits intomodel-checking:mainfrom
feliperodri:stub-sets
Open

Implement stub sets for reusable stub groups#4594
feliperodri wants to merge 4 commits intomodel-checking:mainfrom
feliperodri:stub-sets

Conversation

@feliperodri
Copy link
Copy Markdown
Contributor

Add kani::stub_set! macro and #[kani::use_stub_set] attribute for defining reusable groups of stubs that can be applied to multiple proof harnesses without repeating individual #[kani::stub] annotations.

Resolves #2096.

Problem

When multiple proof harnesses need the same set of stubs (e.g., mocking I/O, randomness, or network calls), users must duplicate #[kani::stub(orig, repl)] annotations on every harness. This is verbose, error-prone, and makes it hard to maintain consistent stub configurations across a test suite.

Solution

kani::stub_set! macro

Defines a named, reusable group of stub pairs:

kani::stub_set! {
    pub my_io_stubs {
        stub(std::fs::read, mock_read)
        stub(std::fs::write, mock_write)
        use_stub_set(other_stubs)  // compose with other sets
    }
}

#[kani::use_stub_set] attribute

Applies a stub set to a harness:

#[kani::proof]
#[kani::use_stub_set(my_io_stubs)]
fn check_with_mocked_io() { ... }

Features

  • Composition: Stub sets can include use_stub_set(other_set) entries to compose sets
  • Visibility: pub modifier for cross-module access
  • Combining: #[kani::use_stub_set] works alongside individual #[kani::stub] attributes
  • Per-harness: Different harnesses can use different stub sets
  • Circular reference detection: Errors on circular use_stub_set references

Implementation

  • stub_set! generates a const with a #[kanitool::stub_set(...)] attribute encoding the stub pairs
  • use_stub_set resolution in attributes.rs reads the attribute, resolves paths relative to the harness module, and expands the pairs into the harness's stub list
  • Path resolution in resolve.rs extended to look up stub_set consts

Testing

5 tests covering:

  • stub_set_basic.rs — basic stub set definition and usage
  • stub_set_composed.rs — composing stub sets via use_stub_set entries
  • stub_set_module.rs — cross-module access with pub visibility
  • stub_set_per_harness.rs — different stub sets per harness
  • stub_set_with_individual.rs — combining stub sets with individual #[kani::stub]

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@feliperodri feliperodri added this to the Stubbing milestone Apr 28, 2026
@feliperodri feliperodri added [C] Feature / Enhancement A new feature request or enhancement to an existing feature. Z-Contracts Issue related to code contracts labels Apr 28, 2026
@github-actions github-actions Bot added Z-EndToEndBenchCI Tag a PR to run benchmark CI Z-CompilerBenchCI Tag a PR to run benchmark CI labels Apr 28, 2026
@feliperodri feliperodri force-pushed the stub-sets branch 2 times, most recently from bfe1c5b to af1c2d1 Compare April 28, 2026 14:42
Add kani::stub_set! macro and #[kani::use_stub_set] attribute for
defining reusable groups of stubs that can be applied to multiple
proof harnesses.

Stub sets support:
- Grouping multiple stub(original, replacement) pairs under a name
- Composing stub sets via use_stub_set(other_set) entries
- Visibility modifiers for cross-module access (pub)
- Combining with individual #[kani::stub] attributes
- Different stub sets per harness
- Circular reference detection

Implementation:
- stub_set! generates a const with #[kanitool::stub_set(...)] attribute
- use_stub_set resolves the const, reads the attribute, and expands
  the stub pairs into the harness's stub list
- Paths in stub sets are resolved relative to the harness module

Resolves model-checking#2096
Mark stub_set! doc examples as `ignore` since kanitool is only
registered when running under the Kani compiler, not plain rustc.

Add a doc comment to the pub macro arm so pub stub sets appear
meaningfully in rustdoc. The non-pub arm already correctly applies
#[doc(hidden)].
Add a test that verifies circular stub set references (set_a → set_b →
set_a) are detected and reported as errors. This exercises the DFS
stack-based cycle detection in collect_stubs_from_set.
@feliperodri feliperodri marked this pull request as ready for review April 28, 2026 15:16
@feliperodri feliperodri requested a review from a team as a code owner April 28, 2026 15:16
Add expected-output test for invalid entries in stub_set! (e.g.,
unknown_entry(foo)) to verify the error path in collect_stubs_from_set.

Replace bare unreachable!() in the StubSet arm of harness_attributes
with a descriptive message for easier debugging if the invariant is
ever violated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[C] Feature / Enhancement A new feature request or enhancement to an existing feature. Z-CompilerBenchCI Tag a PR to run benchmark CI Z-Contracts Issue related to code contracts Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement stub-sets

1 participant