Fix #19596: unit-parameter member conformance with signature#19615
Fix #19596: unit-parameter member conformance with signature#19615T-Gro wants to merge 6 commits into
Conversation
e8e6743 to
e4bc6ae
Compare
4b5e839 to
3608686
Compare
Merge conflicts resolved in commit
Build verified: 0 warnings/errors. |
3608686 to
8923561
Compare
Merge conflicts resolved in commit
Build: 0 warnings/errors. |
T-Gro
left a comment
There was a problem hiding this comment.
Review: Fix #19596 — unit-parameter member conformance
The core fix in SignatureConformance.fs is sound for the overloaded case. The three-part approach — relaxed arg group arity in checkValInfo, min-guarded List.take, and type-equivalence fallback matching — correctly handles the M(()) vs M: unit → unit discrepancy.
Key concern: single-val path gap (@abonie's comment is correct)
The [av],[fv] path at line 689 still uses valuesPartiallyMatch which requires strict TotalArgCount equality. A non-overloaded member M(()) with sig member M: unit → unit will fail here (TotalArgCount 1 vs 2). The relaxed matching only applies to the multi-val _ -> branch.
This means the fix only works when M has overloads (so it enters the _ -> branch). A solo member M(()) = () paired with sig member M: unit → unit will still fail. This should be addressed — either with a type-equivalence fallback in the [av],[fv] path, or tracked as a follow-up issue.
Minor observations
-
NicePrint.fs change is a separate concern — the SRTP constraint dedup in
layoutNonMemberValis unrelated to unit-param conformance. Consider splitting into its own commit for clearer attribution. -
FS0503 test documents a behavioral asymmetry —
d.M()fails when impl isM(())but succeeds when impl isM(), despite both having sigmember M: unit → unit. The sig should define the API contract, so consumers shouldn’t see impl-level calling convention differences. This may be a pre-existing design constraint, but worth documenting in a comment or tracking separately. -
Test coverage for the overloaded path is excellent — both directions, consumer access, IL verification, and negative cases are covered.
SignatureConformance.fs: when matching overloaded members, add relaxed fallback for unmatched pairs using type equivalence. This handles member M(()) (argInfos=[[]]) vs sig member M: unit->unit (argInfos=[[unit_arg]]) where types are equivalent but TotalArgCount differs. Also relax checkValInfo arg group check: empty impl group is compatible with singleton sig group for unit-parameter members. Tests: roundtrip test, handwritten sig+impl+consumer (both directions). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ures Proves the conformance relaxation is safe at IL level — both member M(()) and member M() compile to '.method public hidebysig instance int32 M()', confirming the representation difference is compile-time only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Consumer cannot call d.M() when impl is M(()) with overloads (FS0503 expected) - Consumer can call d.M() when impl is M() with sig M: unit -> unit Covers both directions of sig↔impl conformance with consumer validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add type-equivalence fallback in [av],[fv] single-val path so non-overloaded member M(()) conforms to sig member M: unit -> unit (addresses abonie + T-Gro feedback) - Use idiomatic implGroup.IsEmpty && sigGroup.Length = 1 (T-Gro nit) - Add test for non-overloaded unit-param member conformance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
e1bf547 to
c94466e
Compare
…ixes - Fix release notes PR number: #19609 -> #19615 - Prevent double-consume of impl vals in relaxed matching by using List.fold to track remaining available avs - Use obj.ReferenceEquals instead of System.Object.ReferenceEquals for consistency with codebase style - Add trailing newline to TypeTests.fs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
❗ Release notes required
|
…ixes - Fix release notes PR number: #19609 -> #19615 - Prevent double-consume of impl vals in relaxed matching by using List.fold to track remaining available avs - Use obj.ReferenceEquals instead of System.Object.ReferenceEquals for consistency with codebase style - Add trailing newline to TypeTests.fs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0f7bbfe to
7ac3c70
Compare
Fixes #19596
Stacked on #19609.
member M(())produces ValReprInfo[[]](empty arg group), but sigmember M: unit -> unitparses to[[unit_arg]]. Both produce identical IL (.method instance void M()). The conformance checker rejected them becauseTotalArgCountdiffers (1 vs 2 includingthis).Fix: Relax signature conformance matching for the unit-parameter case:
checkValInfo: allow empty impl group[]to match singleton sig group[_]typeAEquivAux EraseAll+TotalArgCountdiff=1 guard[av],[fv]path: same relaxationSafety:
verifyILContainstestEraseAllmatches the erasure mode used byvalLinkageAEquivin the primary matching pathTotalArgCountdiff=1 guard restricts to unit-param case onlyE_StructConstructor01conformance test still correctly fails