.forbids pragma: defining forbidden tags (#20050)

* .forbids pragma: defining illegal effects for proc types

This patch intends to define the opposite of the .tags pragma: a way to define effects which are not allowed in a proc.

* updated documentation and changelogs for the forbids pragma

* renamed notTagEffects to forbiddenEffects

* corrected issues of forbids pragma

the forbids pragma didn't handle simple restrictions properly and it also had issues with subtyping

* removed incorrect character from changelog

* added test to cover the interaction of methods and the forbids pragma

* covering the interaction of the tags and forbids pragmas

* updated manual about the forbids pragma

* removed useless statement

* corrected the subtyping of proc types using the forbids pragma

* updated manual for the forbids pragma

* updated documentations for forbids pragma

* updated nim docs

* updated docs with rsttester.nim

* regenerated documentation

* updated rst docs

* Update changelog.md

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>

* updated changelog

* corrected typo

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
This commit is contained in:
Lancer11211 2022-07-26 07:40:49 +02:00 • committed by GitHub
commit efd5c571bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 405 additions and 71 deletions

View file

@ -1372,6 +1372,13 @@ proc compatibleEffectsAux(se, re: PNode): bool =
return false
result = true
proc hasIncompatibleEffect(se, re: PNode): bool =
if re.isNil: return false
for r in items(re):
for s in items(se):
if safeInheritanceDiff(r.typ, s.typ) != high(int):
return true
type
EffectsCompat* = enum
efCompat
@ -1381,6 +1388,7 @@ type
efTagsUnknown
efLockLevelsDiffer
efEffectsDelayed
efTagsIllegal
proc compatibleEffects*(formal, actual: PType): EffectsCompat =
# for proc type compatibility checking:
@ -1414,6 +1422,14 @@ proc compatibleEffects*(formal, actual: PType): EffectsCompat =
if not res:
#if tfEffectSystemWorkaround notin actual.flags:
return efTagsDiffer
let sn = spec[forbiddenEffects]
if not isNil(sn) and sn.kind != nkArgList:
if 0 == real.len:
return efTagsUnknown
elif hasIncompatibleEffect(sn, real[tagEffects]):
return efTagsIllegal
if formal.lockLevel.ord < 0 or
actual.lockLevel.ord <= formal.lockLevel.ord:
@ -1627,6 +1643,8 @@ proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType, n: P
msg.add "\nlock levels differ"
of efEffectsDelayed:
msg.add "\n.effectsOf annotations differ"
of efTagsIllegal:
msg.add "\n.notTag catched an illegal effect"
localError(conf, info, msg)
proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool =