proc redefinition search based on the type system instead of on sloppy AST matching

This will work the same for procs/templates/macros/etc, having arbitrary mix of implicit
and explicit generics (as long as the symbols are equivalent for the purposes of overload
resolution, they will be detected as redefinitions)

fixes tgeneric
This commit is contained in:
Zahary Karadjov
2013-12-30 02:13:50 +02:00
parent fa3bb8d66b
commit e3f53409f6
3 changed files with 48 additions and 30 deletions

View File

@@ -30,7 +30,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
if not exprStructuralEquivalent(a.ast, b.ast): return
result = true
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
# Searchs for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil.
@@ -63,6 +63,30 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
nil
result = nextIdentIter(it, scope.symbols)
proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
const flags = {ExactGenericParams, ExactTypeDescValues,
ExactConstraints, IgnoreCC}
var it: TIdentIter
result = initIdentIter(it, scope.symbols, fn.name)
while result != nil:
if result.kind in skProcKinds and
sameType(result.typ, fn.typ, flags): return
result = nextIdentIter(it, scope.symbols)
return nil
proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
result = searchForProcNew(c, scope, fn)
when false:
let old = searchForProcOld(c, scope, fn)
if old != result:
echo "Mismatch in searchForProc: ", fn.info
debug fn.typ
debug if result != nil: result.typ else: nil
debug if old != nil: old.typ else: nil
when false:
proc paramsFitBorrow(child, parent: PNode): bool =
var length = sonsLen(child)

View File

@@ -827,22 +827,6 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
dec(c.p.nestedBlockCounter)
proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
# XXX hack 1022 for generics ... would have been nice if the compiler had
# been designed with them in mind from start ...
when false:
if n.kind == nkSym:
# for generics we need to lookup the type var again:
var s = searchInScopes(c, n.sym.name)
if s != nil:
if s.kind == skType and s.typ != nil:
var t = n.sym.typ
echo "came here"
return t
else:
echo "s is crap:"
debug(s)
else:
echo "s is nil!!!!"
result = semTypeNode(c, n, nil)
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =

View File

@@ -606,8 +606,10 @@ type
TTypeCmpFlag* = enum
IgnoreTupleFields
IgnoreCC
ExactTypeDescValues
ExactGenericParams
ExactConstraints
AllowCommonBase
TTypeCmpFlags* = set[TTypeCmpFlag]
@@ -637,15 +639,17 @@ proc sameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
if a == nil or b == nil: result = false
else: result = sameTypeAux(a, b, c)
proc sameType*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
var c = initSameTypeClosure()
c.flags = flags
result = sameTypeAux(a, b, c)
proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
if a == b:
result = true
else:
else:
if a == nil or b == nil: result = false
else:
var c = initSameTypeClosure()
c.flags = flags
result = sameTypeAux(a, b, c)
else: result = sameType(a, b, flags)
proc equalParam(a, b: PSym): TParamsEquality =
if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
@@ -661,7 +665,15 @@ proc equalParam(a, b: PSym): TParamsEquality =
result = paramsIncompatible
else:
result = paramsNotEqual
proc sameConstraints(a, b: PNode): bool =
internalAssert a.len == b.len
for i in 1 .. <a.len:
if not exprStructuralEquivalent(a[i].sym.constraint,
b[i].sym.constraint):
return false
return true
proc equalParams(a, b: PNode): TParamsEquality =
result = paramsEqual
var length = sonsLen(a)
@@ -860,8 +872,9 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
else:
result = sameFlags(a, b)
of tyGenericParam:
result = if ExactGenericParams in c.flags: a.id == b.id
else: sameChildrenAux(a, b, c) and sameFlags(a, b)
result = sameChildrenAux(a, b, c) and sameFlags(a, b)
if result and ExactGenericParams in c.flags:
result = a.sym.position == b.sym.position
of tyGenericInvokation, tyGenericBody, tySequence,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
@@ -869,7 +882,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
cycleCheck()
result = sameChildrenAux(a, b, c) and sameFlags(a, b)
if result and a.kind == tyProc:
result = a.callConv == b.callConv
result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n))
of tyRange:
cycleCheck()
result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
@@ -877,10 +891,6 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
sameValue(a.n.sons[1], b.n.sons[1])
of tyNone: result = false
proc sameType*(x, y: PType): bool =
var c = initSameTypeClosure()
result = sameTypeAux(x, y, c)
proc sameBackendType*(x, y: PType): bool =
var c = initSameTypeClosure()
c.flags.incl IgnoreTupleFields