mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
fixes #2216
This commit is contained in:
@@ -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.:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!
|
||||
|
||||
27
tests/notnil/tnotnil_in_generic.nim
Normal file
27
tests/notnil/tnotnil_in_generic.nim
Normal 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()
|
||||
Reference in New Issue
Block a user