Restore the compilation of linalg by tweaking the complex disambiguation rules

This commit is a potentially breaking change, but the problem was that
linalg was relying on a previous bug in the compiler, which was fixed
in the concepts branch.

With the old disambiguation rules, generic procs like:

proc \`==\`[T](lhs, rhs: T)

and

proc \`==\`(lhs, rhs: Matrix32|Matrix64)

.. were considered equal, even though it's obvious that the second one
should be preferred. We never noticed this, because there was a bug in
sigmatch incorrectly counting one of the params of the second proc as
a non-generic match, thus giving it an edge.

This commit gives some preference to tyOr and tyAnd during the complex
disambiguation, which may affect overload resolution in other cases.

I see this only as a temporary solution. With my upcoming work on
concept refinement, I plan to provide an experimental implementation
of alaternative C++-like rules for determining which proc is more specific.
We can then discuss our strategy for dealing with such a breaking change.
This commit is contained in:
Zahary Karadjov
2017-04-16 16:11:45 +03:00
parent 2da4a4fbe3
commit 13701c0957

View File

@@ -177,6 +177,13 @@ proc sumGeneric(t: PType): int =
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody:
t = t.lastSon
inc result
of tyOr:
var maxBranch = 0
for branch in t.sons:
let branchSum = branch.sumGeneric
if branchSum > maxBranch: maxBranch = branchSum
inc result, maxBranch + 1
break
of tyVar:
t = t.sons[0]
inc result
@@ -185,8 +192,8 @@ proc sumGeneric(t: PType): int =
t = t.lastSon
if t.kind == tyEmpty: break
inc result
of tyGenericInvocation, tyTuple, tyProc:
result += ord(t.kind == tyGenericInvocation)
of tyGenericInvocation, tyTuple, tyProc, tyAnd:
result += ord(t.kind in {tyGenericInvocation, tyAnd})
for i in 0 .. <t.len:
if t.sons[i] != nil:
result += t.sons[i].sumGeneric
@@ -228,6 +235,15 @@ proc complexDisambiguation(a, b: PType): int =
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
result = x - y
proc writeMatches*(c: TCandidate) =
echo "Candidate '", c.calleeSym.name.s, "' at ", c.calleeSym.info
echo " exact matches: ", c.exactMatches
echo " generic matches: ", c.genericMatches
echo " subtype matches: ", c.subtypeMatches
echo " intconv matches: ", c.intConvMatches
echo " conv matches: ", c.convMatches
echo " inheritance: ", c.inheritancePenalty
proc cmpCandidates*(a, b: TCandidate): int =
result = a.exactMatches - b.exactMatches
if result != 0: return
@@ -248,14 +264,6 @@ proc cmpCandidates*(a, b: TCandidate): int =
if result != 0: return
result = a.calleeScope - b.calleeScope
proc writeMatches*(c: TCandidate) =
writeLine(stdout, "exact matches: " & $c.exactMatches)
writeLine(stdout, "generic matches: " & $c.genericMatches)
writeLine(stdout, "subtype matches: " & $c.subtypeMatches)
writeLine(stdout, "intconv matches: " & $c.intConvMatches)
writeLine(stdout, "conv matches: " & $c.convMatches)
writeLine(stdout, "inheritance: " & $c.inheritancePenalty)
proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
if arg.kind in nkSymChoices:
result = typeToString(arg[0].typ, prefer)