summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2018-09-25 00:28:39 +0200
committerAraq <rumpf_a@web.de>2018-09-25 00:28:39 +0200
commit548fc778c9b7048f474bf53c5d665bb8425e3343 (patch)
treebfae68122544db324cbb01b032eab1795ed6e0b8
parent8029a649ba2cd394cad1749c017d5758cdcdbd4c (diff)
downloadNim-548fc778c9b7048f474bf53c5d665bb8425e3343.tar.gz
.error for routines now can also have a custom error message; improve error message for 'nil' strings
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/suggest.nim31
-rw-r--r--lib/system.nim12
4 files changed, 33 insertions, 15 deletions
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index a22b613f0..62c55de3d 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -81,6 +81,7 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimAshr")
   defineSymbol("nimNoNilSeqs")
   defineSymbol("nimNoNilSeqs2")
+  defineSymbol("nimHasUserErrors")
 
   defineSymbol("nimHasNilSeqs")
   for f in low(Feature)..high(Feature):
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 36c79bc9e..9a624fcce 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -954,12 +954,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         recordPragma(c, it, "warning", s)
         message(c.config, it.info, warnUser, s)
       of wError:
-        if sym != nil and sym.isRoutine:
+        if sym != nil and (sym.isRoutine or sym.kind == skType):
           # This is subtle but correct: the error *statement* is only
           # allowed for top level statements. Seems to be easier than
           # distinguishing properly between
           # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
-          noVal(c, it)
+          if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
           incl(sym.flags, sfError)
         else:
           let s = expectStrLit(c, it)
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index b6b8d713c..b264415d8 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -33,7 +33,7 @@
 # included from sigmatch.nim
 
 import algorithm, prefixmatches, lineinfos, pathutils
-from wordrecg import wDeprecated
+from wordrecg import wDeprecated, wError
 
 when defined(nimsuggest):
   import passes, tables # importer
@@ -453,33 +453,42 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
         isDecl:
       suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
 
-proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
-  var pragmaNode: PNode
-
+proc extractPragma(s: PSym): PNode =
   if s.kind in routineKinds:
-    pragmaNode = s.ast[pragmasPos]
+    result = s.ast[pragmasPos]
   elif s.kind in {skType}:
     # s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
-    pragmaNode = s.ast[0][1]
-
-  doAssert pragmaNode == nil or pragmaNode.kind == nkPragma
+    result = s.ast[0][1]
+  doAssert result == nil or result.kind == nkPragma
 
+proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
+  let pragmaNode = extractPragma(s)
   if pragmaNode != nil:
     for it in pragmaNode:
       if whichPragma(it) == wDeprecated and it.safeLen == 2 and
-        it[1].kind in {nkStrLit..nkTripleStrLit}:
+          it[1].kind in {nkStrLit..nkTripleStrLit}:
         message(conf, info, warnDeprecated, it[1].strVal & "; " & s.name.s)
         return
-
   message(conf, info, warnDeprecated, s.name.s)
 
+proc userError(conf: ConfigRef; info: TLineInfo; s: PSym) =
+  let pragmaNode = extractPragma(s)
+
+  if pragmaNode != nil:
+    for it in pragmaNode:
+      if whichPragma(it) == wError and it.safeLen == 2 and
+          it[1].kind in {nkStrLit..nkTripleStrLit}:
+        localError(conf, info, it[1].strVal & "; usage of '$1' is a user-defined error" % s.name.s)
+        return
+  localError(conf, info, "usage of '$1' is a user-defined error" % s.name.s)
+
 proc markUsed(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
   incl(s.flags, sfUsed)
   if s.kind == skEnumField and s.owner != nil:
     incl(s.owner.flags, sfUsed)
   if {sfDeprecated, sfError} * s.flags != {}:
     if sfDeprecated in s.flags: warnAboutDeprecated(conf, info, s)
-    if sfError in s.flags: localError(conf, info,  "usage of '$1' is a user-defined error" % s.name.s)
+    if sfError in s.flags: userError(conf, info, s)
   when defined(nimsuggest):
     suggestSym(conf, info, s, usageSym, false)
 
diff --git a/lib/system.nim b/lib/system.nim
index 49e6a396d..28c4f62ab 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -4112,8 +4112,16 @@ proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect,
 
 when defined(nimNoNilSeqs2):
   when not compileOption("nilseqs"):
-    proc `==`*(x: string; y: type(nil)): bool {.error.} = discard
-    proc `==`*(x: type(nil); y: string): bool {.error.} = discard
+    when defined(nimHasUserErrors):
+      proc `==`*(x: string; y: type(nil)): bool {.
+          error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} =
+        discard
+      proc `==`*(x: type(nil); y: string): bool {.
+          error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} =
+        discard
+    else:
+      proc `==`*(x: string; y: type(nil)): bool {.error.} = discard
+      proc `==`*(x: type(nil); y: string): bool {.error.} = discard
 
 template closureScope*(body: untyped): untyped =
   ## Useful when creating a closure in a loop to capture local loop variables by