summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorIDF <idf31@protonmail.com>2020-10-06 17:49:30 +0300
committerGitHub <noreply@github.com>2020-10-06 16:49:30 +0200
commit9560e49e8fa412839743aa86400bd73e2c57ab3d (patch)
tree0d342d9461fb30a2456c545266b50129463da92e
parent92163fa3304e5b6768a50d36a5243639ce4a2f69 (diff)
downloadNim-9560e49e8fa412839743aa86400bd73e2c57ab3d.tar.gz
New hint for unused exceptions in .raises (#15492)
* New hint for unused exceptions in .raises

* Fix effects test

* Further adapt teffects1.nim
-rw-r--r--compiler/lineinfos.nim4
-rw-r--r--compiler/sempass2.nim8
-rw-r--r--tests/effects/teffects1.nim7
3 files changed, 14 insertions, 5 deletions
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index c9821ac9f..db0569fda 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -58,6 +58,7 @@ type
     warnUser,
     hintSuccess, hintSuccessX, hintCC,
     hintLineTooLong, hintXDeclaredButNotUsed,
+    hintXCannotRaiseY,
     hintConvToBaseNotNeeded,
     hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
     hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
@@ -131,6 +132,7 @@ const
     hintCC: "CC: $1",
     hintLineTooLong: "line too long",
     hintXDeclaredButNotUsed: "'$1' is declared but not used",
+    hintXCannotRaiseY: "$1",
     hintConvToBaseNotNeeded: "conversion to base object is not needed",
     hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
     hintExprAlwaysX: "expression evaluates always to '$1'",
@@ -179,7 +181,7 @@ const
 
   HintsToStr* = [
     "Success", "SuccessX", "CC", "LineTooLong",
-    "XDeclaredButNotUsed",
+    "XDeclaredButNotUsed", "XCannotRaiseY",
     "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
     "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
     "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 19223b88f..4eac6ef13 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -1140,7 +1140,8 @@ proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool =
     return safeInheritanceDiff(g.excType(real), spec.typ) <= 0
 
 proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool;
-                     effectPredicate: proc (g: ModuleGraph; a, b: PNode): bool {.nimcall.}) =
+                     effectPredicate: proc (g: ModuleGraph; a, b: PNode): bool {.nimcall.};
+                     hintsArg: PNode = nil) =
   # check that any real exception is listed in 'spec'; mark those as used;
   # report any unused exception
   var used = initIntSet()
@@ -1158,7 +1159,8 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
   if hints:
     for s in 0..<spec.len:
       if not used.contains(s):
-        message(g.config, spec[s].info, hintXDeclaredButNotUsed, renderTree(spec[s]))
+        message(g.config, spec[s].info, hintXCannotRaiseY,
+                "'$1' cannot raise '$2'" % [renderTree(hintsArg), renderTree(spec[s])])
 
 proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
   ## checks for consistent effects for multi methods.
@@ -1279,7 +1281,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
   let raisesSpec = effectSpec(p, wRaises)
   if not isNil(raisesSpec):
     checkRaisesSpec(g, raisesSpec, t.exc, "can raise an unlisted exception: ",
-                    hints=on, subtypeRelation)
+                    hints=on, subtypeRelation, hintsArg=s.ast[0])
     # after the check, use the formal spec:
     effects[exceptionEffects] = raisesSpec
 
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index 3551ff1a1..66d6a3518 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,5 +1,10 @@
 discard """
   cmd: "nim check $file"
+  nimout: '''teffects1.nim(22, 28) template/generic instantiation from here
+teffects1.nim(23, 13) Error: can raise an unlisted exception: ref IOError
+teffects1.nim(22, 29) Hint: 'lier' cannot raise 'IO2Error' [XCannotRaiseY]
+teffects1.nim(38, 21) Error: type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
+.raise effects differ'''
 """
 
 type
@@ -12,7 +17,7 @@ type
 proc forw: int {. .}
 
 proc lier(): int {.raises: [IO2Error].} =
-  #[tt.Hint                 ^ 'IO2Error' is declared but not used [XDeclaredButNotUsed] ]#
+  #[tt.Hint                 ^ 'lier' cannot raise 'IO2Error' [XCannotRaiseY] ]#
   writeLine stdout, "arg" #[tt.Error
             ^  can raise an unlisted exception: ref IOError
   ]#