diff options
author | jcosborn <jcosborn@users.noreply.github.com> | 2020-08-27 05:56:38 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-27 12:56:38 +0200 |
commit | d11933ad998fb0a3eb51bbefbaa53e583aaa3ac1 (patch) | |
tree | 3c6a4f43932120fd5abc8fc5a720efe7e7657b64 /compiler | |
parent | ccccd30cf6b8704c224e42001d0def2b566d5388 (diff) | |
download | Nim-d11933ad998fb0a3eb51bbefbaa53e583aaa3ac1.tar.gz |
fix some issues overloading with generics and inheritance (#15211)
* fix some issues overloading with generics and inheritance * fix passing procs with subtype matches
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/sigmatch.nim | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 1d648c32a..8700d9a47 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -199,6 +199,27 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) = a.baseTypeMatch = b.baseTypeMatch copyIdTable(a.bindings, b.bindings) +proc typeRel*(c: var TCandidate, f, aOrig: PType, + flags: TTypeRelFlags = {}): TTypeRelation + +proc checkGeneric(a, b: TCandidate): int = + let c = a.c + let aa = a.callee + let bb = b.callee + var winner = 0 + for i in 1..<min(aa.len, bb.len): + var ma = newCandidate(c, bb[i]) + let tra = typeRel(ma, bb[i], aa[i], {trDontBind}) + var mb = newCandidate(c, aa[i]) + let trb = typeRel(mb, aa[i], bb[i], {trDontBind}) + if tra == isGeneric and trb == isNone: + if winner == -1: return 0 + winner = 1 + if trb == isGeneric and tra == isNone: + if winner == 1: return 0 + winner = -1 + result = winner + proc sumGeneric(t: PType): int = # count the "genericness" so that Foo[Foo[T]] has the value 3 # and Foo[T] has the value 2 so that we know Foo[Foo[T]] is more @@ -296,6 +317,9 @@ proc cmpCandidates*(a, b: TCandidate): int = # the other way round because of other semantics: result = b.inheritancePenalty - a.inheritancePenalty if result != 0: return + # check for generic subclass relation + result = checkGeneric(a, b) + if result != 0: return # prefer more specialized generic over more general generic: result = complexDisambiguation(a.callee, b.callee) # only as a last resort, consider scoping: @@ -336,9 +360,6 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1; result.add(argTypeToString(arg, prefer)) if i != n.len - 1: result.add(", ") -proc typeRel*(c: var TCandidate, f, aOrig: PType, - flags: TTypeRelFlags = {}): TTypeRelation - proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType = case t.kind of tyTypeDesc: @@ -357,8 +378,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType = # proc sort[T](cmp: proc(a, b: T): int = cmp) if result.kind != tyGenericParam: break of tyGenericInvocation: - result = t - doAssert(false, "cannot resolve type: " & typeToString(t)) + result = nil of tyOwned: # bug #11257: the comparison system.`==`[T: proc](x, y: T) works # better without the 'owned' type: @@ -599,7 +619,8 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation = # if f is metatype. result = typeRel(c, f, a) - if result <= isSubtype or inconsistentVarTypes(f, a): + # v--- is this correct? + if result <= isIntConv or inconsistentVarTypes(f, a): result = isNone #if result == isEqual: @@ -1465,7 +1486,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, if baseType != nil: c.inheritancePenalty += 1 let ret = typeRel(c, f, baseType) - return if ret == isEqual: isSubtype else: ret + return if ret in {isEqual,isGeneric}: isSubtype else: ret result = isNone else: @@ -1496,10 +1517,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, #echo "inferred ", typeToString(inst), " for ", f return typeRel(c, inst, a) - if x.kind == tyGenericInvocation or f[0].kind != tyGenericBody: - #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation") - # simply no match for now: - discard + if x.kind == tyGenericInvocation: + if f[0] == x[0]: + for i in 1..<f.len: + let tr = typeRel(c, f[i], x[i]) + if tr <= isSubtype: return + result = isGeneric elif x.kind == tyGenericInst and f[0] == x[0] and x.len - 1 == f.len: for i in 1..<f.len: |