mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-04 04:54:49 +00:00
further improvements to the error messages produced by concepts
This commit is contained in:
@@ -133,7 +133,7 @@ type
|
||||
hintConditionAlwaysTrue, hintName, hintPattern,
|
||||
hintExecuting, hintLinking, hintDependency,
|
||||
hintSource, hintStackTrace, hintGCStats,
|
||||
hintUser
|
||||
hintUser, hintUserRaw
|
||||
|
||||
const
|
||||
MsgKindToStr*: array[TMsgKind, string] = [
|
||||
@@ -434,10 +434,11 @@ const
|
||||
hintSource: "$1",
|
||||
hintStackTrace: "$1",
|
||||
hintGCStats: "$1",
|
||||
hintUser: "$1"]
|
||||
hintUser: "$1",
|
||||
hintUserRaw: "$1"]
|
||||
|
||||
const
|
||||
WarningsToStr*: array[0..30, string] = ["CannotOpenFile", "OctalEscape",
|
||||
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
|
||||
"XIsNeverRead", "XmightNotBeenInit",
|
||||
"Deprecated", "ConfigDeprecated",
|
||||
"SmallLshouldNotBeUsed", "UnknownMagic",
|
||||
@@ -449,12 +450,12 @@ const
|
||||
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
|
||||
"GcMem", "Destructor", "LockLevel", "ResultShadowed", "User"]
|
||||
|
||||
HintsToStr*: array[0..22, string] = ["Success", "SuccessX", "LineTooLong",
|
||||
HintsToStr* = ["Success", "SuccessX", "LineTooLong",
|
||||
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
|
||||
"Source", "StackTrace", "GCStats",
|
||||
"User"]
|
||||
"User", "UserRaw"]
|
||||
|
||||
const
|
||||
fatalMin* = errUnknown
|
||||
@@ -658,9 +659,6 @@ proc concat(strings: openarray[string]): string =
|
||||
result = newStringOfCap totalLen
|
||||
for s in strings: result.add s
|
||||
|
||||
template writeBufferedMsg(args: varargs[string, `$`]) =
|
||||
bufferedMsgs.safeAdd concat(args)
|
||||
|
||||
proc suggestWriteln*(s: string) =
|
||||
if eStdOut in errorOutputs:
|
||||
if isNil(writelnHook):
|
||||
@@ -929,7 +927,7 @@ proc rawMessage*(msg: TMsgKind, args: openArray[string]) =
|
||||
if msg notin gNotes: return
|
||||
title = HintTitle
|
||||
color = HintColor
|
||||
kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||
inc(gHintCounter)
|
||||
let s = msgKindToString(msg) % args
|
||||
|
||||
@@ -997,7 +995,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
ignoreMsg = optHints notin gOptions or msg notin gNotes
|
||||
title = HintTitle
|
||||
color = HintColor
|
||||
kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||
inc(gHintCounter)
|
||||
# NOTE: currently line info line numbers start with 1,
|
||||
# but column numbers start with 0, however most editors expect
|
||||
|
||||
@@ -215,7 +215,6 @@ proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||
proc isOpImpl(c: PContext, n: PNode): PNode
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
flags: TExprFlags = {}): PNode
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
|
||||
@@ -148,7 +148,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||
# as semOverlodedCall is already pretty slow (and we need this information
|
||||
# only in case of an error).
|
||||
if c.compilesContextId > 0:
|
||||
if errorOutputs == {}:
|
||||
# fail fast:
|
||||
globalError(n.info, errTypeMismatch, "")
|
||||
if errors.isNil or errors.len == 0:
|
||||
@@ -263,7 +263,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
internalAssert result.state == csMatch
|
||||
#writeMatches(result)
|
||||
#writeMatches(alt)
|
||||
if c.compilesContextId > 0:
|
||||
if errorOutputs == {}:
|
||||
# quick error message for performance of 'compiles' built-in:
|
||||
globalError(n.info, errGenerated, "ambiguous call")
|
||||
elif gErrorCounter == 0:
|
||||
@@ -374,7 +374,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
# this may be triggered, when the explain pragma is used
|
||||
if errors.len > 0:
|
||||
let (_, candidates) = presentFailedCandidates(c, n, errors)
|
||||
message(n.info, hintUser,
|
||||
message(n.info, hintUserRaw,
|
||||
"Non-matching candidates for " & renderTree(n) & "\n" &
|
||||
candidates)
|
||||
result = semResolvedCall(c, n, r)
|
||||
|
||||
@@ -302,7 +302,7 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc isOpImpl(c: PContext, n: PNode): PNode =
|
||||
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
internalAssert n.sonsLen == 3 and
|
||||
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
|
||||
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||
@@ -324,12 +324,13 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
|
||||
maybeLiftType(t2, c, n.info)
|
||||
var m: TCandidate
|
||||
initCandidate(c, m, t2)
|
||||
if efExplain in flags: m.diagnostics = @[]
|
||||
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
||||
result = newIntNode(nkIntLit, ord(match))
|
||||
|
||||
result.typ = n.typ
|
||||
|
||||
proc semIs(c: PContext, n: PNode): PNode =
|
||||
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) != 3:
|
||||
localError(n.info, errXExpectsTwoArguments, "is")
|
||||
|
||||
@@ -349,7 +350,7 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||
return
|
||||
|
||||
# BUGFIX: don't evaluate this too early: ``T is void``
|
||||
if not n[1].typ.base.containsGenericType: result = isOpImpl(c, n)
|
||||
if not n[1].typ.base.containsGenericType: result = isOpImpl(c, n, flags)
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
const flags = {efDetermineType}
|
||||
@@ -754,7 +755,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# This is a proc variable, apply normal overload resolution
|
||||
let m = resolveIndirectCall(c, n, nOrig, t)
|
||||
if m.state != csMatch:
|
||||
if c.compilesContextId > 0:
|
||||
if errorOutputs == {}:
|
||||
# speed up error generation:
|
||||
globalError(n.info, errTypeMismatch, "")
|
||||
return emptyNode
|
||||
@@ -1837,7 +1838,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
||||
of mIs: result = semIs(c, setMs(n, s))
|
||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||
of mOf: result = semOf(c, setMs(n, s))
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||
|
||||
@@ -1609,7 +1609,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
n.typ = n.sons[i].typ
|
||||
return
|
||||
else:
|
||||
var expr = semExpr(c, n.sons[i])
|
||||
var expr = semExpr(c, n.sons[i], flags)
|
||||
n.sons[i] = expr
|
||||
if c.inTypeClass > 0 and expr.typ != nil:
|
||||
case expr.typ.kind
|
||||
|
||||
@@ -664,6 +664,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||
var
|
||||
oldWriteHook: type(writelnHook)
|
||||
diagnostics: seq[string]
|
||||
errorPrefix: string
|
||||
flags: TExprFlags = {}
|
||||
collectDiagnostics = m.diagnostics != nil or
|
||||
sfExplain in Concept.sym.flags
|
||||
@@ -673,9 +674,13 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||
# 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}
|
||||
|
||||
writelnHook = proc (s: string) =
|
||||
if errorPrefix == nil: errorPrefix = Concept.sym.name.s & ":"
|
||||
let msg = s.replace("Error:", errorPrefix)
|
||||
if oldWriteHook != nil: oldWriteHook msg
|
||||
diagnostics.add msg
|
||||
|
||||
var checkedBody = c.semTryExpr(c, body.copyTree, flags)
|
||||
|
||||
if collectDiagnostics:
|
||||
|
||||
Reference in New Issue
Block a user