[error messages, stacktraces] fix #8794 #9270 #9767 #9768 (#9766)

* fixes #8794 : `Error: undeclared field: 'foo'` should show type (+ where type is defined) (hard to guess in generic code)

* fixes #9270: `--listFullPaths` not honored by `declared in foo.nim` messages

* fixes #9767: VM stacktrace doesn't honor --excessiveStackTrace:on

* fixes #9768: VM stacktrace misses column info, can lead to ambiguous or harder to read stacktraces

* refactors some col+1 code to col + ColOffset (self documents code)

* make getProcHeader show declared info location also for types and all routine kinds (including macros,templates) instead of just (rather arbitrarily) for iterator,proc,func,method

* --listFullPaths now is honored in more places

* fix typo system/except.nim => lib/system/excpt.nim

* remove substr(foo, 0) hack in compiler/vm.nim which seems old and not applicable anymore
This commit is contained in:
Timothee Cour
2019-01-08 15:58:47 -08:00
committed by GitHub
parent fb26b95f81
commit bf3a308e86
9 changed files with 129 additions and 31 deletions

View File

@@ -150,7 +150,7 @@ type
proc getSymRepr*(conf: ConfigRef; s: PSym): string =
case s.kind
of skProc, skFunc, skMethod, skConverter, skIterator:
of routineKinds, skType:
result = getProcHeader(conf, s)
else:
result = s.name.s

View File

@@ -135,6 +135,10 @@ const
WarningColor = fgYellow
HintTitle = "Hint: "
HintColor = fgGreen
# NOTE: currently line info line numbers start with 1,
# but column numbers start with 0, however most editors expect
# first column to be 1, so we need to +1 here
ColOffset* = 1
proc getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
@@ -155,7 +159,10 @@ template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil:
"???"
else:
conf.m.fileInfos[fileIdx.int32].projPath.string
if optListFullPaths in conf.globalOptions:
conf.m.fileInfos[fileIdx.int32].fullPath.string
else:
conf.m.fileInfos[fileIdx.int32].projPath.string
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: result = "???"
@@ -192,10 +199,10 @@ proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
result = "???"
return
let absPath = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
if optListFullPaths in conf.globalOptions:
result = absPath
else:
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
result = if absPath.len < relPath.len: absPath else: relPath
proc toLinenumber*(info: TLineInfo): int {.inline.} =
@@ -208,7 +215,9 @@ proc toFileLine*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
result = toFilename(conf, info) & ":" & $info.line
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
result = toFilename(conf, info) & "(" & $info.line & ", " & $(info.col+1) & ")"
# consider calling `helpers.lineInfoToString` instead
result = toFilename(conf, info) & "(" & $info.line & ", " &
$(info.col + ColOffset) & ")"
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
@@ -359,7 +368,7 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
styledMsgWriteln(styleBright,
PosFormat % [toMsgFilename(conf, context.info),
coordToStr(context.info.line.int),
coordToStr(context.info.col+1)],
coordToStr(context.info.col+ColOffset)],
resetStyle,
message)
info = context.info
@@ -446,7 +455,7 @@ proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): s
of hintMin..hintMax: HintTitle
else: ErrorTitle
result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
coordToStr(info.col+1)] &
coordToStr(info.col+ColOffset)] &
title &
getMessageStr(msg, arg)
@@ -483,11 +492,8 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
inc(conf.hintCounter)
# NOTE: currently line info line numbers start with 1,
# but column numbers start with 0, however most editors expect
# first column to be 1, so we need to +1 here
let x = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
coordToStr(info.col+1)]
coordToStr(info.col+ColOffset)]
let s = getMessageStr(msg, arg)
if not ignoreMsg:

View File

@@ -78,7 +78,7 @@ type # please make sure we have under 32 options
optShowAllMismatches # show all overloading resolution candidates
optWholeProject # for 'doc2': output any dependency
optMixedMode # true if some module triggered C++ codegen
optListFullPaths
optListFullPaths # use full paths in toMsgFilename, toFilename
optNoNimblePath
optDynlibOverrideAll

View File

@@ -287,7 +287,20 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
let ident = considerQuotedIdent(c, f, n).s
if nfDotField in n.flags and nfExplicitCall notin n.flags:
result = errUndeclaredField % ident & result
let sym = n.sons[1].typ.sym
var typeHint = ""
if sym == nil:
#[
Perhaps we're in a `compiles(foo.bar)` expression, or
in a concept, eg:
ExplainedConcept {.explain.} = concept o
o.foo is int
We coudl use: `(c.config $ n.sons[1].info)` to get more context.
]#
discard
else:
typeHint = " for type " & getProcHeader(c.config, sym)
result = errUndeclaredField % ident & typeHint & " " & result
else:
if result.len == 0: result = errUndeclaredRoutine % ident
else: result = errBadRoutine % [ident, result]

View File

@@ -107,20 +107,23 @@ proc isFloatLit*(t: PType): bool {.inline.} =
result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName): string =
result = sym.owner.name.s & '.' & sym.name.s & '('
var n = sym.typ.n
for i in countup(1, sonsLen(n) - 1):
let p = n.sons[i]
if p.kind == nkSym:
add(result, p.sym.name.s)
add(result, ": ")
add(result, typeToString(p.sym.typ, prefer))
if i != sonsLen(n)-1: add(result, ", ")
else:
result.add renderTree(p)
add(result, ')')
if n.sons[0].typ != nil:
result.add(": " & typeToString(n.sons[0].typ, prefer))
assert sym != nil
result = sym.owner.name.s & '.' & sym.name.s
if sym.kind in routineKinds:
result.add '('
var n = sym.typ.n
for i in countup(1, sonsLen(n) - 1):
let p = n.sons[i]
if p.kind == nkSym:
add(result, p.sym.name.s)
add(result, ": ")
add(result, typeToString(p.sym.typ, prefer))
if i != sonsLen(n)-1: add(result, ", ")
else:
result.add renderTree(p)
add(result, ')')
if n.sons[0].typ != nil:
result.add(": " & typeToString(n.sons[0].typ, prefer))
result.add "[declared in "
result.add(conf$sym.info)
result.add "]"

View File

@@ -65,15 +65,20 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
return
stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
var info = c.debug[pc]
# we now use the same format as in system/except.nim
var s = substr(toFilename(c.config, info), 0)
# this 'substr' prevents a strange corruption. XXX This needs to be
# investigated eventually but first attempts to fix it broke everything
# see the araq-wip-fixed-writebarrier branch.
# we now use a format similar to the one in lib/system/excpt.nim
var s = ""
# todo: factor with quotedFilename
if optExcessiveStackTrace in c.config.globalOptions:
s = toFullPath(c.config, info)
else:
s = toFilename(c.config, info)
var line = toLinenumber(info)
var col = toColumn(info)
if line > 0:
add(s, '(')
add(s, $line)
add(s, ", ")
add(s, $(col + ColOffset))
add(s, ')')
if x.prc != nil:
for k in 1..max(1, 25-s.len): add(s, ' ')

2
tests/errmsgs/m8794.nim Normal file
View File

@@ -0,0 +1,2 @@
type Foo3* = object
a1: int

39
tests/errmsgs/t8794.nim Normal file
View File

@@ -0,0 +1,39 @@
discard """
cmd: "nim check $options $file"
errormsg: ""
nimout: '''
t8794.nim(39, 27) Error: undeclared field: 'a3' for type m8794.Foo3[declared in m8794.nim(1, 6)]
'''
"""
## line 20
## issue #8794
import m8794
when false: # pending https://github.com/nim-lang/Nim/pull/10091 add this
type Foo = object
a1: int
discard Foo().a2
type Foo3b = Foo3
var x2: Foo3b
proc getFun[T](): T =
var a: T
a
discard getFun[type(x2)]().a3

30
tests/errmsgs/t9768.nim Normal file
View File

@@ -0,0 +1,30 @@
discard """
errmsg: "unhandled exception:"
file: "system.nim"
nimout: '''
stack trace: (most recent call last)
t9768.nim(28, 33) main
t9768.nim(23, 11) foo1
'''
"""
## line 20
proc foo1(a: int): auto =
doAssert a < 4
result = a * 2
proc main()=
static:
if foo1(1) > 0: discard foo1(foo1(2))
main()