New hint for unused exceptions in .raises (#15492)

* New hint for unused exceptions in .raises

* Fix effects test

* Further adapt teffects1.nim
This commit is contained in:
IDF 2020-10-06 17:49:30 +03:00 • committed by GitHub
commit 9560e49e8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 5 deletions

View file

@ -58,6 +58,7 @@ type
warnUser, warnUser,
hintSuccess, hintSuccessX, hintCC, hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintLineTooLong, hintXDeclaredButNotUsed,
hintXCannotRaiseY,
hintConvToBaseNotNeeded, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
@ -131,6 +132,7 @@ const
hintCC: "CC: $1", hintCC: "CC: $1",
hintLineTooLong: "line too long", hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used", hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintXCannotRaiseY: "$1",
hintConvToBaseNotNeeded: "conversion to base object is not needed", hintConvToBaseNotNeeded: "conversion to base object is not needed",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless", hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
hintExprAlwaysX: "expression evaluates always to '$1'", hintExprAlwaysX: "expression evaluates always to '$1'",
@ -179,7 +181,7 @@ const
HintsToStr* = [ HintsToStr* = [
"Success", "SuccessX", "CC", "LineTooLong", "Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "XDeclaredButNotUsed", "XCannotRaiseY",
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency", "Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",

View file

@ -1140,7 +1140,8 @@ proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool =
return safeInheritanceDiff(g.excType(real), spec.typ) <= 0 return safeInheritanceDiff(g.excType(real), spec.typ) <= 0
proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool; 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; # check that any real exception is listed in 'spec'; mark those as used;
# report any unused exception # report any unused exception
var used = initIntSet() var used = initIntSet()
@ -1158,7 +1159,8 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
if hints: if hints:
for s in 0..<spec.len: for s in 0..<spec.len:
if not used.contains(s): 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) = proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
## checks for consistent effects for multi methods. ## checks for consistent effects for multi methods.
@ -1279,7 +1281,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
let raisesSpec = effectSpec(p, wRaises) let raisesSpec = effectSpec(p, wRaises)
if not isNil(raisesSpec): if not isNil(raisesSpec):
checkRaisesSpec(g, raisesSpec, t.exc, "can raise an unlisted exception: ", 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: # after the check, use the formal spec:
effects[exceptionEffects] = raisesSpec effects[exceptionEffects] = raisesSpec

View file

@ -1,5 +1,10 @@
discard """ discard """
cmd: "nim check $file" 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 type
@ -12,7 +17,7 @@ type
proc forw: int {. .} proc forw: int {. .}
proc lier(): int {.raises: [IO2Error].} = 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 writeLine stdout, "arg" #[tt.Error
^ can raise an unlisted exception: ref IOError ^ can raise an unlisted exception: ref IOError
]# ]#