fixes #2229
This commit is contained in:
parent
3adcad1b5d
commit
cac259cdfb
3 changed files with 200 additions and 180 deletions
|
|
@ -41,20 +41,28 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
best, alt: var TCandidate,
|
best, alt: var TCandidate,
|
||||||
errors: var CandidateErrors) =
|
errors: var CandidateErrors) =
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
var sym = initOverloadIter(o, c, headSymbol)
|
# thanks to the lazy semchecking for operands, we need to iterate over the
|
||||||
|
# symbol table *before* any call to 'initCandidate' which might invoke
|
||||||
|
# semExpr which might modify the symbol table in cases like
|
||||||
|
# 'init(a, 1, (var b = new(Type2); b))'.
|
||||||
|
var symx = initOverloadIter(o, c, headSymbol)
|
||||||
let symScope = o.lastOverloadScope
|
let symScope = o.lastOverloadScope
|
||||||
|
|
||||||
var z: TCandidate
|
var syms: seq[tuple[a: PSym, b: int]] = @[]
|
||||||
|
while symx != nil:
|
||||||
|
if symx.kind in filter: syms.add((symx, o.lastOverloadScope))
|
||||||
|
symx = nextOverloadIter(o, c, headSymbol)
|
||||||
|
if syms.len == 0: return
|
||||||
|
|
||||||
if sym == nil: return
|
var z: TCandidate
|
||||||
initCandidate(c, best, sym, initialBinding, symScope)
|
initCandidate(c, best, syms[0][0], initialBinding, symScope)
|
||||||
initCandidate(c, alt, sym, initialBinding, symScope)
|
initCandidate(c, alt, syms[0][0], initialBinding, symScope)
|
||||||
best.state = csNoMatch
|
best.state = csNoMatch
|
||||||
|
|
||||||
while sym != nil:
|
for i in 0 .. <syms.len:
|
||||||
if sym.kind in filter:
|
let sym = syms[i][0]
|
||||||
determineType(c, sym)
|
determineType(c, sym)
|
||||||
initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
|
initCandidate(c, z, sym, initialBinding, syms[i][1])
|
||||||
z.calleeSym = sym
|
z.calleeSym = sym
|
||||||
|
|
||||||
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
|
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
|
||||||
|
|
@ -82,7 +90,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
# for i in 1 .. <len(z.call):
|
# for i in 1 .. <len(z.call):
|
||||||
# z.call[i].typ.debug
|
# z.call[i].typ.debug
|
||||||
# quit 1
|
# quit 1
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
|
||||||
|
|
||||||
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||||
|
|
|
||||||
|
|
@ -1244,19 +1244,18 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
case r
|
case r
|
||||||
of isConvertible:
|
of isConvertible:
|
||||||
inc(m.convMatches)
|
inc(m.convMatches)
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
of isIntConv:
|
of isIntConv:
|
||||||
# I'm too lazy to introduce another ``*matches`` field, so we conflate
|
# I'm too lazy to introduce another ``*matches`` field, so we conflate
|
||||||
# ``isIntConv`` and ``isIntLit`` here:
|
# ``isIntConv`` and ``isIntLit`` here:
|
||||||
inc(m.intConvMatches)
|
inc(m.intConvMatches)
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
of isSubtype:
|
of isSubtype:
|
||||||
inc(m.subtypeMatches)
|
inc(m.subtypeMatches)
|
||||||
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
|
||||||
of isSubrange:
|
of isSubrange:
|
||||||
inc(m.subtypeMatches)
|
inc(m.subtypeMatches)
|
||||||
#result = copyTree(arg)
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
|
||||||
of isInferred, isInferredConvertible:
|
of isInferred, isInferredConvertible:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
|
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
|
||||||
|
|
@ -1269,7 +1268,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
result = implicitConv(nkHiddenStdConv, f, result, m, c)
|
result = implicitConv(nkHiddenStdConv, f, result, m, c)
|
||||||
of isGeneric:
|
of isGeneric:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
when true:
|
|
||||||
if arg.typ == nil:
|
if arg.typ == nil:
|
||||||
result = arg
|
result = arg
|
||||||
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
|
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
|
||||||
|
|
@ -1279,31 +1277,22 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
result.typ = getInstantiatedType(c, arg, m, f)
|
result.typ = getInstantiatedType(c, arg, m, f)
|
||||||
else:
|
else:
|
||||||
result = arg
|
result = arg
|
||||||
else:
|
|
||||||
# XXX Why is this ever necessary? arg's type should not be retrofitted
|
|
||||||
# to match formal's type in this way!
|
|
||||||
result = copyTree(arg)
|
|
||||||
result.typ = getInstantiatedType(c, arg, m, f)
|
|
||||||
# BUG: f may not be the right key!
|
|
||||||
if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
|
||||||
# BUGFIX: use ``result.typ`` and not `f` here
|
|
||||||
of isFromIntLit:
|
of isFromIntLit:
|
||||||
# too lazy to introduce another ``*matches`` field, so we conflate
|
# too lazy to introduce another ``*matches`` field, so we conflate
|
||||||
# ``isIntConv`` and ``isIntLit`` here:
|
# ``isIntConv`` and ``isIntLit`` here:
|
||||||
inc(m.intConvMatches, 256)
|
inc(m.intConvMatches, 256)
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
of isEqual:
|
of isEqual:
|
||||||
inc(m.exactMatches)
|
inc(m.exactMatches)
|
||||||
result = copyTree(arg)
|
result = arg
|
||||||
if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
|
||||||
of isNone:
|
of isNone:
|
||||||
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
||||||
if a.kind in {tyProxy, tyUnknown}:
|
if a.kind in {tyProxy, tyUnknown}:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
m.fauxMatch = a.kind
|
m.fauxMatch = a.kind
|
||||||
return copyTree(arg)
|
return arg
|
||||||
result = userConvMatch(c, m, f, a, arg)
|
result = userConvMatch(c, m, f, a, arg)
|
||||||
# check for a base type match, which supports varargs[T] without []
|
# check for a base type match, which supports varargs[T] without []
|
||||||
# constructor in a call:
|
# constructor in a call:
|
||||||
|
|
|
||||||
24
tests/overload/tsymtabchange_during_or.nim
Normal file
24
tests/overload/tsymtabchange_during_or.nim
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
# bug #2229
|
||||||
|
|
||||||
|
type Type1 = object
|
||||||
|
id: int
|
||||||
|
|
||||||
|
type Type2 = object
|
||||||
|
id: int
|
||||||
|
|
||||||
|
proc init(self: var Type1, a: int, b: ref Type2) =
|
||||||
|
echo "1"
|
||||||
|
|
||||||
|
proc init(self: var Type2, a: int) =
|
||||||
|
echo """
|
||||||
|
Works when this proc commented out
|
||||||
|
Otherwise error:
|
||||||
|
test.nim(14, 4) Error: ambiguous call; both test.init(self: var Type1, a: int, b: ref Type2) and test.init(self: var Type1, a: int, b: ref Type2) match for: (Type1, int literal(1), ref Type2)
|
||||||
|
"""
|
||||||
|
|
||||||
|
var a: Type1
|
||||||
|
init(a, 1, (
|
||||||
|
var b = new(Type2);
|
||||||
|
b
|
||||||
|
))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue