Skip to content

Autoharness: support generic functions - #4679

Open
tautschnig wants to merge 3 commits into
model-checking:mainfrom
tautschnig:autoharness-generics
Open

Autoharness: support generic functions#4679
tautschnig wants to merge 3 commits into
model-checking:mainfrom
tautschnig:autoharness-generics

Conversation

@tautschnig

Copy link
Copy Markdown
Member

Description

Autoharness now generates harnesses for generic functions. For each generic function, it verifies a single monomorphic instantiation: every type parameter is substituted with the first candidate from a fixed list of primitive types (i32, u32, usize, bool, char) such that all of the function's trait bounds are satisfied — checked properly with the trait solver (rustc_trait_selection::ObligationCtxt) — and lifetime parameters are erased. Functions whose bounds no candidate satisfies (e.g. bounds on user traits with no primitive impls) and functions with const generic parameters are still skipped with the existing "Generic Function" reason.

This handles arbitrary numbers of generic parameters, methods of generic impl blocks (whose impl-level parameters are instantiated too), impl Trait argument position (anonymous type parameters), and generic functions with contracts. For contract harnesses, the harness metadata now stores the definition-level name of the target function rather than the instantiated one, since gen_contracts_metadata matches target_fn against definition-level ContractedFunction names (this previously had no observable effect because generic functions never reached that code path).

Design note on soundness of the reported result: verifying foo::<i32> is an underapproximation of foo's behaviors for all instantiations. The summary table makes this explicit by displaying the instantiated name (foo::<i32>), and the documentation spells out that a successful result covers only the chosen instantiation. Verifying one instantiation per function (rather than a set) keeps verification cost proportional to crate size; extending this to user-configurable instantiation sets is possible follow-up work.

Testing

New script-based test cargo_autoharness_generics covering: unbounded and bounded type parameters, bound-driven candidate selection (impl Into<u64> + Copy correctly skips i32 and picks u32), multiple type parameters, lifetimes, methods of generic impl blocks, a generic function with a contract (verified as proof_for_contract), a genuine bug found at the chosen instantiation (arithmetic overflow), and graceful skipping of unsatisfiable bounds and const generics.

Updated cargo_autoharness_filter/include/exclude tests, whose generic example functions are now instantiated and verified instead of skipped.

Manually verified no regressions in all autoharness and autoderive script-based tests and kani-compiler unit tests.

Note: the two functions previously used to exercise multi-parameter generics in a prototype branch ICE'd the compiler ("type parameter U/#1 out of range"); both are covered by the new test and verify correctly.

Towards #3832 (ticks the "Generics" box, the last unchecked entry together with #4677 and #4678).

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

@tautschnig
tautschnig requested a review from a team as a code owner July 28, 2026 01:06
Copilot AI review requested due to automatic review settings July 28, 2026 01:06
@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 Jul 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for generating automatic harnesses for generic functions by selecting a single monomorphic instantiation per function (based on a fixed primitive candidate list and trait-bound satisfaction via the trait solver), and updates related metadata, docs, and script-based tests to reflect the new behavior.

Changes:

  • Instantiate generic functions for autoharness using primitive candidates and trait-solver checking; erase lifetimes and keep skipping const generics/unsatisfiable bounds.
  • Fix contract-harness metadata to store the definition-level target function name (to match contract metadata lookup behavior).
  • Add/refresh script-based tests and documentation for generic-function autoharness behavior and output.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/script-based-pre/cargo_autoharness_include/src/lib.rs Updates include test source comment to reflect generic instantiation behavior.
tests/script-based-pre/cargo_autoharness_include/include.expected Updates expected output to include instantiated generic function verification.
tests/script-based-pre/cargo_autoharness_generics/src/lib.rs Adds new script-based test crate covering generic instantiation cases and edge cases.
tests/script-based-pre/cargo_autoharness_generics/generics.sh Adds script to run cargo kani autoharness with contracts enabled for the new test.
tests/script-based-pre/cargo_autoharness_generics/generics.expected Adds expected summary lines for generic instantiation successes/failure and skips.
tests/script-based-pre/cargo_autoharness_generics/config.yml Registers the new script-based test (expects failure exit code due to intentional bug).
tests/script-based-pre/cargo_autoharness_generics/Cargo.toml Adds manifest for the new test crate.
tests/script-based-pre/cargo_autoharness_filter/src/lib.rs Adjusts filter test inputs to include a generic function now expected to be harnessed.
tests/script-based-pre/cargo_autoharness_filter/filter.expected Updates expected output counts and entries to include instantiated generic function.
tests/script-based-pre/cargo_autoharness_exclude/src/lib.rs Updates exclude test source comment to reflect generic instantiation behavior.
tests/script-based-pre/cargo_autoharness_exclude/exclude.expected Updates expected output to include instantiated generic function verification.
kani-compiler/src/main.rs Adds rustc_infer / rustc_trait_selection extern crates required for trait-solver usage.
kani-compiler/src/kani_middle/metadata.rs Switches contract harness metadata to use definition-level target function names.
kani-compiler/src/kani_middle/codegen_units.rs Implements generic instantiation candidate selection and predicate checking for autoharness eligibility.
docs/src/reference/experimental/autoharness.md Documents the new “single-instantiation” behavior and its underapproximation implications.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +481 to +485
if let Ok(instance) = Instance::resolve(def, &args)
&& instance.has_body()
{
return Some(instance);
}
tautschnig and others added 2 commits July 29, 2026 00:33
Previously, autoharness skipped all generic functions. Now, it generates a
harness for a single monomorphic instantiation: each type parameter is
substituted with the first candidate from a fixed list of primitive types
(i32, u32, usize, bool, char) such that all of the function's trait bounds
are satisfied, checked with the trait solver
(rustc_trait_selection::ObligationCtxt). Lifetime parameters are erased.
Functions whose bounds no candidate satisfies, or with const generic
parameters, are still skipped as 'Generic Function'.

The generated harness's name reflects the chosen instantiation (e.g.
foo::<i32>), making explicit that verification covers only that
instantiation; the documentation spells out this underapproximation.
Functions with any number of type, lifetime, and (unsupported) const
parameters are handled, including methods of generic impl blocks, impl-Trait
arguments, and functions with contracts. For contract harnesses, harness
metadata now stores the definition-level name of the target function rather
than the instantiated one, since gen_contracts_metadata matches it against
definition-level ContractedFunction names.

This addresses the 'Generics' item of the automatic harness generation
tracking issue, the last unchecked entry together with the invariants and
pointers work.

Towards model-checking#3832

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Rather than the single 'Generic Function' skip reason, attach a detail
explaining what prevented instantiation: const generic parameters, or that
no candidate type satisfies the function's trait bounds. This makes the
skipped-functions table actionable and allows corpus evaluations to
classify the generic-function gap precisely.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig
tautschnig force-pushed the autoharness-generics branch from 525b08a to 52aceef Compare July 29, 2026 00:37
@feliperodri feliperodri added the Z-Autoharness Issue related to autoharness subcommand label Jul 29, 2026
Instantiate usize const generic parameters (by far the most common case,
e.g. array lengths) with the value 2, alongside the existing type-parameter
instantiation; the summary table shows the chosen value as part of the
instantiated name (e.g. with_const::<2>). Non-usize const parameters are
still skipped, now with a precise reason; the check consults the internal
generics since the public identity arguments do not carry the parameter's
type.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Z-Autoharness Issue related to autoharness subcommand Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants