From ecd83dd48621de783c81b36d3f3d3632272ff012 Mon Sep 17 00:00:00 2001 From: Clyybber Date: Tue, 22 Feb 2022 19:27:09 +0100 Subject: [PATCH] Debug unreported errors with -d:nimDebugUnreportedErrors Also fix semIf not handling nkError nodes correctly. Also cleanup buildErrorList/walkErrors roundabout way of doing post-visit DFS. Also improve rsemTypeKindMismatch error message. --- compiler/ast/errorhandling.nim | 16 ++++++++++++---- compiler/ast/errorreporting.nim | 8 +++++++- compiler/ast/reports.nim | 1 + compiler/ast/typesrenderer.nim | 2 +- compiler/front/cli_reporter.nim | 8 ++++++++ compiler/front/main.nim | 19 +++++++++++++++++++ compiler/front/options.nim | 4 ++++ compiler/sem/semstmts.nim | 16 +++++++++++----- doc/debug.rst | 15 ++++++++------- tests/errmsgs/tnested_errors.nim | 18 ++++++++++++++++++ 10 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 tests/errmsgs/tnested_errors.nim diff --git a/compiler/ast/errorhandling.nim b/compiler/ast/errorhandling.nim index 923ea08a4955a..6be9cce95a1d6 100644 --- a/compiler/ast/errorhandling.nim +++ b/compiler/ast/errorhandling.nim @@ -43,6 +43,9 @@ import front/[ msgs, options + ], + std/[ + tables ] proc errorSubNode*(n: PNode): PNode = @@ -102,6 +105,10 @@ proc newError*( for a in args: result.add #[ 3+ ]# a + when defined(nimDebugUnreportedErrors): + if errorKind != rsemWrappedError: + conf.unreportedErrors[result.reportId] = result + proc newError*( conf: ConfigRef, wrongNode: PNode, @@ -166,15 +173,16 @@ proc wrapIfErrorInSubTree*(conf: ConfigRef, wrongNodeContainer: PNode): PNode instLoc()) proc buildErrorList(config: ConfigRef, n: PNode, errs: var seq[PNode]) = - ## creates a list (`errs` seq) from least specific to most specific + ## creates a list (`errs` seq) from most specific to least specific + ## by traversing the the error tree in a depth-first-search. case n.kind of nkEmpty .. nkNilLit: discard of nkError: - errs.add n buildErrorList(config, n[wrongNodePos], errs) + errs.add n else: - for i in countdown(n.len - 1, 0): + for i in 0..typedesc: typedesc is declared as such, and is 10x more common. "GenericInvocation", "GenericBody", "GenericInst", "GenericParam", diff --git a/compiler/front/cli_reporter.nim b/compiler/front/cli_reporter.nim index 1c4551bd0d139..b32ca000eca67 100644 --- a/compiler/front/cli_reporter.nim +++ b/compiler/front/cli_reporter.nim @@ -910,6 +910,14 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string = of rsemTypeKindMismatch: result = r.str + result.add " got '$1'" % typeToString(r.actualType) + result.add " but expected " + var first = true + for typKind in r.formalTypeKind: + if not first: + result.add " or " + result.add "'$1'" % typeToStr[typKind] + first = false of rsemExprHasNoAddress: result = "expression has no address" diff --git a/compiler/front/main.nim b/compiler/front/main.nim index bb53e4b8c774c..4fcbdf5a072fd 100644 --- a/compiler/front/main.nim +++ b/compiler/front/main.nim @@ -59,6 +59,19 @@ from ic / ic import rodViewer when not defined(leanCompiler): import backend/jsgen, tools/[docgen, docgen2] +when defined(nimDebugUnreportedErrors): + import std/exitprocs + import utils/astrepr + + proc echoAndResetUnreportedErrors(conf: ConfigRef) = + if conf.unreportedErrors.len > 0: + echo "Unreported errors:" + for reportId, node in conf.unreportedErrors: + var reprConf = defaultTReprConf + reprConf.flags.incl trfShowNodeErrors + echo conf.treeRepr(node) + conf.unreportedErrors.clear + proc semanticPasses(g: ModuleGraph) = registerPass g, verbosePass registerPass g, semPass @@ -318,6 +331,9 @@ proc mainCommand*(graph: ModuleGraph) = if conf.cmd in cmdDocLike + {cmdRst2html, cmdRst2tex}: ret = ret / htmldocsDir conf.outDir = ret + when defined(nimDebugUnreportedErrors): + addExitProc proc = echoAndResetUnreportedErrors(conf) + ## process all commands case conf.cmd of cmdBackends: compileToBackend() @@ -432,6 +448,9 @@ proc mainCommand*(graph: ModuleGraph) = echo conf.dump(conf.vmProfileData) genSuccessX(conf) + when defined(nimDebugUnreportedErrors): + echoAndResetUnreportedErrors(conf) + when PrintRopeCacheStats: echo "rope cache stats: " echo " tries : ", gCacheTries diff --git a/compiler/front/options.nim b/compiler/front/options.nim index 5d773debbf252..803ca532d5c6e 100644 --- a/compiler/front/options.nim +++ b/compiler/front/options.nim @@ -19,6 +19,7 @@ export in_options from terminal import isatty from times import utc, fromUnix, local, getTime, format, DateTime from std/private/globs import nativeToUnixPath + const hasTinyCBackend* = defined(tinyc) useEffectSystem* = true @@ -244,6 +245,9 @@ type debugUtilsStack*: seq[string] ## which proc name to stop trace output ## len is also used for output indent level + when defined(nimDebugUnreportedErrors): + unreportedErrors*: OrderedTable[ReportId, PNode] + template `[]`*(conf: ConfigRef, idx: FileIndex): TFileInfo = conf.m.fileInfos[idx.uint32] diff --git a/compiler/sem/semstmts.nim b/compiler/sem/semstmts.nim index 44acfee3806f0..928d5a71dd679 100644 --- a/compiler/sem/semstmts.nim +++ b/compiler/sem/semstmts.nim @@ -134,6 +134,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode = result = n var typ = commonTypeBegin var hasElse = false + var hasError = false for i in 0..