Skip to content

Conversation

@T-Gro
Copy link
Member

@T-Gro T-Gro commented Jan 23, 2026

Simplify implementation of interface hierarchies with equally named abstract slots: when a derived interface provides a Default Interface Member (DIM) implementation for a base interface slot, F# no longer requires explicit interface declarations for the DIM-covered slot. (RFC FS-1336, Language suggestion #1430,

RFC PR = fsharp/fslang-design#826

T-Gro added 18 commits January 22, 2026 16:55
- Add LanguageFeature.ImplicitDIMCoverage gated to preview version
- Add FSComp.txt feature description
- Create DIMSlotCoverageTests.fs with comprehensive tests
- Implement DIM coverage filtering in MethodOverrides.fs:
  - Add slotHasDIMCoverage helper to check if slot is covered by DIM
  - Filter DIM-covered slots in CheckOverridesAreAllUsedOnce (error checking)
  - Filter DIM-covered slots in slot-to-override matching (IL generation)
- Tests verify:
  - C# interface with DIM allows implicit slot coverage (succeeds)
  - Pure F# interface hierarchy still requires explicit impl (FS0361)
  - Explicit implementation of both interfaces works
Core compiler changes to filter out DIM-covered slots from FS0361 error:

1. Added slotHasDIMCoverage helper function in CheckOverridesAreAllUsedOnce
   - Checks if a RequiredSlot has DIM coverage (IsOptional + HasDefaultInterfaceImplementation)
   - Gated on LanguageFeature.ImplicitDIMCoverage

2. Modified dispatch slot filtering logic (around line 637)
   - Before checking for multi-slot conflict, filter out DIM-covered slots
   - Only emits FS0361 when multiple uncovered slots remain

3. Added slotHasDIMCoverageForIL in CheckImplementationRelationAtEndOfInferenceScope
   - Skip DIM-covered slots during IL MethodImpl generation
   - Prevents 'MethodDefNotFound' errors

4. Updated DIMSlotCoverageTests.fs
   - Simple DIM shadowing test now expects success
   - F# pure interface test still correctly expects FS0361

Test results: 13000+ tests, 0 failures
- Build succeeds with 0 errors
- Simple DIM shadowing works
- F# interfaces without DIMs still error correctly
Sprint 3: Edge cases - diamond inheritance + properties

Tests added:
- Diamond with single DIM: IB provides DIM for IA.M, IC doesn't, ID inherits both
  => Should work because IB provides the DIM coverage
- Diamond with conflicting DIMs: IB and IC both provide different DIMs for IA.M
  => Should error with FS0366 (no most-specific implementation)
- Property with DIM getter: IWritable extends IReadable with DIM for getter
  => Should work because DIM covers the IReadable.Value getter

All 6 DIM tests pass (3 existing + 3 new edge cases)
Sprint 4: Added tests for object expression scenarios with DIM:
- Object expression implementing interface with DIM-covered slot (works)
- Object expression with explicit override of DIM (works with interface decl)
- Class with explicit override of DIM slot (user can override DIM)
- Object expression with diamond and single DIM (works)
- Object expression with pure F# interface hierarchy (still errors)

All 11 DIM Slot Coverage Tests pass. Object expressions use the same
CheckOverridesAreAllUsedOnce code path as classes, with slotHasDIMCoverage
applied at line 650 in MethodOverrides.fs.
Tests added:
- Test 12: Re-abstracted member should require implementation
- Test 13: Re-abstracted member with explicit implementation works
- Test 14: Generic interfaces with different instantiations (partial DIM coverage)
- Test 15: Missing required generic instantiation fails
- Test 16: possiblyNoMostSpecific flag produces correct error (FS3352)

All 16 DIM Slot Coverage tests pass. Build succeeds with 0 errors.
Sprint 6: Language version gating tests

- Test 17: Old language version (9.0) emits FS0361 for DIM-covered slots
- Test 18: Preview language version does NOT emit FS0361
- Test 19: Language version 10.0 also emits FS0361 (feature is previewVersion)
- Test 20: Feature string verification

All tests pass (48 total), DoD verified.
- All ./build.sh -c Release --testcoreclr tests pass
- neg26.bsl and neg36.bsl baselines unchanged (F# interfaces, no DIMs)
- E_MoreThanOneDispatchSlotMatch01.fs unchanged (F# interfaces, no DIMs)
- All 20 DIM Slot Coverage Tests pass
- All 56 DefaultInterfaceMember tests pass
- ILVerify baselines match
- Surface area tests pass
- Formatting check passes
- Add release notes entry to docs/release-notes/.FSharp.Compiler.Service/11.0.0.md
- Update RFC document to mark implementation as complete with PR placeholder
- Formatting check passed
- Full test suite passed (6011 tests)
Extract duplicated slotHasDIMCoverage and slotHasDIMCoverageForIL local
functions into a single HasImplicitDIMCoverage(g) member on RequiredSlot type.

This eliminates code duplication while keeping the DIM coverage check logic
close to the type where it semantically belongs.

The new member checks:
- ImplicitDIMCoverage feature is enabled
- Slot has a default interface implementation
- Slot is optional (not re-abstracted)
- Consolidated 6 C# library definitions into single DIMTestLib with namespaces
- Reduced test count from 20 to 14 by removing redundant tests:
  - Tests 1&18 (identical DIM shadowing with preview)
  - Tests 5&16 (same conflicting DIMs scenario, kept 3352 error version)
  - Tests 17&19&20 (redundant lang version tests, kept 9.0 only)
  - Test 9 (duplicate of Test 3 explicit override)
  - Test 15 (covered by generic interfaces test)
- Reduced file from 550 lines to 197 lines
- Removed verbose comments and section separators
Fixes Sprint 1 DoD:
- Build succeeds with 0 errors
- All 20 existing tests still pass (was 14, now 20)
- C# library count reduced from 5-6 to 1 (better than target of 2)
- No functional behavior change in any test

Restored 6 missing tests:
- Class - explicit override of DIM slot still allowed
- Generic interfaces - missing required instantiation should fail
- possiblyNoMostSpecific - ambiguous DIMs produce specific error message
- Language version preview - DIM-covered slot should NOT emit FS0361
- Language version 10.0 requires explicit implementation
- Feature string - verify feature description displays correctly
- Delete Test 18 (duplicate of Test 1 - both test DIM shadowing with preview)
- Delete Test 16 (duplicate of Test 5 - both test conflicting DIMs with FS3352)
- Merge Tests 17+19+20 into single 'Old language version (pre-feature)' test
- Delete Test 14 (duplicate of Test 3 - both test explicit implementation of IA and IB)

Test count: 20 → 15
Line count: 267 → 208
All unique test coverage preserved.
Created 4 shared helper functions to reduce repetitive test code:
- fsharpImplementingInterface: Wraps module/open/type pattern
- shouldCompileWithDIM: Combines preview + refs + compile + success
- shouldFailWithDIM: For failure cases with error codes
- shouldFailWithoutFeature: For language version gating tests

Applied helpers to 11 of 15 tests. Line count reduced from 209 to 165.
Per-test boilerplate reduced from ~8-10 lines to ~2-3 lines (>50%).
All 43 DIM tests pass.
Add comprehensive module-level documentation explaining:
- 8 testing dimensions (DIM availability, construct type, hierarchy shape,
  DIM conflict, member type, generics, re-abstraction, language version)
- Why 3-level type depth (diamond inheritance) is sufficient for DIM testing
- Test coverage mapping showing which tests cover each dimension

Documentation-only change to improve test maintainability.
Add comprehensive module-level documentation explaining:
- 8 testing dimensions (DIM availability, construct type, hierarchy shape,
  DIM conflict, member type, generics, re-abstraction, language version)
- Why 3-level type depth (diamond inheritance) is sufficient for DIM testing
- Test coverage mapping showing which tests cover each dimension

Documentation-only change to improve test maintainability.
@github-actions
Copy link
Contributor

github-actions bot commented Jan 23, 2026

⚠️ Release notes required, but author opted out

Warning

Author opted out of release notes, check is disabled for this pull request.
cc @dotnet/fsharp-team-msft

@T-Gro T-Gro added the NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes label Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants