mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user