This commit is contained in:
Araq
2015-02-26 00:11:21 +01:00
parent 5d9663e4de
commit 9053799bf5
5 changed files with 47 additions and 16 deletions

View File

@@ -95,15 +95,6 @@ proc inferWithMetatype(c: PContext, formal: PType,
var commonTypeBegin = PType(kind: tyExpr)
proc isEmptyContainer(t: PType): bool =
case t.kind
of tyExpr, tyNil: result = true
of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
of tySet, tySequence, tyOpenArray, tyVarargs:
result = t.sons[0].kind == tyEmpty
of tyGenericInst: result = isEmptyContainer(t.lastSon)
else: result = false
proc commonType*(x, y: PType): PType =
# new type relation that is used for array constructors,
# if expressions, etc.:

View File

@@ -1145,7 +1145,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
case n.len
of 3:
result = semTypeNode(c, n.sons[1], prev)
if result.kind in NilableTypes and n.sons[2].kind == nkNilLit:
if result.skipTypes({tyGenericInst}).kind in NilableTypes+GenericTypes and
n.sons[2].kind == nkNilLit:
result = freshType(result, prev)
result.flags.incl(tfNotNil)
else:

View File

@@ -236,7 +236,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
# tyGenericInvocation[A, tyGenericInvocation[A, B]]
# is difficult to handle:
# is difficult to handle:
var body = t.sons[0]
if body.kind != tyGenericBody: internalError(cl.info, "no generic body")
var header: PType = t
@@ -245,7 +245,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
result = PType(idTableGet(cl.localCache, t))
else:
result = searchInstTypes(t)
if result != nil: return
if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
for i in countup(1, sonsLen(t) - 1):
var x = t.sons[i]
if x.kind == tyGenericParam:
@@ -260,10 +260,10 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
if header != t:
# search again after first pass:
result = searchInstTypes(header)
if result != nil: return
if result != nil and eqTypeFlags*result.flags == eqTypeFlags*t.flags: return
else:
header = instCopyType(cl, t)
result = newType(tyGenericInst, t.sons[0].owner)
result.flags = header.flags
# be careful not to propagate unnecessary flags here (don't use rawAddSon)

View File

@@ -1165,6 +1165,15 @@ proc isInlineIterator*(t: PType): bool =
result = t.kind == tyIter or
(t.kind == tyBuiltInTypeClass and t.base.kind == tyIter)
proc isEmptyContainer*(t: PType): bool =
case t.kind
of tyExpr, tyNil: result = true
of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
of tySet, tySequence, tyOpenArray, tyVarargs:
result = t.sons[0].kind == tyEmpty
of tyGenericInst: result = isEmptyContainer(t.lastSon)
else: result = false
proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
argSemantized, argOrig: PNode): PNode =
var
@@ -1260,11 +1269,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
result = implicitConv(nkHiddenStdConv, f, result, m, c)
of isGeneric:
inc(m.genericMatches)
when false:
when true:
if skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
else:
elif arg.typ != nil and arg.typ.isEmptyContainer:
result = arg.copyTree
result.typ = getInstantiatedType(c, arg, m, f)
else:
result = arg
else:
# XXX Why is this ever necessary? arg's type should not be retrofitted
# to match formal's type in this way!

View File

@@ -0,0 +1,27 @@
discard """
errormsg: "cannot prove 'x' is not nil"
"""
# bug #2216
type
A[T] = ref object
x: int
ud: T
proc good[T](p: A[T]) =
discard
proc bad[T](p: A[T] not nil) =
discard
proc go() =
let s = A[int](x: 1)
good(s)
bad(s)
var x: A[int]
bad(x)
go()