Fill omitted defaulted generic parameters during type resolution - #4915
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Fully omitted generic argument lists still bypass default filling.
Review effort: Balanced
Findings: 1
What changed in this PR
Fills omitted trailing default type parameters during contract target resolution.
Changes:
- Instantiates omitted type defaults using prior generic arguments.
- Adds positive and negative regression coverage.
- Leaves const defaults unsupported.
| File | Description |
|---|---|
kani-compiler/src/kani_middle/resolve/type_resolution.rs |
Adds default type argument resolution. |
tests/kani/FunctionContracts/generic_default_argument_fill.rs |
Tests successful default filling. |
tests/expected/function-contract/generic_default_missing_required.rs |
Tests missing required parameters. |
tests/expected/function-contract/generic_default_missing_required.expected |
Records expected diagnostic. |
tests/expected/function-contract/generic_default_const_param.rs |
Tests unsupported const defaults. |
tests/expected/function-contract/generic_default_const_param.expected |
Records expected diagnostic. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
tautschnig
approved these changes
Sep 30, 2026
An omitted trailing type parameter with a declared default now resolves from that default, instantiated with the arguments so far (what rustc does for omitted arguments): <Vec<u8> as Trait>::m resolves as written, where the omitted allocator default previously kept the uninstantiated type. This unblocks std targets of the same shape, such as Challenge 24's <vec::IntoIter<u8> as Iterator>::__iterator_get_unchecked. A parameter with no default, or a const parameter, keeps the uninstantiated type. A path with no generic arguments at all (PathArguments::None, e.g. a bare Wrapper for struct Wrapper<T = u8>) is now also treated as an empty argument list, so an all-defaulted type written with no argument list resolves too. Parenthesized arguments still keep the uninstantiated type, as before.
kasimte
force-pushed
the
arc-defaults-fill
branch
from
September 30, 2026 19:19
913f8a6 to
7f77075
Compare
feliperodri
enabled auto-merge
September 30, 2026 21:13
tautschnig
reviewed
Oct 1, 2026
auto-merge was automatically disabled
October 1, 2026 12:00
Head branch was pushed to by a user without write access
feliperodri
enabled auto-merge
October 1, 2026 13:16
feliperodri
disabled auto-merge
October 1, 2026 20:26
Merged
via the queue into
model-checking:main
with commit Oct 1, 2026
6934274
33 of 34 checks passed
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.

A
proof_for_contracttarget that omits a trailing generic parameter with a declared default failed to resolve withMissingTraitImpl. For example<Vec<u8> as Trait>::m, or the natural spelling of<vec::IntoIter<u8> as Iterator>::__iterator_get_unchecked, a target in the Challenge 24 submission (model-checking/verify-rust-std#689); both omit the allocator parameter. The parameter-count check kept the uninstantiated type instead of filling the default.This PR fills an omitted trailing parameter from its declared default, instantiated with the arguments so far, matching what rustc does for omitted arguments. The logic lives in
default_type_arg, called frominstantiate_path_args's substitution loop.A path written with no generic arguments at all (a bare
Wrapperforstruct Wrapper<T = u8>) is treated as an empty argument list, so an all-defaulted type resolves too. Parenthesized arguments keep the uninstantiated type.Verification
-Zfunction-contracts)tests/kani/FunctionContracts/generic_default_argument_fill.rsVec<u8>fillsA = Global); a sibling impl with a distinct postcondition (Vec<u16>), so each harness only verifies if resolution picks its own impl; a default referencing an earlier parameter (Pair<T, U = T>atPair<u8>fillsU = u8); the explicit spelling (Vec<u16, std::alloc::Global>) unchanged; and an all-defaulted type written with no argument list (AllDefaultforstruct AllDefault<T = u8>) fillsT = u8.tests/expected/function-contract/generic_default_missing_required.rsMissingTraitImpl(expected-output test; this diagnostic is the pass).NoDefault<u8>omits a parameter with no default, so only declared defaults are filled.tests/expected/function-contract/generic_default_missing_bare.rsMissingTraitImpl(expected-output test; this diagnostic is the pass).NoDefaultBarewritten with no argument list omits a parameter with no default, so the no-arguments path still keeps the uninstantiated type.tests/expected/function-contract/generic_default_const_param.rsMissingTraitImpl(expected-output test; this diagnostic is the pass).WithConst<u8>omits a defaulted const parameter; only defaulted type parameters are filled, so the const default is not filled and the target keeps the uninstantiated type.The four original targets were confirmed locally when this PR was first submitted (
generic_default_argument_fill4/4, the two negatives failingMissingTraitImpl, resolver suites unchanged atgeneric_argument_instantiation6,cross_module_multiple_impls7,multiple_inherent_impls3). This revision adds the no-arguments case (check_all_parameters_defaulted) and thegeneric_default_missing_barenegative; CI runs the full suite on the pinned toolchain.Scope: type parameters only. A const parameter (with or without a default), and any argument that cannot be resolved, keep the uninstantiated type, as before. Defaults are instantiated structurally (no normalization), matching how
resolve_tyalready handstcx.type_ofresults forward.Resolves #4914.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.