Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
14cdb2b
Add DSL for overload resolution tiebreaker rules
T-Gro Jan 18, 2026
eed6225
Implement compareTypeConcreteness function for RFC tiebreakers
T-Gro Jan 18, 2026
bff8e96
Integrate 'more concrete' tiebreaker into better() function
T-Gro Jan 18, 2026
3b3ffef
Add test infrastructure for Tiebreakers conformance tests
T-Gro Jan 18, 2026
e1e2385
Add RFC example tests 1-4 for Most Concrete tiebreaker
T-Gro Jan 18, 2026
73e1ff1
Add multiple type parameter tests (Examples 5-6)
T-Gro Jan 18, 2026
7e4a950
Add real-world scenario tests for Examples 7-9
T-Gro Jan 18, 2026
627020d
Add tests for Examples 10-12: Optional and ParamArray interactions
T-Gro Jan 18, 2026
1b17909
Add extension method tests for RFC FS-XXXX tiebreaker
T-Gro Jan 18, 2026
706b211
Add byref and Span tests for RFC tiebreaker
T-Gro Jan 18, 2026
0f3bf2a
Add constraint and TDC interaction tests
T-Gro Jan 18, 2026
75e3e2b
Add orthogonal test scenarios for tiebreaker feature
T-Gro Jan 18, 2026
1a9c786
Fix overload resolution concreteness tiebreaker to compare formal par…
T-Gro Jan 19, 2026
3924c11
Sprint 2: Verify test expectations - all RFC examples correctly confi…
T-Gro Jan 19, 2026
65ca1e6
Add optional diagnostics FS3575/FS3576 for concreteness tiebreaker
T-Gro Jan 19, 2026
b56c847
Add LanguageFeature.MoreConcreteTiebreaker language feature flag
T-Gro Jan 19, 2026
21ed52d
Update CONTEXT.md and VISION.md for Sprint 4 completion
T-Gro Jan 19, 2026
bc1bde6
Add release notes and format OverloadResolutionRules for Most Concret…
T-Gro Jan 19, 2026
7ac7cc3
docs: Add RFC example coverage mapping to VISION.md
T-Gro Jan 20, 2026
00914c2
Document deferred items for RFC MoreConcrete tiebreaker
T-Gro Jan 20, 2026
4c9ecab
Cleanup PR: Remove workflow artifacts, add design documentation
T-Gro Jan 20, 2026
e65d861
Add compareTypeConcreteness and aggregateComparisons to OverloadResol…
T-Gro Jan 20, 2026
df5c009
Refactor better() and wasConcretenessTiebreaker() to use rule engine
T-Gro Jan 20, 2026
bb24c00
Add explainIncomparableConcreteness API for enhanced FS0041 diagnostics
T-Gro Jan 21, 2026
6ad81e7
Integrate enhanced FS0041 error message for incomparable concreteness
T-Gro Jan 21, 2026
b629c8c
Sprint 2: Verify error info extension complete (already done in Sprin…
T-Gro Jan 21, 2026
bd52440
Sprint 3: Verify enhanced FS0041 message formatting
T-Gro Jan 21, 2026
53ed498
Sprint 4: Verify enhanced FS0041 diagnostic test
T-Gro Jan 21, 2026
37db094
Better explanations
T-Gro Jan 21, 2026
6954e89
Implement constraint count comparison for type variables (RFC Example…
T-Gro Jan 21, 2026
ed35225
Update documentation: Example 15 now implemented
T-Gro Jan 21, 2026
31c511c
Implement FS3576 diagnostic for bypassed generic overloads
T-Gro Jan 21, 2026
96bfbb4
Fix constraint-based overload tests to expect FS0438
T-Gro Jan 21, 2026
42b17ad
Update release note placeholders with clear TBD markers
T-Gro Jan 21, 2026
3e95280
Fix SRTP regression in MoreConcrete tiebreaker rule
T-Gro Jan 21, 2026
a164742
Add RFC quality assessment for FS-XXXX Most Concrete tiebreaker
T-Gro Jan 21, 2026
0fd35ee
Update RFC diagnostic messages to match FSComp.txt exactly
T-Gro Jan 21, 2026
bccd0d9
Verify RFC claims vs implementation
T-Gro Jan 21, 2026
a9c69a0
change rules from strings to ordered and strongly typed enums
T-Gro Jan 22, 2026
ff753d1
doc changes, cleanups
T-Gro Jan 22, 2026
1ec2bab
Add LanguageFeature.OverloadResolutionPriority for F# 10.0
T-Gro Jan 22, 2026
f6d90ee
Add GetOverloadResolutionPriority() method to MethInfo
T-Gro Jan 22, 2026
891e216
Add OverloadResolutionPriorityAttribute tests for RFC FS-XXXX
T-Gro Jan 22, 2026
23139d4
Fix ORP tests to run as baseline tests (not skipped)
T-Gro Jan 22, 2026
9974608
Sprint 1: Add ORP tests with inline C# library
T-Gro Jan 22, 2026
9cb2a22
Sprint 1: Fix ORP tests - remove Skip, document current behavior
T-Gro Jan 22, 2026
07a094c
Sprint 1: Add ORP tests with inline C# library
T-Gro Jan 22, 2026
f02f714
Sprint 2: Implement ORP pre-filter in ConstraintSolver.fs
T-Gro Jan 22, 2026
73da94c
Sprint 2: Add release notes for OverloadResolutionPriority support
T-Gro Jan 22, 2026
497dbb9
Sprint 3: Add 12 ORP edge case tests
T-Gro Jan 22, 2026
652d1e8
Add FS3590 diagnostic for OverloadResolutionPriority
T-Gro Jan 22, 2026
9163e4f
Move MoreConcreteTiebreaker and OverloadResolutionPriority to preview
T-Gro Jan 23, 2026
ccec98e
Add RequiredFeature to TiebreakRule type
T-Gro Jan 23, 2026
9946c65
Add LangVersion Latest Tests for feature gating verification
T-Gro Jan 23, 2026
996b998
Release notes: Document langversion=preview requirement for MoreConcr…
T-Gro Jan 23, 2026
ad34329
cleanup
T-Gro Jan 23, 2026
5777753
code cleanups
T-Gro Jan 23, 2026
f3118b6
Add RFC documents for tiebreaker and OverloadResolutionPriority features
T-Gro Feb 11, 2026
3c724a3
Remove ORP RFC (already exists in fslang-design)
T-Gro Feb 11, 2026
f50b118
Merge branch 'main' into feature/tiebreakers
T-Gro Feb 12, 2026
fa0a8af
Merge branch 'feature/tiebreakers' of https://github.com/dotnet/fshar…
T-Gro Feb 12, 2026
68920e0
fix CI failures
T-Gro Feb 12, 2026
dd7bf92
filterByOverloadResolutionPriority refactor
T-Gro Feb 12, 2026
ed6f351
Fix Desktop test failures: guard net472-incompatible tiebreaker tests…
T-Gro Feb 12, 2026
4c1662d
Fixup #1: Address CODE-QUALITY, PERF, and TEST-CODE-QUALITY verifier …
T-Gro Feb 12, 2026
d8172a9
Fixup #1 (iteration 2): Address remaining CODE-QUALITY, PERF, TEST-CO…
T-Gro Feb 12, 2026
8165d0c
Remove dead code and reduce API surface in OverloadResolutionRules
T-Gro Feb 12, 2026
6bafd8b
Fixup #2: Remove dead FS3590 diagnostic, hide TiebreakRule from API s…
T-Gro Feb 12, 2026
f7e5d15
Fixup #2 (iteration 2): Remove leftover docs, deduplicate tests, para…
T-Gro Feb 12, 2026
41f8807
Fixup #2 (iteration 3): Remove redundant comments, merge duplicate Wa…
T-Gro Feb 12, 2026
25c370b
Fixup #3: Address PERF, TEST-CODE-QUALITY, and NO-LEFTOVERS verifier …
T-Gro Feb 12, 2026
5346f77
Fixup #3 (iteration 2): Cache GetParamDatas and SRTP checks in moreCo…
T-Gro Feb 12, 2026
14b9c3f
Fix release notes: add PR #19277 links and FSharp.Compiler.Service en…
T-Gro Feb 12, 2026
2d4e2f4
Fixup #1: Address PERF, TEST-COVERAGE, HONEST-ASSESSMENT, NO-LEFTOVER…
T-Gro Feb 12, 2026
c3b0e1d
Fixup #2: Commit 4 test upgrades from typecheck to compileAndRun with…
T-Gro Feb 13, 2026
10addb1
Fixup #3: Fix unnamedArgsRule to use flat comparison list for cross-g…
T-Gro Feb 13, 2026
9277273
Fixup #1: Code quality and perf improvements for overload resolution
T-Gro Feb 13, 2026
bac3b04
Fixup #2: Add MoreConcrete, function-type, and tuple-type test coverage
T-Gro Feb 13, 2026
c3967f0
Fixup #2: Deduplicate tests, absorb standalone Fact tests into moreCo…
T-Gro Feb 13, 2026
0a5cc6d
Fixup #1: Perf optimizations and test coverage improvements
T-Gro Feb 13, 2026
fcc6460
Fix PERF and TEST-CODE-QUALITY verifier issues
T-Gro Feb 13, 2026
42754d9
Fix fantomas formatting in OverloadResolutionRules.fs
T-Gro Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/release-notes/.FSharp.Compiler.Service/10.0.300.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

### Added

* Added "Most Concrete" tiebreaker for overload resolution (`--langversion:preview`). ([PR #19277](https://github.com/dotnet/fsharp/pull/19277))
* Added support for `OverloadResolutionPriorityAttribute` in overload resolution (`--langversion:preview`). ([PR #19277](https://github.com/dotnet/fsharp/pull/19277))

### Changed

* Centralized product TFM (Target Framework Moniker) into MSBuild props file `eng/TargetFrameworks.props`. Changing the target framework now only requires editing one file, and it integrates with MSBuild's `--getProperty` for scripts.
Expand Down
2 changes: 2 additions & 0 deletions docs/release-notes/.Language/preview.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
### Added

* Added "Most Concrete" tiebreaker for overload resolution. When multiple method overloads match, the overload with more concrete type parameters wins. Requires `--langversion:preview`. ([PR #19277](https://github.com/dotnet/fsharp/pull/19277))
* Added support for `System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute` (.NET 9). Methods with higher priority values are preferred during overload resolution, matching C# behavior. Requires `--langversion:preview`. ([PR #19277](https://github.com/dotnet/fsharp/pull/19277))
### Fixed

### Changed
237 changes: 66 additions & 171 deletions src/Compiler/Checking/ConstraintSolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ open FSharp.Compiler.TypedTreeBasics
open FSharp.Compiler.TypedTreeOps
open FSharp.Compiler.TypeHierarchy
open FSharp.Compiler.TypeRelations
open FSharp.Compiler.OverloadResolutionRules

#if !NO_TYPEPROVIDERS
open FSharp.Compiler.TypeProviders
Expand Down Expand Up @@ -197,7 +198,8 @@ type OverloadResolutionFailure =
| PossibleCandidates of
methodName: string *
candidates: OverloadInformation list *
cx: TraitConstraintInfo option
cx: TraitConstraintInfo option *
incomparableConcreteness: OverloadResolutionRules.IncomparableConcretenessInfo option

type OverallTy =
/// Each branch of the expression must have the type indicated
Expand Down Expand Up @@ -3469,7 +3471,10 @@ and ResolveOverloading
(methodName = "op_Implicit")

// See what candidates we have based on name and arity
let candidates = calledMethGroup |> List.filter (fun cmeth -> cmeth.IsCandidate(m, ad))
let candidates =
calledMethGroup
|> List.filter (fun cmeth -> cmeth.IsCandidate(m, ad))
|> filterByOverloadResolutionPriority g (fun cm -> cm.Method)

let calledMethOpt, errors, calledMethTrace =
match calledMethGroup, candidates with
Expand Down Expand Up @@ -3577,7 +3582,7 @@ and ResolveOverloading
None, ErrorD err, NoTrace

| [(calledMeth, warns, t, _usesTDC)] ->
Some calledMeth, OkResult (warns, ()), WithTrace t
Some calledMeth, OkResult(warns, ()), WithTrace t

| applicableMeths ->
GetMostApplicableOverload csenv ndeep candidates applicableMeths calledMethGroup reqdRetTyOpt isOpConversion callerArgs methodName cx m
Expand Down Expand Up @@ -3657,177 +3662,25 @@ and FailOverloading csenv calledMethGroup reqdRetTyOpt isOpConversion callerArgs
UnresolvedOverloading (denv, callerArgs, overloadResolutionFailure, m)

and GetMostApplicableOverload csenv ndeep candidates applicableMeths calledMethGroup reqdRetTyOpt isOpConversion callerArgs methodName cx m =
let g = csenv.g
let infoReader = csenv.InfoReader
/// Compare two things by the given predicate.
/// If the predicate returns true for x1 and false for x2, then x1 > x2
/// If the predicate returns false for x1 and true for x2, then x1 < x2
/// Otherwise x1 = x2

// Note: Relies on 'compare' respecting true > false
let compareCond (p: 'T -> 'T -> bool) x1 x2 =
compare (p x1 x2) (p x2 x1)

/// Compare types under the feasibly-subsumes ordering
let compareTypes ty1 ty2 =
(ty1, ty2) ||> compareCond (fun x1 x2 -> TypeFeasiblySubsumesType ndeep csenv.g csenv.amap m x2 CanCoerce x1)

/// Compare arguments under the feasibly-subsumes ordering and the adhoc Func-is-better-than-other-delegates rule
let compareArg (calledArg1: CalledArg) (calledArg2: CalledArg) =
let c = compareTypes calledArg1.CalledArgumentType calledArg2.CalledArgumentType
if c <> 0 then c else

let c =
(calledArg1.CalledArgumentType, calledArg2.CalledArgumentType) ||> compareCond (fun ty1 ty2 ->

// Func<_> is always considered better than any other delegate type
match tryTcrefOfAppTy csenv.g ty1 with
| ValueSome tcref1 when
tcref1.DisplayName = "Func" &&
(match tcref1.PublicPath with Some p -> p.EnclosingPath = [| "System" |] | _ -> false) &&
isDelegateTy g ty1 &&
isDelegateTy g ty2 -> true

// T is always better than inref<T>
| _ when isInByrefTy csenv.g ty2 && typeEquiv csenv.g ty1 (destByrefTy csenv.g ty2) ->
true
let moreConcretEnabled = csenv.g.langVersion.SupportsFeature LanguageFeature.MoreConcreteTiebreaker

// T is always better than Nullable<T> from F# 5.0 onwards
| _ when g.langVersion.SupportsFeature(LanguageFeature.NullableOptionalInterop) &&
isNullableTy csenv.g ty2 &&
typeEquiv csenv.g ty1 (destNullableTy csenv.g ty2) ->
true
let ctx: OverloadResolutionContext =
{ g = csenv.g; amap = csenv.amap; m = m; ndeep = ndeep
paramDataCache = (if moreConcretEnabled then System.Collections.Generic.Dictionary() else Unchecked.defaultof<_>)
srtpCache = (if moreConcretEnabled then System.Collections.Generic.Dictionary() else Unchecked.defaultof<_>) }

| _ -> false)

if c <> 0 then c else
0
let decidingRuleCache =
if moreConcretEnabled then System.Collections.Generic.Dictionary<struct(obj * obj), TiebreakRuleId voption>()
else Unchecked.defaultof<_>

/// Check whether one overload is better than another
let better (candidate: CalledMeth<_>, candidateWarnings, _, usesTDC1) (other: CalledMeth<_>, otherWarnings, _, usesTDC2) =
let candidateWarnCount = List.length candidateWarnings
let otherWarnCount = List.length otherWarnings

// Prefer methods that don't use type-directed conversion
let c = compare (match usesTDC1 with TypeDirectedConversionUsed.No -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.No -> 1 | _ -> 0)
if c <> 0 then c else

// Prefer methods that need less type-directed conversion
let c = compare (match usesTDC1 with TypeDirectedConversionUsed.Yes(_, false, _) -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.Yes(_, false, _) -> 1 | _ -> 0)
if c <> 0 then c else

// Prefer methods that only have nullable type-directed conversions
let c = compare (match usesTDC1 with TypeDirectedConversionUsed.Yes(_, _, true) -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.Yes(_, _, true) -> 1 | _ -> 0)
if c <> 0 then c else

// Prefer methods that don't give "this code is less generic" warnings
// Note: Relies on 'compare' respecting true > false
let c = compare (candidateWarnCount = 0) (otherWarnCount = 0)
if c <> 0 then c else

// Prefer methods that don't use param array arg
// Note: Relies on 'compare' respecting true > false
let c = compare (not candidate.UsesParamArrayConversion) (not other.UsesParamArrayConversion)
if c <> 0 then c else

// Prefer methods with more precise param array arg type
let c =
if candidate.UsesParamArrayConversion && other.UsesParamArrayConversion then
compareTypes (candidate.GetParamArrayElementType()) (other.GetParamArrayElementType())
else
0
if c <> 0 then c else

// Prefer methods that don't use out args
// Note: Relies on 'compare' respecting true > false
let c = compare (not candidate.HasOutArgs) (not other.HasOutArgs)
if c <> 0 then c else

// Prefer methods that don't use optional args
// Note: Relies on 'compare' respecting true > false
let c = compare (not candidate.HasOptionalArgs) (not other.HasOptionalArgs)
if c <> 0 then c else

// check regular unnamed args. The argument counts will only be different if one is using param args
let c =
if candidate.TotalNumUnnamedCalledArgs = other.TotalNumUnnamedCalledArgs then
// For extension members, we also include the object argument type, if any in the comparison set
// This matches C#, where all extension members are treated and resolved as "static" methods calls
let cs =
(if candidate.Method.IsExtensionMember && other.Method.IsExtensionMember then
let objArgTys1 = candidate.CalledObjArgTys(m)
let objArgTys2 = other.CalledObjArgTys(m)
if objArgTys1.Length = objArgTys2.Length then
List.map2 compareTypes objArgTys1 objArgTys2
else
[]
else
[]) @
((candidate.AllUnnamedCalledArgs, other.AllUnnamedCalledArgs) ||> List.map2 compareArg)
// "all args are at least as good, and one argument is actually better"
if cs |> List.forall (fun x -> x >= 0) && cs |> List.exists (fun x -> x > 0) then
1
// "all args are at least as bad, and one argument is actually worse"
elif cs |> List.forall (fun x -> x <= 0) && cs |> List.exists (fun x -> x < 0) then
-1
// "argument lists are incomparable"
else
0
else
0
if c <> 0 then c else

// prefer non-extension methods
let c = compare (not candidate.Method.IsExtensionMember) (not other.Method.IsExtensionMember)
if c <> 0 then c else

// between extension methods, prefer most recently opened
let c =
if candidate.Method.IsExtensionMember && other.Method.IsExtensionMember then
compare candidate.Method.ExtensionMemberPriority other.Method.ExtensionMemberPriority
else
0
if c <> 0 then c else

// Prefer non-generic methods
// Note: Relies on 'compare' respecting true > false
let c = compare candidate.CalledTyArgs.IsEmpty other.CalledTyArgs.IsEmpty
if c <> 0 then c else

// F# 5.0 rule - prior to F# 5.0 named arguments (on the caller side) were not being taken
// into account when comparing overloads. So adding a name to an argument might mean
// overloads could no longer be distinguished. We thus look at *all* arguments (whether
// optional or not) as an additional comparison technique.
let c =
if g.langVersion.SupportsFeature(LanguageFeature.NullableOptionalInterop) then
let cs =
let args1 = candidate.AllCalledArgs |> List.concat
let args2 = other.AllCalledArgs |> List.concat
if args1.Length = args2.Length then
(args1, args2) ||> List.map2 compareArg
else
[]
// "all args are at least as good, and one argument is actually better"
if cs |> List.forall (fun x -> x >= 0) && cs |> List.exists (fun x -> x > 0) then
1
// "all args are at least as bad, and one argument is actually worse"
elif cs |> List.forall (fun x -> x <= 0) && cs |> List.exists (fun x -> x < 0) then
-1
// "argument lists are incomparable"
else
0
else
0
if c <> 0 then c else

// Properties are kept incl. almost-duplicates because of the partial-override possibility.
// E.g. base can have get,set and derived only get => we keep both props around until method resolution time.
// Now is the type to pick the better (more derived) one.
match candidate.AssociatedPropertyInfo,other.AssociatedPropertyInfo,candidate.Method.IsExtensionMember,other.Method.IsExtensionMember with
| Some p1, Some p2, false, false -> compareTypes p1.ApparentEnclosingType p2.ApparentEnclosingType
| _ -> 0


let better (candidate: CalledMeth<_>, candidateWarnings: _ list, _, usesTDC1) (other: CalledMeth<_>, otherWarnings: _ list, _, usesTDC2) =
let struct (result, decidingRule) = findDecidingRule ctx (struct (candidate, usesTDC1, candidateWarnings.Length)) (struct (other, usesTDC2, otherWarnings.Length))
if moreConcretEnabled then
decidingRuleCache[struct(candidate :> obj, other :> obj)] <- decidingRule
result

let bestMethods =
let indexedApplicableMeths = applicableMeths |> List.indexed
indexedApplicableMeths |> List.choose (fun (i, candidate) ->
Expand All @@ -3841,7 +3694,41 @@ and GetMostApplicableOverload csenv ndeep candidates applicableMeths calledMethG

match bestMethods with
| [(calledMeth, warns, t, _)] ->
Some calledMeth, OkResult (warns, ()), WithTrace t
// Only compute concreteness warnings when the MoreConcrete rule was used as deciding factor
let anyMoreConcreteUsed =
moreConcretEnabled &&
decidingRuleCache.Values
|> Seq.exists (fun v -> match v with ValueSome TiebreakRuleId.MoreConcrete -> true | _ -> false)

let allWarns =
if not anyMoreConcreteUsed then
warns
else
let concretenessWarns =
applicableMeths
|> List.choose (fun loser ->
let (loserMeth, _, _, _) = loser

if System.Object.ReferenceEquals(loserMeth, calledMeth) then
None
else
match decidingRuleCache.TryGetValue(struct(calledMeth :> obj, loserMeth :> obj)) with
| true, ValueSome TiebreakRuleId.MoreConcrete ->
Some(calledMeth.Method.DisplayName, loserMeth.Method.DisplayName)
| _ -> None)

match concretenessWarns with
| [] -> warns
| (winnerName, loserName) :: _ ->
let warn3575 =
Error(FSComp.SR.tcMoreConcreteTiebreakerUsed (winnerName, winnerName, loserName), m)
let warn3576List =
concretenessWarns
|> List.map (fun (winner, loser) -> Error(FSComp.SR.tcGenericOverloadBypassed (loser, winner), m))

warn3575 :: warn3576List @ warns

Some calledMeth, OkResult(allWarns, ()), WithTrace t

| bestMethods ->
let methods =
Expand All @@ -3865,7 +3752,15 @@ and GetMostApplicableOverload csenv ndeep candidates applicableMeths calledMethG

let methods = List.concat methods

let err = FailOverloading csenv calledMethGroup reqdRetTyOpt isOpConversion callerArgs (PossibleCandidates(methodName, methods,cx)) m
let incomparableConcretenessInfo =
applicableMeths
|> List.tryPick (fun (meth1, _, _, _) ->
applicableMeths
|> List.tryPick (fun (meth2, _, _, _) ->
if System.Object.ReferenceEquals(meth1, meth2) then None
else explainIncomparableMethodConcreteness ctx meth1 meth2))

let err = FailOverloading csenv calledMethGroup reqdRetTyOpt isOpConversion callerArgs (PossibleCandidates(methodName, methods, cx, incomparableConcretenessInfo)) m
None, ErrorD err, NoTrace

let ResolveOverloadingForCall denv css m methodName callerArgs ad calledMethGroup permitOptArgs reqdRetTy =
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/Checking/ConstraintSolver.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ type OverloadResolutionFailure =
| PossibleCandidates of
methodName: string *
candidates: OverloadInformation list * // methodNames may be different (with operators?), this is refactored from original logic to assemble overload failure message
cx: TraitConstraintInfo option
cx: TraitConstraintInfo option *
incomparableConcreteness: OverloadResolutionRules.IncomparableConcretenessInfo option

/// Represents known information prior to checking an expression or pattern, e.g. it's expected type
type OverallTy =
Expand Down
Loading
Loading