This commit is contained in:
Araq 2019-05-21 01:11:43 +02:00 • committed by Andreas Rumpf
commit 90e882d55b
4 changed files with 55 additions and 53 deletions

View file

@ -1517,6 +1517,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')') internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')')
proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string = proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string =
if n == nil: return "<nil tree>"
var g: TSrcGen var g: TSrcGen
initSrcGen(g, renderFlags, newPartialConfigRef()) initSrcGen(g, renderFlags, newPartialConfigRef())
# do not indent the initial statement list so that # do not indent the initial statement list so that

View file

@ -130,6 +130,9 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old) echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old)
if typeToString(old) == "seq[string]": if typeToString(old) == "seq[string]":
writeStackTrace() writeStackTrace()
if typeToString(key) == "K":
echo "putting to K ", typeToString(val)
writeStackTrace()
idTablePut(c.bindings, key, val.skipIntLit) idTablePut(c.bindings, key, val.skipIntLit)
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
@ -321,33 +324,9 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
add(result, argTypeToString(arg, prefer)) add(result, argTypeToString(arg, prefer))
if i != sonsLen(n) - 1: add(result, ", ") if i != sonsLen(n) - 1: add(result, ", ")
proc typeRelImpl*(c: var TCandidate, f, aOrig: PType, proc typeRel*(c: var TCandidate, f, aOrig: PType,
flags: TTypeRelFlags = {}): TTypeRelation 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 concreteType(c: TCandidate, t: PType): PType = proc concreteType(c: TCandidate, t: PType): PType =
case t.kind case t.kind
of tyNil: of tyNil:
@ -489,7 +468,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
break break
if r.kind == tyObject and ptrs <= 1: result = r 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} assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
var askip = skippedNone var askip = skippedNone
var fskip = skippedNone var fskip = skippedNone
@ -973,7 +952,7 @@ when false:
template skipOwned(a) = template skipOwned(a) =
if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst}) if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst})
proc typeRelImpl(c: var TCandidate, f, aOrig: PType, proc typeRel(c: var TCandidate, f, aOrig: PType,
flags: TTypeRelFlags = {}): TTypeRelation = flags: TTypeRelFlags = {}): TTypeRelation =
# typeRel can be used to establish various relationships between types: # typeRel can be used to establish various relationships between types:
# #
@ -1413,11 +1392,15 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
if roota.base == rootf.base: if roota.base == rootf.base:
let nextFlags = flags + {trNoCovariance} let nextFlags = flags + {trNoCovariance}
var hasCovariance = false var hasCovariance = false
const noBug {.booldefine.} = false
result = when noBug: isGeneric else: isEqual
for i in 1 .. rootf.sonsLen-2: for i in 1 .. rootf.sonsLen-2:
let ff = rootf.sons[i] let ff = rootf.sons[i]
let aa = roota.sons[i] let aa = roota.sons[i]
result = typeRel(c, ff, aa, nextFlags) let res = typeRel(c, ff, aa, nextFlags)
if result notin {isEqual, isGeneric}: if res != isEqual: result = isGeneric
if res notin {isEqual, isGeneric}:
if trNoCovariance notin flags and ff.kind == aa.kind: if trNoCovariance notin flags and ff.kind == aa.kind:
let paramFlags = rootf.base.sons[i-1].flags let paramFlags = rootf.base.sons[i-1].flags
hasCovariance = hasCovariance =
@ -1425,7 +1408,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
if tfWeakCovariant in paramFlags: if tfWeakCovariant in paramFlags:
isCovariantPtr(c, ff, aa) isCovariantPtr(c, ff, aa)
else: else:
ff.kind notin {tyRef, tyPtr} and result == isSubtype ff.kind notin {tyRef, tyPtr} and res == isSubtype
else: else:
tfContravariant in paramFlags and tfContravariant in paramFlags and
typeRel(c, aa, ff) == isSubtype typeRel(c, aa, ff) == isSubtype
@ -1434,7 +1417,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
return isNone return isNone
if prev == nil: put(c, f, a) if prev == nil: put(c, f, a)
result = isGeneric
else: else:
let fKind = rootf.lastSon.kind let fKind = rootf.lastSon.kind
if fKind in {tyAnd, tyOr}: if fKind in {tyAnd, tyOr}:
@ -1480,6 +1462,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
c.calleeSym != nil and c.calleeSym != nil and
c.calleeSym.kind in {skProc, skFunc} and c.call != nil: c.calleeSym.kind in {skProc, skFunc} and c.call != nil:
let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
#echo "inferred ", typeToString(inst), " for ", f
return typeRel(c, inst, a) return typeRel(c, inst, a)
var depth = 0 var depth = 0
@ -1487,16 +1470,26 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
#InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation") #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
# simply no match for now: # simply no match for now:
discard discard
elif x.kind == tyGenericInst and elif x.kind == tyGenericInst and isGenericSubType(c, x, f, depth, f) and
((f.sons[0] == x.sons[0]) or isGenericSubType(c, x, f, depth)) and
(sonsLen(x) - 1 == sonsLen(f)): (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): for i in 1 ..< sonsLen(f):
if x.sons[i].kind == tyGenericParam: if x.sons[i].kind == tyGenericParam:
internalError(c.c.graph.config, "wrong instantiated type!") internalError(c.c.graph.config, "wrong instantiated type!")
elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
# Workaround for regression #4589 # Workaround for regression #4589
if f.sons[i].kind != tyTypeDesc: return if f.sons[i].kind != tyTypeDesc: return
c.inheritancePenalty += depth
result = isGeneric result = isGeneric
else: else:
let genericBody = f.sons[0] let genericBody = f.sons[0]
@ -1664,6 +1657,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
else: else:
result = isNone result = isNone
else: 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: if f.sonsLen > 0 and f.sons[0].kind != tyNone:
let oldInheritancePenalty = c.inheritancePenalty let oldInheritancePenalty = c.inheritancePenalty
result = typeRel(c, f.lastSon, a, flags + {trDontBind}) result = typeRel(c, f.lastSon, a, flags + {trDontBind})
@ -1699,16 +1693,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
elif x.kind == tyGenericParam: elif x.kind == tyGenericParam:
result = isGeneric result = isGeneric
else: 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 result = typeRel(c, x, a) # check if it fits
if result > isGeneric: result = isGeneric if result > isGeneric: result = isGeneric
of tyStatic: of tyStatic:
@ -2075,7 +2059,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
of isEqual: of isEqual:
inc(m.exactMatches) inc(m.exactMatches)
result = arg 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) result = implicitConv(nkHiddenSubConv, f, arg, m, c)
of isNone: of isNone:
# do not do this in ``typeRel`` as it then can't infer T in ``ref T``: # do not do this in ``typeRel`` as it then can't infer T in ``ref T``:

View file

@ -746,7 +746,7 @@ block t5632:
block t7247: block t7247:
type n8 = range[0'i8..127'i8] type n8 = range[0'i8..127'i8]
var tab = initSet[n8]() var tab = initHashSet[n8]()
doAssert tab.contains(8) == false doAssert tab.contains(8) == false

View file

@ -179,3 +179,19 @@ proc varargProc(args: varargs[AbstractObject, convert]): int =
var obj = SomeObject(a: 17) var obj = SomeObject(a: 17)
discard varargProc(obj) 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]"