decent error message for 'var T' problems

This commit is contained in:
Andreas Rumpf 2016-07-14 23:20:38 +02:00
commit 995727ffd0
2 changed files with 16 additions and 15 deletions

View file

@ -69,7 +69,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
# gDebug = true # gDebug = true
matches(c, n, orig, z) matches(c, n, orig, z)
if errors != nil: if errors != nil:
errors.safeAdd(sym) errors.safeAdd((sym, int z.mutabilityProblem))
if z.errors != nil: if z.errors != nil:
for err in z.errors: for err in z.errors:
errors.add(err) errors.add(err)
@ -111,7 +111,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
let proto = describeArgs(c, n, 1, preferName) let proto = describeArgs(c, n, 1, preferName)
var prefer = preferName var prefer = preferName
for err in errors: for err, mut in items(errors):
var errProto = "" var errProto = ""
let n = err.typ.n let n = err.typ.n
for i in countup(1, n.len - 1): for i in countup(1, n.len - 1):
@ -123,18 +123,21 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
if errProto == proto: if errProto == proto:
prefer = preferModuleInfo prefer = preferModuleInfo
break break
# now use the information stored in 'prefer' to produce a nice error message: # now use the information stored in 'prefer' to produce a nice error message:
var result = msgKindToString(errTypeMismatch) var result = msgKindToString(errTypeMismatch)
add(result, describeArgs(c, n, 1, prefer)) add(result, describeArgs(c, n, 1, prefer))
add(result, ')') add(result, ')')
var candidates = "" var candidates = ""
for err in errors: for err, mut in items(errors):
if err.kind in routineKinds and err.ast != nil: if err.kind in routineKinds and err.ast != nil:
add(candidates, renderTree(err.ast, add(candidates, renderTree(err.ast,
{renderNoBody, renderNoComments,renderNoPragmas})) {renderNoBody, renderNoComments,renderNoPragmas}))
else: else:
add(candidates, err.getProcHeader(prefer)) add(candidates, err.getProcHeader(prefer))
add(candidates, "\n") add(candidates, "\n")
if mut != 0 and mut < n.len:
add(candidates, "for a 'var' type a variable needs to be passed, but '" & renderTree(n[mut]) & "' is immutable\n")
if candidates != "": if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates) add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
if c.compilesContextId > 0 and optReportConceptFailures in gGlobalOptions: if c.compilesContextId > 0 and optReportConceptFailures in gGlobalOptions:
@ -158,8 +161,6 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
template pickBest(headSymbol) = template pickBest(headSymbol) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding, pickBestCandidate(c, headSymbol, n, orig, initialBinding,
filter, result, alt, errors) filter, result, alt, errors)
pickBest(f) pickBest(f)
let overloadsState = result.state let overloadsState = result.state
@ -230,7 +231,6 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
#notFoundError(c, n, errors) #notFoundError(c, n, errors)
return return
if alt.state == csMatch and cmpCandidates(result, alt) == 0 and if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
not sameMethodDispatcher(result.calleeSym, alt.calleeSym): not sameMethodDispatcher(result.calleeSym, alt.calleeSym):
internalAssert result.state == csMatch internalAssert result.state == csMatch
@ -299,8 +299,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
var finalCallee = x.calleeSym var finalCallee = x.calleeSym
markUsed(n.sons[0].info, finalCallee) markUsed(n.sons[0].info, finalCallee)
styleCheckUse(n.sons[0].info, finalCallee) styleCheckUse(n.sons[0].info, finalCallee)
if finalCallee.ast == nil: assert finalCallee.ast != nil
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if x.hasFauxMatch: if x.hasFauxMatch:
result = x.call result = x.call
result.sons[0] = newSymNode(finalCallee, result.sons[0].info) result.sons[0] = newSymNode(finalCallee, result.sons[0].info)

View file

@ -22,7 +22,7 @@ type
TCandidateState* = enum TCandidateState* = enum
csEmpty, csMatch, csNoMatch csEmpty, csMatch, csNoMatch
CandidateErrors* = seq[PSym] CandidateErrors* = seq[(PSym,int)]
TCandidate* = object TCandidate* = object
c*: PContext c*: PContext
exactMatches*: int # also misused to prefer iters over procs exactMatches*: int # also misused to prefer iters over procs
@ -49,6 +49,7 @@ type
# a distrinct type # a distrinct type
typedescMatched*: bool typedescMatched*: bool
isNoCall*: bool # misused for generic type instantiations C[T] isNoCall*: bool # misused for generic type instantiations C[T]
mutabilityProblem*: uint8 # tyVar mismatch
inheritancePenalty: int # to prefer closest father object type inheritancePenalty: int # to prefer closest father object type
errors*: CandidateErrors # additional clarifications to be displayed to the errors*: CandidateErrors # additional clarifications to be displayed to the
# user if overload resolution fails # user if overload resolution fails
@ -1579,6 +1580,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
if formal.typ.kind == tyVar: if formal.typ.kind == tyVar:
if not n.isLValue: if not n.isLValue:
m.state = csNoMatch m.state = csNoMatch
m.mutabilityProblem = uint8(f-1)
return return
var var