Skip to content

Autoharness: per-parameter and trait-impl-derived generic instantiation - #4706

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

Autoharness: per-parameter and trait-impl-derived generic instantiation#4706
tautschnig wants to merge 4 commits into
model-checking:mainfrom
tautschnig:autoharness-generics-c5

Conversation

@tautschnig

Copy link
Copy Markdown
Member

Description

Stacked on #4679 (first commit; review only the last commit).

The top-100 crates.io evaluation (#3832) showed ~8,700 functions skipped as "Generic Function: no candidate type satisfies the function's trait bounds". This PR extends the instantiation search in three ways:

  1. Wider primitive candidates: add u8, i64, u64, f64, f32. The float candidates alone unlock the numerous Float/FloatCore-bounded functions in num-traits and its dependents.
  2. Per-parameter search: after the cheap uniform pass (same candidate for every parameter), search per-parameter combinations, so functions whose parameters need different types (e.g. fn cast<T: Float, U: PrimInt>) are instantiated. Capped at 256 trait-solver queries per function.
  3. Trait-impl-derived candidates: for each type parameter, derive additional candidates from the concrete implementations of the traits it is bound by (capped at 16 per parameter). A parameter bound by a crate-local trait can thus be instantiated with a crate-local type implementing it.

Measured impact (with --bounded-arguments, -j 16): num-traits 75 generic skips → 0 (2,107 → 2,154 harnesses; every public function now harnessed); serde_json 594 → 276; syn 167 → 41.

Testing

cargo_autoharness_generics gains cases for each capability: a float-only trait bound (halve::<f64>), a crate-local trait satisfied only by a struct (frob_it::<Widget>), and parameters needing different types (mixed::<f64, Widget>); needs_exotic (trait with no impls) remains skipped with the updated message. Full script-based autoharness suite passes.

Towards #3832.

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

tautschnig and others added 4 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>
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>
Extend the generic-instantiation search in three ways, found by evaluating
autoharness on the top-100 crates.io crates, where ~8,700 functions were
skipped because no candidate type satisfied their trait bounds:

1. Widen the primitive candidate list with u8, i64, u64, f64 and f32; float
   candidates alone unlock the numerous Float/FloatCore-bounded functions in
   num-traits and its dependents.
2. Search per-parameter candidate combinations (after the cheap uniform
   pass), so functions whose parameters need different types, e.g.
   fn cast<T: Float, U: PrimInt>, are instantiated. The search is capped at
   256 trait-solver queries per function.
3. Derive additional per-parameter candidates from the concrete
   implementations of the traits each parameter is bound by (capped at 16
   per parameter), so parameters bound by crate-local traits can be
   instantiated with the crate's own types implementing them.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig
tautschnig requested a review from a team as a code owner July 31, 2026 21:49
Copilot AI review requested due to automatic review settings July 31, 2026 21:49

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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 31, 2026
@feliperodri feliperodri added the Z-Autoharness Issue related to autoharness subcommand label Aug 1, 2026
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