improve the error messages regarding type mismatches in overloading resolution

This commit is contained in:
Andreas Rumpf 2018-02-04 07:04:50 +01:00
commit 326b7dc556
4 changed files with 74 additions and 11 deletions

View file

@ -106,6 +106,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
errors.safeAdd(CandidateError( errors.safeAdd(CandidateError(
sym: sym, sym: sym,
unmatchedVarParam: int z.mutabilityProblem, unmatchedVarParam: int z.mutabilityProblem,
firstMismatch: z.firstMismatch,
diagnostics: z.diagnostics)) diagnostics: z.diagnostics))
else: else:
# Symbol table has been modified. Restart and pre-calculate all syms # Symbol table has been modified. Restart and pre-calculate all syms
@ -154,7 +155,20 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
else: else:
add(candidates, err.sym.getProcHeader(prefer)) add(candidates, err.sym.getProcHeader(prefer))
add(candidates, "\n") add(candidates, "\n")
if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len: if err.firstMismatch != 0 and n.len > 2:
add(candidates, "first type mismatch at position: " & $err.firstMismatch &
"\nrequired type: ")
if err.firstMismatch < err.sym.typ.len:
candidates.add typeToString(err.sym.typ.sons[err.firstMismatch])
else:
candidates.add "none"
if err.firstMismatch < n.len:
candidates.add "\nbut expression '"
candidates.add renderTree(n[err.firstMismatch])
candidates.add "' is of type: "
candidates.add typeToString(n[err.firstMismatch].typ)
candidates.add "\n"
elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
add(candidates, "for a 'var' type a variable needs to be passed, but '" & add(candidates, "for a 'var' type a variable needs to be passed, but '" &
renderTree(n[err.unmatchedVarParam]) & "' is immutable\n") renderTree(n[err.unmatchedVarParam]) & "' is immutable\n")
for diag in err.diagnostics: for diag in err.diagnostics:
@ -189,7 +203,7 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
while symx != nil: while symx != nil:
if symx.kind in routineKinds: if symx.kind in routineKinds:
errors.add(CandidateError(sym: symx, errors.add(CandidateError(sym: symx,
unmatchedVarParam: 0, unmatchedVarParam: 0, firstMismatch: 0,
diagnostics: nil)) diagnostics: nil))
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
if errors.len == 0: if errors.len == 0:

View file

@ -24,7 +24,7 @@ type
CandidateError* = object CandidateError* = object
sym*: PSym sym*: PSym
unmatchedVarParam*: int unmatchedVarParam*, firstMismatch*: int
diagnostics*: seq[string] diagnostics*: seq[string]
CandidateErrors* = seq[CandidateError] CandidateErrors* = seq[CandidateError]
@ -67,7 +67,9 @@ type
# or when the explain pragma is used. may be # or when the explain pragma is used. may be
# triggered with an idetools command in the # triggered with an idetools command in the
# future. # future.
inheritancePenalty: int # to prefer closest father object type inheritancePenalty: int # to prefer closest father object type
firstMismatch*: int # position of the first type mismatch for
# better error messages
TTypeRelFlag* = enum TTypeRelFlag* = enum
trDontBind trDontBind
@ -2249,6 +2251,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
n.sons[a], nOrig.sons[a]) n.sons[a], nOrig.sons[a])
if arg == nil: if arg == nil:
m.state = csNoMatch m.state = csNoMatch
m.firstMismatch = f
return return
if m.baseTypeMatch: if m.baseTypeMatch:
#assert(container == nil) #assert(container == nil)
@ -2303,6 +2306,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
else: else:
# no default value # no default value
m.state = csNoMatch m.state = csNoMatch
m.firstMismatch = f
break break
else: else:
# use default value: # use default value:

View file

@ -1,25 +1,48 @@
discard """ discard """
errormsg: "type mismatch: got (Bar[system.int])" errormsg: "type mismatch: got (Bar[system.int])"
nimout: ''' nimout: '''
t3330.nim(40, 4) Error: type mismatch: got (Bar[system.int]) t3330.nim(63, 4) Error: type mismatch: got (Bar[system.int])
but expected one of: but expected one of:
proc test(foo: Foo[int]) proc test(foo: Foo[int])
t3330.nim(25, 8) Hint: Non-matching candidates for add(k, string, T) t3330.nim(48, 8) Hint: Non-matching candidates for add(k, string, T)
proc add(x: var string; y: string) proc add(x: var string; y: string)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: char) proc add(x: var string; y: char)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(result: var string; x: int64) proc add(result: var string; x: int64)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(result: var string; x: float) proc add(result: var string; x: float)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add(x: var string; y: cstring) proc add(x: var string; y: cstring)
first type mismatch at position: 1
required type: var string
but expression 'k' is of type: Alias
proc add[T](x: var seq[T]; y: openArray[T]) proc add[T](x: var seq[T]; y: openArray[T])
first type mismatch at position: 1
required type: var seq[T]
but expression 'k' is of type: Alias
proc add[T](x: var seq[T]; y: T) proc add[T](x: var seq[T]; y: T)
first type mismatch at position: 1
required type: var seq[T]
but expression 'k' is of type: Alias
t3330.nim(25, 8) template/generic instantiation from here t3330.nim(48, 8) template/generic instantiation from here
t3330.nim(32, 6) Foo: 'bar.value' cannot be assigned to t3330.nim(55, 6) Foo: 'bar.value' cannot be assigned to
t3330.nim(25, 8) template/generic instantiation from here t3330.nim(48, 8) template/generic instantiation from here
t3330.nim(33, 6) Foo: 'bar.x' cannot be assigned to t3330.nim(56, 6) Foo: 'bar.x' cannot be assigned to
'''
expression: test(bar)'''
""" """
type type
Foo[T] = concept k Foo[T] = concept k
add(k, string, T) add(k, string, T)

View file

@ -0,0 +1,22 @@
discard """
cmd: "nim check $file"
errormsg: "type mismatch: got (int literal(1), int literal(2), int literal(3))"
nimout: '''
but expected one of:
proc main(a, b, c: string)
first type mismatch at position: 1
required type: string
but expression '1' is of type: int literal(1)
expression: main(1, 2, 3)
'''
"""
const
myconst = "abcdefghijklmnopqrstuvwxyz"
proc main(a, b, c: string) {.deprecated: "use foo " & "instead " & myconst.} =
return
main(1, 2, 3)