Autoharness: verify Debug and Display implementations - #4701
Merged
feliperodri merged 1 commit intoAug 24, 2026
Conversation
feliperodri
force-pushed
the
autoharness-fmt-impls
branch
from
August 24, 2026 19:45
c52c099 to
3cac4a0
Compare
feliperodri
approved these changes
Aug 24, 2026
The fmt methods of Debug/Display implementations were always skipped, since their '&mut Formatter' argument has no Arbitrary implementation (Formatter wraps private state and a dyn Write sink and cannot be synthesized). In the top-100 crates.io evaluation, Formatter arguments accounted for ~1900 skipped functions, the single largest 'Missing Arbitrary' type. Rather than generating a Formatter, generate the harness the way user code exercises these implementations: format a nondeterministic value of the implementing type into a sink that discards the output, via two new models (check_debug_fmt/check_display_fmt) that call core::fmt::write(&mut Sink, format_args!(..., value)). The Formatter is constructed by the core formatting machinery, so it is always valid, and panics or undefined behavior inside the fmt implementation are detected as usual; reachability follows the format_args reference to the impl. The models are pure core and live in kani_core, so they are available in both library flavors. Detection uses trait_impl_of_assoc plus the Debug/Display diagnostic items; eligibility requires the self type to implement or be able to derive Arbitrary, with the usual skip reason otherwise. Towards model-checking#3832 Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
feliperodri
force-pushed
the
autoharness-fmt-impls
branch
from
August 24, 2026 20:48
3cac4a0 to
d035634
Compare
Member
|
Good catch — addressed. Added |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The
fmtmethods ofDebug/Displayimplementations were always skipped by autoharness: their&mut Formatterargument has noArbitraryimplementation, andFormattercannot be synthesized (it wraps private state and adyn Writesink). In the top-100 crates.io evaluation,Formatterarguments were the single largest "Missing Arbitrary" type (~1,900 skipped functions).Rather than generating a
Formatter, generate the harness the way user code exercises these implementations: format a nondeterministic value of the implementing type into a sink that discards the output, via two new models that callcore::fmt::write(&mut DiscardingSink, format_args!(..., value)). TheFormatteris constructed by the core formatting machinery — so it is always valid — and panics or undefined behavior inside the user'sfmtare detected as usual (reachability follows theformat_args!reference to the impl). The models are purecoreand live inkani_core, available in both library flavors — no optional-model machinery needed.Detection uses
trait_impl_of_assocplus theDebug/Displaydiagnostic items; eligibility requires the self type to implement (or be able to derive)Arbitrary. The self value is generated withkani::anythrough the sharedcall_kani_any_for_tyhelper, so these harnesses are unbounded (full coverage of the self type — no--bounded-argumentsinterplay) and the self type'sInvariant, if any, is assumed just like for a regular argument.Both the eligibility check (
automatic_harness_partition) and the harness generation (AutomaticHarnessPass) go through the samefmt_impl_self_typredicate, so the two cannot disagree about which functions the formatting models handle.A
fmtmethod carrying a function contract is deliberately excluded: the automatic contract harness calls the function directly (and would therefore need aFormatter), and the formatting models reachfmtthrough a function pointer, where contract dispatch does not apply. Such a method is reported as skipped for its&mut Formatterargument, exactly as before this change.Compiler-derived
Debugimplementations are verified too. That is consistent with how autoharness already treats other derived implementations (Clone::clone,PartialEq::eq,PartialOrd::partial_cmp,Default::defaultall get harnesses today), so no separate filter was added.The documented limitations of the approach: the
Formattercarries the default formatting parameters (so paths taken only for a non-default width/precision/fill/alignment/sign or the alternate{:#?}flag are not covered), the sink never fails (so?write-error paths are not covered), and failures may point at a location insidecore::fmtsince the core formatting machinery is verified along with thefmtimplementation.Testing
New script-based test
cargo_autoharness_fmt_impls, covering:Debugimpl (assertion reachable — fails, with the panic message asserted in the expected output),Displayimpl (assertion reachable — fails), so that theDisplaymodel and its compiler branch are exercised by a failing harness too, not only by passing ones,Displayimpl on a compiler-derived self type (passes),Displayimpl on a self type with anInvariant(passes, i.e. the invariant is assumed — verified separately that the body is reached by negating the assertion),Debugimpl (passes),fmtmethod under contract (skipped for its&mut Formatterargument).Full
script-based-presuite (64 tests, including all 20 autoharness tests andverify_std_cmd, sincekani_coreis shared with theno_coreflow),cargo testforkani-compiler/kani-driver/kani_metadata/cprover_bindings,clippy --all-targets, andkani-fmt --checkall pass.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.