proper error reporting for concepts and the introduction of the {.explain.} pragma

This commit is contained in:
Zahary Karadjov 2016-08-14 02:45:29 +03:00
commit 74a80988d9
13 changed files with 302 additions and 139 deletions

View file

@ -22,7 +22,13 @@ type
TCandidateState* = enum
csEmpty, csMatch, csNoMatch
CandidateErrors* = seq[(PSym,int)]
CandidateError = tuple
sym: PSym
unmatchedVarParam: int
diagnostics: seq[string]
CandidateErrors* = seq[CandidateError]
TCandidate* = object
c*: PContext
exactMatches*: int # also misused to prefer iters over procs
@ -53,11 +59,16 @@ type
# matching. they will be reset if the matching
# is not successful. may replace the bindings
# table in the future.
diagnostics*: seq[string] # when this is not nil, the matching process
# will collect extra diagnostics that will be
# displayed to the user.
# triggered when overload resolution fails
# or when the explain pragma is used. may be
# triggered with an idetools command in the
# future.
mutabilityProblem*: uint8 # tyVar mismatch
inheritancePenalty: int # to prefer closest father object type
errors*: CandidateErrors # additional clarifications to be displayed to the
# user if overload resolution fails
TTypeRelation* = enum # order is important!
isNone, isConvertible,
isIntConv,
@ -105,7 +116,7 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
idTablePut(c.bindings, key, val.skipIntLit)
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
binding: PNode, calleeScope = -1) =
binding: PNode, calleeScope = -1, diagnostics = false) =
initCandidateAux(ctx, c, callee.typ)
c.calleeSym = callee
if callee.kind in skProcKinds and calleeScope == -1:
@ -120,9 +131,9 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
c.calleeScope = 1
else:
c.calleeScope = calleeScope
c.diagnostics = if diagnostics: @[] else: nil
c.magic = c.calleeSym.magic
initIdTable(c.bindings)
c.errors = nil
if binding != nil and callee.kind in routineKinds:
var typeParams = callee.ast[genericParamsPos]
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
@ -577,14 +588,15 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
proc matchUserTypeClass*(c: PContext, m: var TCandidate,
ff, a: PType): PType =
var body = ff.skipTypes({tyUserTypeClassInst})
var
Concept = ff.skipTypes({tyUserTypeClassInst})
body = Concept.n[3]
if c.inTypeClass > 4:
localError(body.n[3].info, $body.n[3] & " too nested for type matching")
localError(body.info, $body & " too nested for type matching")
return nil
openScope(c)
inc c.inTypeClass
defer:
dec c.inTypeClass
closeScope(c)
@ -599,7 +611,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
param: PSym
template paramSym(kind): untyped =
newSym(kind, typeParamName, body.sym, body.sym.info)
newSym(kind, typeParamName, Concept.sym, Concept.sym.info)
case typ.kind
of tyStatic:
@ -622,7 +634,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
addDecl(c, param)
typeParams.safeAdd((param, typ))
for param in body.n[0]:
for param in Concept.n[0]:
var
dummyName: PNode
dummyType: PType
@ -645,11 +657,31 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
internalAssert dummyName.kind == nkIdent
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar,
dummyName.ident, body.sym, body.sym.info)
dummyName.ident, Concept.sym, Concept.sym.info)
dummyParam.typ = dummyType
addDecl(c, dummyParam)
var checkedBody = c.semTryExpr(c, body.n[3].copyTree)
var
oldWriteHook: type(writelnHook)
diagnostics: seq[string]
flags: TExprFlags = {}
collectDiagnostics = m.diagnostics != nil or
sfExplain in Concept.sym.flags
if collectDiagnostics:
oldWriteHook = writelnHook
# XXX: we can't write to m.diagnostics directly, because
# Nim doesn't support capturing var params in closures
diagnostics = @[]
writelnHook = proc (s: string) = diagnostics.add(s)
flags = {efExplain}
var checkedBody = c.semTryExpr(c, body.copyTree, flags)
if collectDiagnostics:
writelnHook = oldWriteHook
for msg in diagnostics: m.diagnostics.safeAdd msg
if checkedBody == nil: return nil
# The inferrable type params have been identified during the semTryExpr above.