diff options
author | Araq <rumpf_a@web.de> | 2019-05-21 01:11:43 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-22 07:41:16 +0200 |
commit | 90e882d55b69020b52efd891c935e942d10829ee (patch) | |
tree | 7539e199ada2ef5900d98d4cdd4a8aa167bb89a2 | |
parent | 11fca968b2cb3714b55141acf39bd1691d7ae8eb (diff) | |
download | Nim-90e882d55b69020b52efd891c935e942d10829ee.tar.gz |
fixes #11239
-rw-r--r-- | compiler/renderer.nim | 1 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 89 | ||||
-rw-r--r-- | tests/generics/tgenerics_issues.nim | 2 | ||||
-rw-r--r-- | tests/overload/toverload_issues.nim | 16 |
4 files changed, 55 insertions, 53 deletions
diff --git a/compiler/renderer.nim b/compiler/renderer.nim index b51bd3162..8d3f234b7 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -1517,6 +1517,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')') proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string = + if n == nil: return "<nil tree>" var g: TSrcGen initSrcGen(g, renderFlags, newPartialConfigRef()) # do not indent the initial statement list so that diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 978ee37fa..541ef63da 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -130,6 +130,9 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} = echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old) if typeToString(old) == "seq[string]": writeStackTrace() + if typeToString(key) == "K": + echo "putting to K ", typeToString(val) + writeStackTrace() idTablePut(c.bindings, key, val.skipIntLit) proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, @@ -321,32 +324,8 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1; add(result, argTypeToString(arg, prefer)) if i != sonsLen(n) - 1: add(result, ", ") -proc typeRelImpl*(c: var TCandidate, f, aOrig: PType, - flags: TTypeRelFlags = {}): TTypeRelation - -const traceTypeRel = false - -when traceTypeRel: - var nextTypeRel = 0 - -template typeRel*(c: var TCandidate, f, aOrig: PType, - flags: TTypeRelFlags = {}): TTypeRelation = - when traceTypeRel: - var enteringAt = nextTypeRel - if mdbg: - inc nextTypeRel - echo "----- TYPE REL ", enteringAt - debug f - debug aOrig - # writeStackTrace() - - let r = typeRelImpl(c, f, aOrig, flags) - - when traceTypeRel: - if enteringAt != nextTypeRel: - echo "----- TYPE REL ", enteringAt, " RESULT: ", r - - r +proc typeRel*(c: var TCandidate, f, aOrig: PType, + flags: TTypeRelFlags = {}): TTypeRelation proc concreteType(c: TCandidate, t: PType): PType = case t.kind @@ -441,10 +420,10 @@ proc handleFloatRange(f, a: PType): TTypeRelation = proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) = if fGenericOrigin != nil and last.kind == tyGenericInst and last.len-1 == fGenericOrigin.len: - for i in 1 ..< sonsLen(fGenericOrigin): - let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i])) - if x == nil: - put(c, fGenericOrigin.sons[i], last.sons[i]) + for i in 1 ..< sonsLen(fGenericOrigin): + let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i])) + if x == nil: + put(c, fGenericOrigin.sons[i], last.sons[i]) proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int = var t = a @@ -489,7 +468,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType = break if r.kind == tyObject and ptrs <= 1: result = r -proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType = nil): bool = +proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType): bool = assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody} var askip = skippedNone var fskip = skippedNone @@ -973,8 +952,8 @@ when false: template skipOwned(a) = if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst}) -proc typeRelImpl(c: var TCandidate, f, aOrig: PType, - flags: TTypeRelFlags = {}): TTypeRelation = +proc typeRel(c: var TCandidate, f, aOrig: PType, + flags: TTypeRelFlags = {}): TTypeRelation = # typeRel can be used to establish various relationships between types: # # 1) When used with concrete types, it will check for type equivalence @@ -1021,7 +1000,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, case f.kind of tyGenericParam: - var prev = PType(idTableGet(c.bindings, f)) + var prev = PType(idTableGet(c.bindings, f)) if prev != nil: candidate = prev of tyFromExpr: let computedType = tryResolvingStaticExpr(c, f.n).typ @@ -1413,11 +1392,15 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, if roota.base == rootf.base: let nextFlags = flags + {trNoCovariance} var hasCovariance = false + const noBug {.booldefine.} = false + result = when noBug: isGeneric else: isEqual + for i in 1 .. rootf.sonsLen-2: let ff = rootf.sons[i] let aa = roota.sons[i] - result = typeRel(c, ff, aa, nextFlags) - if result notin {isEqual, isGeneric}: + let res = typeRel(c, ff, aa, nextFlags) + if res != isEqual: result = isGeneric + if res notin {isEqual, isGeneric}: if trNoCovariance notin flags and ff.kind == aa.kind: let paramFlags = rootf.base.sons[i-1].flags hasCovariance = @@ -1425,7 +1408,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, if tfWeakCovariant in paramFlags: isCovariantPtr(c, ff, aa) else: - ff.kind notin {tyRef, tyPtr} and result == isSubtype + ff.kind notin {tyRef, tyPtr} and res == isSubtype else: tfContravariant in paramFlags and typeRel(c, aa, ff) == isSubtype @@ -1434,7 +1417,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, return isNone if prev == nil: put(c, f, a) - result = isGeneric else: let fKind = rootf.lastSon.kind if fKind in {tyAnd, tyOr}: @@ -1480,6 +1462,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, c.calleeSym != nil and c.calleeSym.kind in {skProc, skFunc} and c.call != nil: let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) + #echo "inferred ", typeToString(inst), " for ", f return typeRel(c, inst, a) var depth = 0 @@ -1487,16 +1470,26 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation") # simply no match for now: discard - elif x.kind == tyGenericInst and - ((f.sons[0] == x.sons[0]) or isGenericSubType(c, x, f, depth)) and + elif x.kind == tyGenericInst and isGenericSubType(c, x, f, depth, f) and (sonsLen(x) - 1 == sonsLen(f)): + # do not recurse here in order to not K bind twice for this code: + # + # type + # BaseFruit[T] = object of RootObj + # Banana[T] = object of BaseFruit[uint32] # Concrete type here, not T! + # proc setColor[K](self: var BaseFruit[K]) + # var x: Banana[float64] + # x.setColor() + c.inheritancePenalty += depth + result = isGeneric + elif x.kind == tyGenericInst and f.sons[0] == x.sons[0] and + sonsLen(x) - 1 == sonsLen(f): for i in 1 ..< sonsLen(f): if x.sons[i].kind == tyGenericParam: internalError(c.c.graph.config, "wrong instantiated type!") elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: # Workaround for regression #4589 if f.sons[i].kind != tyTypeDesc: return - c.inheritancePenalty += depth result = isGeneric else: let genericBody = f.sons[0] @@ -1664,6 +1657,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, else: result = isNone else: + # check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)' if f.sonsLen > 0 and f.sons[0].kind != tyNone: let oldInheritancePenalty = c.inheritancePenalty result = typeRel(c, f.lastSon, a, flags + {trDontBind}) @@ -1699,16 +1693,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, elif x.kind == tyGenericParam: result = isGeneric else: - # Special type binding rule for numeric types. - # See section "Generic type inference for numeric types" of the - # manual for further details: - when false: - let rebinding = maxNumericType(x.skipTypes({tyRange}), a) - if rebinding != nil: - put(c, f, rebinding) - result = isGeneric - else: - discard result = typeRel(c, x, a) # check if it fits if result > isGeneric: result = isGeneric of tyStatic: @@ -2075,7 +2059,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, of isEqual: inc(m.exactMatches) result = arg - if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}: + if skipTypes(f, abstractVar-{tyTypeDesc}).kind == tyTuple or + (arg.typ != nil and skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple): result = implicitConv(nkHiddenSubConv, f, arg, m, c) of isNone: # do not do this in ``typeRel`` as it then can't infer T in ``ref T``: diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim index a1d464b97..3d5d65c75 100644 --- a/tests/generics/tgenerics_issues.nim +++ b/tests/generics/tgenerics_issues.nim @@ -746,7 +746,7 @@ block t5632: block t7247: type n8 = range[0'i8..127'i8] - var tab = initSet[n8]() + var tab = initHashSet[n8]() doAssert tab.contains(8) == false diff --git a/tests/overload/toverload_issues.nim b/tests/overload/toverload_issues.nim index fe1603a44..5db7b54fa 100644 --- a/tests/overload/toverload_issues.nim +++ b/tests/overload/toverload_issues.nim @@ -179,3 +179,19 @@ proc varargProc(args: varargs[AbstractObject, convert]): int = var obj = SomeObject(a: 17) discard varargProc(obj) + + + +# bug #11239 + +type MySeq*[T] = object + +proc foo(a: seq[int]): string = "foo: seq[int]" +proc foo[T](a: seq[T]): string = "foo: seq[T]" +proc foo(a: MySeq[int]): string = "foo: MySeq[int]" +proc foo[T](a: MySeq[T]): string = "foo: MySeq[T]" + +doAssert foo(@[1,2,3]) == "foo: seq[int]" +doAssert foo(@["WER"]) == "foo: seq[T]" +doAssert foo(MySeq[int]()) == "foo: MySeq[int]" +doAssert foo(MySeq[string]()) == "foo: MySeq[T]" |