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
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 if not exprStructuralEquivalent(a.ast, b.ast): return
result = true 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 # Searchs for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly # in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil. # 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 nil
result = nextIdentIter(it, scope.symbols) 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: when false:
proc paramsFitBorrow(child, parent: PNode): bool = proc paramsFitBorrow(child, parent: PNode): bool =
var length = sonsLen(child) var length = sonsLen(child)

View file

@ -827,22 +827,6 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
dec(c.p.nestedBlockCounter) dec(c.p.nestedBlockCounter)
proc semGenericParamInInvokation(c: PContext, n: PNode): PType = 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) result = semTypeNode(c, n, nil)
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =

View file

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