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:
parent
92163fa330
commit
9560e49e8f
3 changed files with 14 additions and 5 deletions
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
]#
|
]#
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue