* 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:
parent
fb26b95f81
commit
bf3a308e86
9 changed files with 129 additions and 31 deletions
|
|
@ -150,7 +150,7 @@ type
|
||||||
|
|
||||||
proc getSymRepr*(conf: ConfigRef; s: PSym): string =
|
proc getSymRepr*(conf: ConfigRef; s: PSym): string =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skFunc, skMethod, skConverter, skIterator:
|
of routineKinds, skType:
|
||||||
result = getProcHeader(conf, s)
|
result = getProcHeader(conf, s)
|
||||||
else:
|
else:
|
||||||
result = s.name.s
|
result = s.name.s
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,10 @@ const
|
||||||
WarningColor = fgYellow
|
WarningColor = fgYellow
|
||||||
HintTitle = "Hint: "
|
HintTitle = "Hint: "
|
||||||
HintColor = fgGreen
|
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 getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
|
||||||
proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
|
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:
|
if fileIdx.int32 < 0 or conf == nil:
|
||||||
"???"
|
"???"
|
||||||
else:
|
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 =
|
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||||
if fileIdx.int32 < 0 or conf == nil: result = "???"
|
if fileIdx.int32 < 0 or conf == nil: result = "???"
|
||||||
|
|
@ -192,10 +199,10 @@ proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
|
||||||
result = "???"
|
result = "???"
|
||||||
return
|
return
|
||||||
let absPath = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
|
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:
|
if optListFullPaths in conf.globalOptions:
|
||||||
result = absPath
|
result = absPath
|
||||||
else:
|
else:
|
||||||
|
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
|
||||||
result = if absPath.len < relPath.len: absPath else: relPath
|
result = if absPath.len < relPath.len: absPath else: relPath
|
||||||
|
|
||||||
proc toLinenumber*(info: TLineInfo): int {.inline.} =
|
proc toLinenumber*(info: TLineInfo): int {.inline.} =
|
||||||
|
|
@ -208,7 +215,9 @@ proc toFileLine*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
|
||||||
result = toFilename(conf, info) & ":" & $info.line
|
result = toFilename(conf, info) & ":" & $info.line
|
||||||
|
|
||||||
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
|
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)
|
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
|
||||||
|
|
||||||
|
|
@ -359,7 +368,7 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
|
||||||
styledMsgWriteln(styleBright,
|
styledMsgWriteln(styleBright,
|
||||||
PosFormat % [toMsgFilename(conf, context.info),
|
PosFormat % [toMsgFilename(conf, context.info),
|
||||||
coordToStr(context.info.line.int),
|
coordToStr(context.info.line.int),
|
||||||
coordToStr(context.info.col+1)],
|
coordToStr(context.info.col+ColOffset)],
|
||||||
resetStyle,
|
resetStyle,
|
||||||
message)
|
message)
|
||||||
info = context.info
|
info = context.info
|
||||||
|
|
@ -446,7 +455,7 @@ proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): s
|
||||||
of hintMin..hintMax: HintTitle
|
of hintMin..hintMax: HintTitle
|
||||||
else: ErrorTitle
|
else: ErrorTitle
|
||||||
result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
|
result = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
|
||||||
coordToStr(info.col+1)] &
|
coordToStr(info.col+ColOffset)] &
|
||||||
title &
|
title &
|
||||||
getMessageStr(msg, arg)
|
getMessageStr(msg, arg)
|
||||||
|
|
||||||
|
|
@ -483,11 +492,8 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
color = HintColor
|
color = HintColor
|
||||||
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||||
inc(conf.hintCounter)
|
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),
|
let x = PosFormat % [toMsgFilename(conf, info), coordToStr(info.line.int),
|
||||||
coordToStr(info.col+1)]
|
coordToStr(info.col+ColOffset)]
|
||||||
let s = getMessageStr(msg, arg)
|
let s = getMessageStr(msg, arg)
|
||||||
|
|
||||||
if not ignoreMsg:
|
if not ignoreMsg:
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ type # please make sure we have under 32 options
|
||||||
optShowAllMismatches # show all overloading resolution candidates
|
optShowAllMismatches # show all overloading resolution candidates
|
||||||
optWholeProject # for 'doc2': output any dependency
|
optWholeProject # for 'doc2': output any dependency
|
||||||
optMixedMode # true if some module triggered C++ codegen
|
optMixedMode # true if some module triggered C++ codegen
|
||||||
optListFullPaths
|
optListFullPaths # use full paths in toMsgFilename, toFilename
|
||||||
optNoNimblePath
|
optNoNimblePath
|
||||||
optDynlibOverrideAll
|
optDynlibOverrideAll
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,20 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||||
|
|
||||||
let ident = considerQuotedIdent(c, f, n).s
|
let ident = considerQuotedIdent(c, f, n).s
|
||||||
if nfDotField in n.flags and nfExplicitCall notin n.flags:
|
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:
|
else:
|
||||||
if result.len == 0: result = errUndeclaredRoutine % ident
|
if result.len == 0: result = errUndeclaredRoutine % ident
|
||||||
else: result = errBadRoutine % [ident, result]
|
else: result = errBadRoutine % [ident, result]
|
||||||
|
|
|
||||||
|
|
@ -107,20 +107,23 @@ proc isFloatLit*(t: PType): bool {.inline.} =
|
||||||
result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
|
result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
|
||||||
|
|
||||||
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName): string =
|
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName): string =
|
||||||
result = sym.owner.name.s & '.' & sym.name.s & '('
|
assert sym != nil
|
||||||
var n = sym.typ.n
|
result = sym.owner.name.s & '.' & sym.name.s
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
if sym.kind in routineKinds:
|
||||||
let p = n.sons[i]
|
result.add '('
|
||||||
if p.kind == nkSym:
|
var n = sym.typ.n
|
||||||
add(result, p.sym.name.s)
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
add(result, ": ")
|
let p = n.sons[i]
|
||||||
add(result, typeToString(p.sym.typ, prefer))
|
if p.kind == nkSym:
|
||||||
if i != sonsLen(n)-1: add(result, ", ")
|
add(result, p.sym.name.s)
|
||||||
else:
|
add(result, ": ")
|
||||||
result.add renderTree(p)
|
add(result, typeToString(p.sym.typ, prefer))
|
||||||
add(result, ')')
|
if i != sonsLen(n)-1: add(result, ", ")
|
||||||
if n.sons[0].typ != nil:
|
else:
|
||||||
result.add(": " & typeToString(n.sons[0].typ, prefer))
|
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 "[declared in "
|
||||||
result.add(conf$sym.info)
|
result.add(conf$sym.info)
|
||||||
result.add "]"
|
result.add "]"
|
||||||
|
|
|
||||||
|
|
@ -65,15 +65,20 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
|
||||||
return
|
return
|
||||||
stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
|
stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
|
||||||
var info = c.debug[pc]
|
var info = c.debug[pc]
|
||||||
# we now use the same format as in system/except.nim
|
# we now use a format similar to the one in lib/system/excpt.nim
|
||||||
var s = substr(toFilename(c.config, info), 0)
|
var s = ""
|
||||||
# this 'substr' prevents a strange corruption. XXX This needs to be
|
# todo: factor with quotedFilename
|
||||||
# investigated eventually but first attempts to fix it broke everything
|
if optExcessiveStackTrace in c.config.globalOptions:
|
||||||
# see the araq-wip-fixed-writebarrier branch.
|
s = toFullPath(c.config, info)
|
||||||
|
else:
|
||||||
|
s = toFilename(c.config, info)
|
||||||
var line = toLinenumber(info)
|
var line = toLinenumber(info)
|
||||||
|
var col = toColumn(info)
|
||||||
if line > 0:
|
if line > 0:
|
||||||
add(s, '(')
|
add(s, '(')
|
||||||
add(s, $line)
|
add(s, $line)
|
||||||
|
add(s, ", ")
|
||||||
|
add(s, $(col + ColOffset))
|
||||||
add(s, ')')
|
add(s, ')')
|
||||||
if x.prc != nil:
|
if x.prc != nil:
|
||||||
for k in 1..max(1, 25-s.len): add(s, ' ')
|
for k in 1..max(1, 25-s.len): add(s, ' ')
|
||||||
|
|
|
||||||
2
tests/errmsgs/m8794.nim
Normal file
2
tests/errmsgs/m8794.nim
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
type Foo3* = object
|
||||||
|
a1: int
|
||||||
39
tests/errmsgs/t8794.nim
Normal file
39
tests/errmsgs/t8794.nim
Normal 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
30
tests/errmsgs/t9768.nim
Normal 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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue