This commit is contained in:
Araq 2015-03-05 20:39:25 +01:00
commit cac259cdfb
3 changed files with 200 additions and 180 deletions

View file

@ -41,48 +41,55 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
best, alt: var TCandidate,
errors: var CandidateErrors) =
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
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
initCandidate(c, best, sym, initialBinding, symScope)
initCandidate(c, alt, sym, initialBinding, symScope)
var z: TCandidate
initCandidate(c, best, syms[0][0], initialBinding, symScope)
initCandidate(c, alt, syms[0][0], initialBinding, symScope)
best.state = csNoMatch
while sym != nil:
if sym.kind in filter:
determineType(c, sym)
initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
z.calleeSym = sym
for i in 0 .. <syms.len:
let sym = syms[i][0]
determineType(c, sym)
initCandidate(c, z, sym, initialBinding, syms[i][1])
z.calleeSym = sym
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
# gDebug = true
matches(c, n, orig, z)
if errors != nil:
errors.safeAdd(sym)
if z.errors != nil:
for err in z.errors:
errors.add(err)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind in skIterators: inc(z.exactMatches, 200)
case best.state
of csEmpty, csNoMatch: best = z
of csMatch:
var cmp = cmpCandidates(best, z)
if cmp < 0: best = z # x is better than the best so far
elif cmp == 0: alt = z # x is as good as the best so far
else: discard
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
# gDebug = true
matches(c, n, orig, z)
if errors != nil:
errors.safeAdd(sym)
if z.errors != nil:
for err in z.errors:
errors.add(err)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind in skIterators: inc(z.exactMatches, 200)
case best.state
of csEmpty, csNoMatch: best = z
of csMatch:
var cmp = cmpCandidates(best, z)
if cmp < 0: best = z # x is better than the best so far
elif cmp == 0: alt = z # x is as good as the best so far
else: discard
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
# echo "Matches ", n.info, " ", typeToString(sym.typ)
# debug sym
# writeMatches(z)
# for i in 1 .. <len(z.call):
# z.call[i].typ.debug
# quit 1
sym = nextOverloadIter(o, c, headSymbol)
# echo "Matches ", n.info, " ", typeToString(sym.typ)
# debug sym
# writeMatches(z)
# for i in 1 .. <len(z.call):
# z.call[i].typ.debug
# quit 1
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
# Gives a detailed error message; this is separated from semOverloadedCall,

View file

@ -1244,19 +1244,18 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
case r
of isConvertible:
inc(m.convMatches)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isIntConv:
# I'm too lazy to introduce another ``*matches`` field, so we conflate
# ``isIntConv`` and ``isIntLit`` here:
inc(m.intConvMatches)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isSubtype:
inc(m.subtypeMatches)
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
of isSubrange:
inc(m.subtypeMatches)
#result = copyTree(arg)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isInferred, isInferredConvertible:
inc(m.genericMatches)
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
@ -1269,41 +1268,31 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
result = implicitConv(nkHiddenStdConv, f, result, m, c)
of isGeneric:
inc(m.genericMatches)
when true:
if arg.typ == nil:
result = arg
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
elif 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!
result = copyTree(arg)
if arg.typ == nil:
result = arg
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
elif arg.typ.isEmptyContainer:
result = arg.copyTree
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
else:
result = arg
of isFromIntLit:
# too lazy to introduce another ``*matches`` field, so we conflate
# ``isIntConv`` and ``isIntLit`` here:
inc(m.intConvMatches, 256)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isEqual:
inc(m.exactMatches)
result = copyTree(arg)
result = arg
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:
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
if a.kind in {tyProxy, tyUnknown}:
inc(m.genericMatches)
m.fauxMatch = a.kind
return copyTree(arg)
return arg
result = userConvMatch(c, m, f, a, arg)
# check for a base type match, which supports varargs[T] without []
# constructor in a call:

View 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
))