mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-03 19:52:36 +00:00
Merge branch 'devel' into araq-pipeline
This commit is contained in:
@@ -84,6 +84,8 @@
|
||||
- `macros.getImpl` for `const` symbols now returns the full definition node
|
||||
(as `nnkConstDef`) rather than the AST of the constant value.
|
||||
|
||||
- Lock levels are deprecated, now a noop.
|
||||
|
||||
- ORC is now the default memory management strategy. Use
|
||||
`--mm:refc` for a transition period.
|
||||
|
||||
|
||||
@@ -929,7 +929,6 @@ type
|
||||
allUsages*: seq[TLineInfo]
|
||||
|
||||
TTypeSeq* = seq[PType]
|
||||
TLockLevel* = distinct int16
|
||||
|
||||
TTypeAttachedOp* = enum ## as usual, order is important here
|
||||
attachedDestructor,
|
||||
@@ -963,7 +962,6 @@ type
|
||||
# -1 means that the size is unkwown
|
||||
align*: int16 # the type's alignment requirements
|
||||
paddingAtEnd*: int16 #
|
||||
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
||||
loc*: TLoc
|
||||
typeInst*: PType # for generic instantiations the tyGenericInst that led to this
|
||||
# type.
|
||||
@@ -1499,17 +1497,9 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
|
||||
pragmas, exceptions, body]
|
||||
|
||||
const
|
||||
UnspecifiedLockLevel* = TLockLevel(-1'i16)
|
||||
MaxLockLevel* = 1000'i16
|
||||
UnknownLockLevel* = TLockLevel(1001'i16)
|
||||
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
|
||||
"=destroy", "=copy", "=sink", "=trace", "=deepcopy"]
|
||||
|
||||
proc `$`*(x: TLockLevel): string =
|
||||
if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"
|
||||
elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
|
||||
else: result = $int16(x)
|
||||
|
||||
proc `$`*(s: PSym): string =
|
||||
if s != nil:
|
||||
result = s.name.s & "@" & $s.id
|
||||
@@ -1519,7 +1509,6 @@ proc `$`*(s: PSym): string =
|
||||
proc newType*(kind: TTypeKind, id: ItemId; owner: PSym): PType =
|
||||
result = PType(kind: kind, owner: owner, size: defaultSize,
|
||||
align: defaultAlignment, itemId: id,
|
||||
lockLevel: UnspecifiedLockLevel,
|
||||
uniqueId: id)
|
||||
when false:
|
||||
if result.itemId.module == 55 and result.itemId.item == 2:
|
||||
@@ -1544,7 +1533,6 @@ proc assignType*(dest, src: PType) =
|
||||
dest.n = src.n
|
||||
dest.size = src.size
|
||||
dest.align = src.align
|
||||
dest.lockLevel = src.lockLevel
|
||||
# this fixes 'type TLock = TSysLock':
|
||||
if src.sym != nil:
|
||||
if dest.sym != nil:
|
||||
|
||||
@@ -147,23 +147,6 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
|
||||
disp.ast[resultPos].kind == nkEmpty:
|
||||
disp.ast[resultPos] = copyTree(meth.ast[resultPos])
|
||||
|
||||
# The following code works only with lock levels, so we disable
|
||||
# it when they're not available.
|
||||
when declared(TLockLevel):
|
||||
proc `<`(a, b: TLockLevel): bool {.borrow.}
|
||||
proc `==`(a, b: TLockLevel): bool {.borrow.}
|
||||
if disp.typ.lockLevel == UnspecifiedLockLevel:
|
||||
disp.typ.lockLevel = meth.typ.lockLevel
|
||||
elif meth.typ.lockLevel != UnspecifiedLockLevel and
|
||||
meth.typ.lockLevel != disp.typ.lockLevel:
|
||||
message(conf, meth.info, warnLockLevel,
|
||||
"method has lock level $1, but another method has $2" %
|
||||
[$meth.typ.lockLevel, $disp.typ.lockLevel])
|
||||
# XXX The following code silences a duplicate warning in
|
||||
# checkMethodeffects() in sempass2.nim for now.
|
||||
if disp.typ.lockLevel < meth.typ.lockLevel:
|
||||
disp.typ.lockLevel = meth.typ.lockLevel
|
||||
|
||||
proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym) =
|
||||
var witness: PSym
|
||||
for i in 0..<g.methods.len:
|
||||
|
||||
@@ -354,7 +354,7 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
|
||||
|
||||
var p = PackedType(kind: t.kind, flags: t.flags, callConv: t.callConv,
|
||||
size: t.size, align: t.align, nonUniqueId: t.itemId.item,
|
||||
paddingAtEnd: t.paddingAtEnd, lockLevel: t.lockLevel)
|
||||
paddingAtEnd: t.paddingAtEnd)
|
||||
storeNode(p, t, n)
|
||||
p.typeInst = t.typeInst.storeType(c, m)
|
||||
for kid in items t.sons:
|
||||
@@ -905,7 +905,7 @@ proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32): PType =
|
||||
result = PType(itemId: ItemId(module: si, item: t.nonUniqueId), kind: t.kind,
|
||||
flags: t.flags, size: t.size, align: t.align,
|
||||
paddingAtEnd: t.paddingAtEnd, lockLevel: t.lockLevel,
|
||||
paddingAtEnd: t.paddingAtEnd,
|
||||
uniqueId: ItemId(module: si, item: item),
|
||||
callConv: t.callConv)
|
||||
|
||||
|
||||
@@ -84,7 +84,6 @@ type
|
||||
size*: BiggestInt
|
||||
align*: int16
|
||||
paddingAtEnd*: int16
|
||||
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
||||
# not serialized: loc*: TLoc because it is backend-specific
|
||||
typeInst*: PackedItemId
|
||||
nonUniqueId*: int32
|
||||
|
||||
@@ -68,7 +68,8 @@ type
|
||||
warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode",
|
||||
warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2",
|
||||
warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor",
|
||||
warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed",
|
||||
warnLockLevel = "LockLevel", # deadcode
|
||||
warnResultShadowed = "ResultShadowed",
|
||||
warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition",
|
||||
warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores",
|
||||
warnStrictNotNil = "StrictNotNil",
|
||||
@@ -161,7 +162,7 @@ const
|
||||
warnUninit: "use explicit initialization of '$1' for clarity",
|
||||
warnGcMem: "'$1' uses GC'ed memory",
|
||||
warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
|
||||
warnLockLevel: "$1",
|
||||
warnLockLevel: "$1", # deadcode
|
||||
warnResultShadowed: "Special variable 'result' is shadowed.",
|
||||
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
|
||||
warnCaseTransition: "Potential object case transition, instantiate new object instead",
|
||||
|
||||
@@ -294,7 +294,6 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
of cmdDoc0: docLikeCmd commandDoc(cache, conf)
|
||||
of cmdDoc:
|
||||
docLikeCmd():
|
||||
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
|
||||
conf.setNoteDefaults(warnRstRedefinitionOfLabel, false) # issue #13218
|
||||
# because currently generates lots of false positives due to conflation
|
||||
# of labels links in doc comments, e.g. for random.rand:
|
||||
|
||||
@@ -684,23 +684,6 @@ proc pragmaLockStmt(c: PContext; it: PNode) =
|
||||
for i in 0..<n.len:
|
||||
n[i] = c.semExpr(c, n[i])
|
||||
|
||||
proc pragmaLocks(c: PContext, it: PNode): TLockLevel =
|
||||
if it.kind notin nkPragmaCallKinds or it.len != 2:
|
||||
invalidPragma(c, it)
|
||||
else:
|
||||
case it[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
if it[1].strVal == "unknown":
|
||||
result = UnknownLockLevel
|
||||
else:
|
||||
localError(c.config, it[1].info, "invalid string literal for locks pragma (only allowed string is \"unknown\")")
|
||||
else:
|
||||
let x = expectIntLit(c, it)
|
||||
if x < 0 or x > MaxLockLevel:
|
||||
localError(c.config, it[1].info, "integer must be within 0.." & $MaxLockLevel)
|
||||
else:
|
||||
result = TLockLevel(x)
|
||||
|
||||
proc typeBorrow(c: PContext; sym: PSym, n: PNode) =
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||
let it = n[1]
|
||||
@@ -1196,7 +1179,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wLocks:
|
||||
if sym == nil: pragmaLockStmt(c, it)
|
||||
elif sym.typ == nil: invalidPragma(c, it)
|
||||
else: sym.typ.lockLevel = pragmaLocks(c, it)
|
||||
else: warningDeprecated(c.config, n.info, "'Lock levels' are deprecated, now a noop")
|
||||
of wBitsize:
|
||||
if sym == nil or sym.kind != skField:
|
||||
invalidPragma(c, it)
|
||||
|
||||
@@ -149,9 +149,6 @@ proc effectProblem(f, a: PType; result: var string; c: PContext) =
|
||||
of efTagsUnknown:
|
||||
result.add "\n The `.tags` requirements differ. Annotate the " &
|
||||
"proc with {.tags: [].} to get extended error information."
|
||||
of efLockLevelsDiffer:
|
||||
result.add "\n The `.locks` requirements differ. Annotate the " &
|
||||
"proc with {.locks: 0.} to get extended error information."
|
||||
of efEffectsDelayed:
|
||||
result.add "\n The `.effectsOf` annotations differ."
|
||||
of efTagsIllegal:
|
||||
|
||||
@@ -77,7 +77,6 @@ type
|
||||
gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool
|
||||
hasDangerousAssign, isInnerProc: bool
|
||||
inEnforcedNoSideEffects: bool
|
||||
maxLockLevel, currLockLevel: TLockLevel
|
||||
currOptions: TOptions
|
||||
config: ConfigRef
|
||||
graph: ModuleGraph
|
||||
@@ -85,11 +84,6 @@ type
|
||||
escapingParams: IntSet
|
||||
PEffects = var TEffects
|
||||
|
||||
proc `<`(a, b: TLockLevel): bool {.borrow.}
|
||||
proc `<=`(a, b: TLockLevel): bool {.borrow.}
|
||||
proc `==`(a, b: TLockLevel): bool {.borrow.}
|
||||
proc max(a, b: TLockLevel): TLockLevel {.borrow.}
|
||||
|
||||
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
|
||||
if typ == nil: return
|
||||
when false:
|
||||
@@ -107,33 +101,12 @@ proc isLocalVar(a: PEffects, s: PSym): bool =
|
||||
s.typ != nil and (s.kind in {skVar, skResult} or (s.kind == skParam and isOutParam(s.typ))) and
|
||||
sfGlobal notin s.flags and s.owner == a.owner
|
||||
|
||||
proc getLockLevel(t: PType): TLockLevel =
|
||||
var t = t
|
||||
# tyGenericInst(TLock {tyGenericBody}, tyStatic, tyObject):
|
||||
if t.kind == tyGenericInst and t.len == 3: t = t[1]
|
||||
if t.kind == tyStatic and t.n != nil and t.n.kind in {nkCharLit..nkInt64Lit}:
|
||||
result = t.n.intVal.TLockLevel
|
||||
|
||||
proc lockLocations(a: PEffects; pragma: PNode) =
|
||||
if pragma.kind != nkExprColonExpr:
|
||||
localError(a.config, pragma.info, "locks pragma without argument")
|
||||
return
|
||||
var firstLL = TLockLevel(-1'i16)
|
||||
for x in pragma[1]:
|
||||
let thisLL = getLockLevel(x.typ)
|
||||
if thisLL != 0.TLockLevel:
|
||||
if thisLL < 0.TLockLevel or thisLL > MaxLockLevel.TLockLevel:
|
||||
localError(a.config, x.info, "invalid lock level: " & $thisLL)
|
||||
elif firstLL < 0.TLockLevel: firstLL = thisLL
|
||||
elif firstLL != thisLL:
|
||||
localError(a.config, x.info,
|
||||
"multi-lock requires the same static lock level for every operand")
|
||||
a.maxLockLevel = max(a.maxLockLevel, firstLL)
|
||||
a.locked.add x
|
||||
if firstLL >= 0.TLockLevel and firstLL != a.currLockLevel:
|
||||
if a.currLockLevel > 0.TLockLevel and a.currLockLevel <= firstLL:
|
||||
localError(a.config, pragma.info, "invalid nested locking")
|
||||
a.currLockLevel = firstLL
|
||||
|
||||
proc guardGlobal(a: PEffects; n: PNode; guard: PSym) =
|
||||
# check whether the corresponding lock is held:
|
||||
@@ -438,8 +411,6 @@ proc listEffects(a: PEffects) =
|
||||
for e in items(a.exc): message(a.config, e.info, hintUser, typeToString(e.typ))
|
||||
for e in items(a.tags): message(a.config, e.info, hintUser, typeToString(e.typ))
|
||||
for e in items(a.forbids): message(a.config, e.info, hintUser, typeToString(e.typ))
|
||||
#if a.maxLockLevel != 0:
|
||||
# message(e.info, hintUser, "lockLevel: " & a.maxLockLevel)
|
||||
|
||||
proc catches(tracked: PEffects, e: PType) =
|
||||
let e = skipTypes(e, skipPtrs)
|
||||
@@ -551,25 +522,6 @@ proc importedFromC(n: PNode): bool =
|
||||
# when imported from C, we assume GC-safety.
|
||||
result = n.kind == nkSym and sfImportc in n.sym.flags
|
||||
|
||||
proc getLockLevel(s: PSym): TLockLevel =
|
||||
result = s.typ.lockLevel
|
||||
if result == UnspecifiedLockLevel:
|
||||
if {sfImportc, sfNoSideEffect} * s.flags != {} or
|
||||
tfNoSideEffect in s.typ.flags:
|
||||
result = 0.TLockLevel
|
||||
else:
|
||||
result = UnknownLockLevel
|
||||
#message(??.config, s.info, warnUser, "FOR THIS " & s.name.s)
|
||||
|
||||
proc mergeLockLevels(tracked: PEffects, n: PNode, lockLevel: TLockLevel) =
|
||||
if lockLevel >= tracked.currLockLevel:
|
||||
# if in lock section:
|
||||
if tracked.currLockLevel > 0.TLockLevel:
|
||||
localError tracked.config, n.info, errGenerated,
|
||||
"expected lock level < " & $tracked.currLockLevel &
|
||||
" but got lock level " & $lockLevel
|
||||
tracked.maxLockLevel = max(tracked.maxLockLevel, lockLevel)
|
||||
|
||||
proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
|
||||
let pragma = s.ast[pragmasPos]
|
||||
let spec = effectSpec(pragma, wRaises)
|
||||
@@ -583,7 +535,6 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
|
||||
markGcUnsafe(tracked, s)
|
||||
if tfNoSideEffect notin s.typ.flags:
|
||||
markSideEffect(tracked, s, n.info)
|
||||
mergeLockLevels(tracked, n, s.getLockLevel)
|
||||
|
||||
proc procVarCheck(n: PNode; conf: ConfigRef) =
|
||||
if n.kind in nkSymChoices:
|
||||
@@ -623,11 +574,6 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
proc assumeTheWorst(tracked: PEffects; n: PNode; op: PType) =
|
||||
addRaiseEffect(tracked, createRaise(tracked.graph, n), nil)
|
||||
addTag(tracked, createTag(tracked.graph, n), nil)
|
||||
let lockLevel = if op.lockLevel == UnspecifiedLockLevel: UnknownLockLevel
|
||||
else: op.lockLevel
|
||||
#if lockLevel == UnknownLockLevel:
|
||||
# message(??.config, n.info, warnUser, "had to assume the worst here")
|
||||
mergeLockLevels(tracked, n, lockLevel)
|
||||
|
||||
proc isOwnedProcVar(tracked: PEffects; n: PNode): bool =
|
||||
# XXX prove the soundness of this effect system rule
|
||||
@@ -885,10 +831,9 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
if a.kind == nkSym:
|
||||
if a.sym == tracked.owner: tracked.isRecursive = true
|
||||
# even for recursive calls we need to check the lock levels (!):
|
||||
mergeLockLevels(tracked, n, a.sym.getLockLevel)
|
||||
if sfSideEffect in a.sym.flags: markSideEffect(tracked, a, n.info)
|
||||
else:
|
||||
mergeLockLevels(tracked, n, op.lockLevel)
|
||||
discard
|
||||
var effectList = op.n[0]
|
||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
@@ -967,7 +912,6 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
type
|
||||
PragmaBlockContext = object
|
||||
oldLocked: int
|
||||
oldLockLevel: TLockLevel
|
||||
enforcedGcSafety, enforceNoSideEffects: bool
|
||||
oldExc, oldTags, oldForbids: int
|
||||
exc, tags, forbids: PNode
|
||||
@@ -976,7 +920,6 @@ proc createBlockContext(tracked: PEffects): PragmaBlockContext =
|
||||
var oldForbidsLen = 0
|
||||
if tracked.forbids != nil: oldForbidsLen = tracked.forbids.len
|
||||
result = PragmaBlockContext(oldLocked: tracked.locked.len,
|
||||
oldLockLevel: tracked.currLockLevel,
|
||||
enforcedGcSafety: false, enforceNoSideEffects: false,
|
||||
oldExc: tracked.exc.len, oldTags: tracked.tags.len,
|
||||
oldForbids: oldForbidsLen)
|
||||
@@ -989,7 +932,6 @@ proc unapplyBlockContext(tracked: PEffects; bc: PragmaBlockContext) =
|
||||
if bc.enforcedGcSafety: tracked.inEnforcedGcSafe = false
|
||||
if bc.enforceNoSideEffects: tracked.inEnforcedNoSideEffects = false
|
||||
setLen(tracked.locked, bc.oldLocked)
|
||||
tracked.currLockLevel = bc.oldLockLevel
|
||||
if bc.exc != nil:
|
||||
# beware that 'raises: []' is very different from not saying
|
||||
# anything about 'raises' in the 'cast' at all. Same applies for 'tags'.
|
||||
@@ -1396,17 +1338,6 @@ proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
|
||||
localError(g.config, branch.info, "for method '" & branch.name.s &
|
||||
"' the `.requires` or `.ensures` properties are incompatible.")
|
||||
|
||||
if branch.typ.lockLevel > disp.typ.lockLevel:
|
||||
when true:
|
||||
message(g.config, branch.info, warnLockLevel,
|
||||
"base method has lock level $1, but dispatcher has $2" %
|
||||
[$branch.typ.lockLevel, $disp.typ.lockLevel])
|
||||
else:
|
||||
# XXX make this an error after bigbreak has been released:
|
||||
localError(g.config, branch.info,
|
||||
"base method has lock level $1, but dispatcher has $2" %
|
||||
[$branch.typ.lockLevel, $disp.typ.lockLevel])
|
||||
|
||||
proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode; s: PSym = nil) =
|
||||
var effects = t.n[0]
|
||||
if t.kind != tyProc or effects.kind != nkEffectList: return
|
||||
@@ -1592,13 +1523,6 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
s.typ.flags.incl tfGcSafe
|
||||
if not t.hasSideEffect and sfSideEffect notin s.flags:
|
||||
s.typ.flags.incl tfNoSideEffect
|
||||
if s.typ.lockLevel == UnspecifiedLockLevel:
|
||||
s.typ.lockLevel = t.maxLockLevel
|
||||
elif t.maxLockLevel > s.typ.lockLevel:
|
||||
#localError(s.info,
|
||||
message(g.config, s.info, warnLockLevel,
|
||||
"declared lock level is $1, but real lock level is $2" %
|
||||
[$s.typ.lockLevel, $t.maxLockLevel])
|
||||
when defined(drnim):
|
||||
if c.graph.strongSemCheck != nil: c.graph.strongSemCheck(c.graph, s, body)
|
||||
when defined(useDfa):
|
||||
|
||||
@@ -1595,10 +1595,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
c.inheritancePenalty = 0
|
||||
let x = typeRel(c, branch, aOrig, flags)
|
||||
maxInheritance = max(maxInheritance, c.inheritancePenalty)
|
||||
|
||||
# 'or' implies maximum matching result:
|
||||
if x > result: result = x
|
||||
if result >= isSubtype:
|
||||
if result >= isIntConv:
|
||||
if result > isGeneric: result = isGeneric
|
||||
bindingRet result
|
||||
else:
|
||||
|
||||
@@ -48,7 +48,6 @@ type
|
||||
ProcConvMismatch* = enum
|
||||
pcmNoSideEffect
|
||||
pcmNotGcSafe
|
||||
pcmLockDifference
|
||||
pcmNotIterator
|
||||
pcmDifferentCallConv
|
||||
|
||||
@@ -728,9 +727,6 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
if tfThread in t.flags:
|
||||
addSep(prag)
|
||||
prag.add("gcsafe")
|
||||
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
|
||||
addSep(prag)
|
||||
prag.add("locks: " & $t.lockLevel)
|
||||
if prag.len != 0: result.add("{." & prag & ".}")
|
||||
of tyVarargs:
|
||||
result = typeToStr[t.kind] % typeToString(t[0])
|
||||
@@ -1386,7 +1382,6 @@ type
|
||||
efRaisesUnknown
|
||||
efTagsDiffer
|
||||
efTagsUnknown
|
||||
efLockLevelsDiffer
|
||||
efEffectsDelayed
|
||||
efTagsIllegal
|
||||
|
||||
@@ -1430,17 +1425,13 @@ proc compatibleEffects*(formal, actual: PType): EffectsCompat =
|
||||
elif hasIncompatibleEffect(sn, real[tagEffects]):
|
||||
return efTagsIllegal
|
||||
|
||||
if formal.lockLevel.ord < 0 or
|
||||
actual.lockLevel.ord <= formal.lockLevel.ord:
|
||||
for i in 1 ..< min(formal.n.len, actual.n.len):
|
||||
if formal.n[i].sym.flags * {sfEffectsDelayed} != actual.n[i].sym.flags * {sfEffectsDelayed}:
|
||||
result = efEffectsDelayed
|
||||
break
|
||||
|
||||
for i in 1 ..< min(formal.n.len, actual.n.len):
|
||||
if formal.n[i].sym.flags * {sfEffectsDelayed} != actual.n[i].sym.flags * {sfEffectsDelayed}:
|
||||
result = efEffectsDelayed
|
||||
break
|
||||
result = efCompat
|
||||
|
||||
result = efCompat
|
||||
else:
|
||||
result = efLockLevelsDiffer
|
||||
|
||||
proc isCompileTimeOnly*(t: PType): bool {.inline.} =
|
||||
result = t.kind in {tyTypeDesc, tyStatic}
|
||||
@@ -1577,13 +1568,6 @@ proc getProcConvMismatch*(c: ConfigRef, f, a: PType, rel = isNone): (set[ProcCon
|
||||
result[1] = isNone
|
||||
result[0].incl pcmDifferentCallConv
|
||||
|
||||
if f.lockLevel.ord != UnspecifiedLockLevel.ord and
|
||||
a.lockLevel.ord != UnspecifiedLockLevel.ord:
|
||||
# proctypeRel has more logic to catch this difference,
|
||||
# so dont need to do `rel = isNone`
|
||||
# but it's a pragma mismatch reason which is why it's here
|
||||
result[0].incl pcmLockDifference
|
||||
|
||||
proc addPragmaAndCallConvMismatch*(message: var string, formal, actual: PType, conf: ConfigRef) =
|
||||
assert formal.kind == tyProc and actual.kind == tyProc
|
||||
let (convMismatch, _) = getProcConvMismatch(conf, formal, actual)
|
||||
@@ -1598,9 +1582,6 @@ proc addPragmaAndCallConvMismatch*(message: var string, formal, actual: PType, c
|
||||
expectedPragmas.add "noSideEffect, "
|
||||
of pcmNotGcSafe:
|
||||
expectedPragmas.add "gcsafe, "
|
||||
of pcmLockDifference:
|
||||
gotPragmas.add("locks: " & $actual.lockLevel & ", ")
|
||||
expectedPragmas.add("locks: " & $formal.lockLevel & ", ")
|
||||
of pcmNotIterator: discard
|
||||
|
||||
if expectedPragmas.len > 0:
|
||||
@@ -1621,8 +1602,6 @@ proc processPragmaAndCallConvMismatch(msg: var string, formal, actual: PType, co
|
||||
msg.add "\n.tag effects differ"
|
||||
of efTagsUnknown:
|
||||
msg.add "\n.tag effect is 'any tag allowed'"
|
||||
of efLockLevelsDiffer:
|
||||
msg.add "\nlock levels differ"
|
||||
of efEffectsDelayed:
|
||||
msg.add "\n.effectsOf annotations differ"
|
||||
of efTagsIllegal:
|
||||
|
||||
@@ -1817,105 +1817,6 @@ restrictions / changes:
|
||||
yet performed for ordinary slices outside of a `parallel` section.
|
||||
|
||||
|
||||
|
||||
Lock levels
|
||||
===========
|
||||
|
||||
Lock levels are used to enforce a global locking order in order to detect
|
||||
potential deadlocks during semantic analysis. A lock level is an constant
|
||||
integer in the range 0..1_000. Lock level 0 means that no lock is acquired at
|
||||
all.
|
||||
|
||||
If a section of code holds a lock of level `M`, it can also acquire any
|
||||
lock of level `N < M`. Another lock of level `M` cannot be acquired. Locks
|
||||
of the same level can only be acquired *at the same time* within a
|
||||
single `locks` section:
|
||||
|
||||
```nim
|
||||
var a, b: TLock[2]
|
||||
var x: TLock[1]
|
||||
# invalid locking order: TLock[1] cannot be acquired before TLock[2]:
|
||||
{.locks: [x].}:
|
||||
{.locks: [a].}:
|
||||
...
|
||||
# valid locking order: TLock[2] acquired before TLock[1]:
|
||||
{.locks: [a].}:
|
||||
{.locks: [x].}:
|
||||
...
|
||||
|
||||
# invalid locking order: TLock[2] acquired before TLock[2]:
|
||||
{.locks: [a].}:
|
||||
{.locks: [b].}:
|
||||
...
|
||||
|
||||
# valid locking order, locks of the same level acquired at the same time:
|
||||
{.locks: [a, b].}:
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
Here is how a typical multilock statement can be implemented in Nim. Note how
|
||||
the runtime check is required to ensure a global ordering for two locks `a`
|
||||
and `b` of the same lock level:
|
||||
|
||||
```nim
|
||||
template multilock(a, b: ptr TLock; body: untyped) =
|
||||
if cast[ByteAddress](a) < cast[ByteAddress](b):
|
||||
pthread_mutex_lock(a)
|
||||
pthread_mutex_lock(b)
|
||||
else:
|
||||
pthread_mutex_lock(b)
|
||||
pthread_mutex_lock(a)
|
||||
{.locks: [a, b].}:
|
||||
try:
|
||||
body
|
||||
finally:
|
||||
pthread_mutex_unlock(a)
|
||||
pthread_mutex_unlock(b)
|
||||
```
|
||||
|
||||
|
||||
Whole routines can also be annotated with a `locks` pragma that takes a lock
|
||||
level. This then means that the routine may acquire locks of up to this level.
|
||||
This is essential so that procs can be called within a `locks` section:
|
||||
|
||||
```nim
|
||||
proc p() {.locks: 3.} = discard
|
||||
|
||||
var a: TLock[4]
|
||||
{.locks: [a].}:
|
||||
# p's locklevel (3) is strictly less than a's (4) so the call is allowed:
|
||||
p()
|
||||
```
|
||||
|
||||
|
||||
As usual, `locks` is an inferred effect and there is a subtype
|
||||
relation: `proc () {.locks: N.}` is a subtype of `proc () {.locks: M.}`
|
||||
iff (M <= N).
|
||||
|
||||
The `locks` pragma can also take the special value `"unknown"`. This
|
||||
is useful in the context of dynamic method dispatching. In the following
|
||||
example, the compiler can infer a lock level of 0 for the `base` case.
|
||||
However, one of the overloaded methods calls a procvar which is
|
||||
potentially locking. Thus, the lock level of calling `g.testMethod`
|
||||
cannot be inferred statically, leading to compiler warnings. By using
|
||||
`{.locks: "unknown".}`, the base method can be marked explicitly as
|
||||
having unknown lock level as well:
|
||||
|
||||
```nim
|
||||
type SomeBase* = ref object of RootObj
|
||||
type SomeDerived* = ref object of SomeBase
|
||||
memberProc*: proc ()
|
||||
|
||||
method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
|
||||
method testMethod(g: SomeDerived) =
|
||||
if g.memberProc != nil:
|
||||
g.memberProc()
|
||||
```
|
||||
|
||||
This feature may be removed in the future due to its practical difficulties.
|
||||
|
||||
|
||||
Strict definitions and `out` parameters
|
||||
=======================================
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ Ast Pattern Matching is a macro library to aid in writing complex
|
||||
macros. This can be seen as a good example of how to repurpose the
|
||||
Nim syntax tree with new semantics.
|
||||
|
||||
[Ast Pattern Matching](https://github.com/krux02/ast-pattern-matching)
|
||||
[Ast Pattern Matching](https://github.com/nim-lang/ast-pattern-matching)
|
||||
|
||||
OpenGL Sandbox
|
||||
--------------
|
||||
|
||||
4
koch.nim
4
koch.nim
@@ -142,7 +142,7 @@ proc csource(args: string) =
|
||||
proc bundleC2nim(args: string) =
|
||||
cloneDependency(distDir, "https://github.com/nim-lang/c2nim.git")
|
||||
nimCompile("dist/c2nim/c2nim",
|
||||
options = "--noNimblePath --useVersion:1.6 --path:. " & args)
|
||||
options = "--noNimblePath --path:. " & args)
|
||||
|
||||
proc bundleNimbleExe(latest: bool, args: string) =
|
||||
let commit = if latest: "HEAD" else: NimbleStableCommit
|
||||
@@ -150,7 +150,7 @@ proc bundleNimbleExe(latest: bool, args: string) =
|
||||
commit = commit, allowBundled = true)
|
||||
# installer.ini expects it under $nim/bin
|
||||
nimCompile("dist/nimble/src/nimble.nim",
|
||||
options = "-d:release --mm:refc --useVersion:1.6 --noNimblePath " & args)
|
||||
options = "-d:release --mm:refc --noNimblePath " & args)
|
||||
|
||||
proc bundleNimsuggest(args: string) =
|
||||
nimCompileFold("Compile nimsuggest", "nimsuggest/nimsuggest.nim",
|
||||
|
||||
@@ -215,12 +215,12 @@ template `or`*(x, y: NimNode): NimNode =
|
||||
y
|
||||
|
||||
proc add*(father, child: NimNode): NimNode {.magic: "NAdd", discardable,
|
||||
noSideEffect, locks: 0.}
|
||||
noSideEffect.}
|
||||
## Adds the `child` to the `father` node. Returns the
|
||||
## father node so that calls can be nested.
|
||||
|
||||
proc add*(father: NimNode, children: varargs[NimNode]): NimNode {.
|
||||
magic: "NAddMultiple", discardable, noSideEffect, locks: 0.}
|
||||
magic: "NAddMultiple", discardable, noSideEffect.}
|
||||
## Adds each child of `children` to the `father` node.
|
||||
## Returns the `father` node so that calls can be nested.
|
||||
|
||||
|
||||
@@ -1025,7 +1025,7 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
|
||||
proc acceptAddr*(server: Socket, client: var owned(Socket), address: var string,
|
||||
flags = {SocketFlag.SafeDisconn},
|
||||
inheritable = defined(nimInheritHandles)) {.
|
||||
tags: [ReadIOEffect], gcsafe, locks: 0.} =
|
||||
tags: [ReadIOEffect], gcsafe.} =
|
||||
## Blocks until a connection is being made from a client. When a connection
|
||||
## is made sets `client` to the client socket and `address` to the address
|
||||
## of the connecting client.
|
||||
|
||||
@@ -122,13 +122,13 @@ when defined(memProfiler):
|
||||
var
|
||||
gTicker {.threadvar.}: int
|
||||
|
||||
proc requestedHook(): bool {.nimcall, locks: 0.} =
|
||||
proc requestedHook(): bool {.nimcall.} =
|
||||
if gTicker == 0:
|
||||
gTicker = SamplingInterval
|
||||
result = true
|
||||
dec gTicker
|
||||
|
||||
proc hook(st: StackTrace, size: int) {.nimcall, locks: 0.} =
|
||||
proc hook(st: StackTrace, size: int) {.nimcall.} =
|
||||
when defined(ignoreAllocationSize):
|
||||
hookAux(st, 1)
|
||||
else:
|
||||
@@ -140,7 +140,7 @@ else:
|
||||
gTicker: int # we use an additional counter to
|
||||
# avoid calling 'getTicks' too frequently
|
||||
|
||||
proc requestedHook(): bool {.nimcall, locks: 0.} =
|
||||
proc requestedHook(): bool {.nimcall.} =
|
||||
if interval == 0: result = true
|
||||
elif gTicker == 0:
|
||||
gTicker = 500
|
||||
@@ -149,7 +149,7 @@ else:
|
||||
else:
|
||||
dec gTicker
|
||||
|
||||
proc hook(st: StackTrace) {.nimcall, locks: 0.} =
|
||||
proc hook(st: StackTrace) {.nimcall.} =
|
||||
#echo "profiling! ", interval
|
||||
if interval == 0:
|
||||
hookAux(st, 1)
|
||||
|
||||
@@ -34,7 +34,7 @@ template sbind(x: int; value) =
|
||||
quit "could not bind value"
|
||||
|
||||
when defined(memTracker):
|
||||
proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [], gcsafe.} =
|
||||
proc logEntries(log: TrackLog) {.nimcall, tags: [], gcsafe.} =
|
||||
if insertStmt.isNil:
|
||||
if prepare_v2(dbHandle, insertQuery,
|
||||
insertQuery.len, insertStmt, nil) != SQLITE_OK:
|
||||
|
||||
@@ -148,7 +148,7 @@ proc thinout*[T](x: ref T) {.inline.} =
|
||||
## and thus would keep the graph from being freed are `nil`'ed.
|
||||
## This is a form of cycle collection that works well with Nim's ARC
|
||||
## and its associated cost model.
|
||||
proc getDynamicTypeInfo[T](x: T): PNimTypeV2 {.magic: "GetTypeInfoV2", noSideEffect, locks: 0.}
|
||||
proc getDynamicTypeInfo[T](x: T): PNimTypeV2 {.magic: "GetTypeInfoV2", noSideEffect.}
|
||||
|
||||
breakCycles(head(cast[pointer](x)), getDynamicTypeInfo(x[]))
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ else:
|
||||
{.pragma: inl, inline.}
|
||||
{.pragma: compilerRtl, compilerproc.}
|
||||
|
||||
{.pragma: benign, gcsafe, locks: 0.}
|
||||
{.pragma: benign, gcsafe.}
|
||||
|
||||
when defined(nimHasSinkInference):
|
||||
{.push sinkInference: on.}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
when notJSnotNims:
|
||||
proc zeroMem*(p: pointer, size: Natural) {.inline, noSideEffect,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
tags: [], raises: [].}
|
||||
## Overwrites the contents of the memory at `p` with the value 0.
|
||||
##
|
||||
## Exactly `size` bytes will be overwritten. Like any procedure
|
||||
## dealing with raw memory this is **unsafe**.
|
||||
|
||||
proc copyMem*(dest, source: pointer, size: Natural) {.inline, benign,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
tags: [], raises: [].}
|
||||
## Copies the contents from the memory at `source` to the memory
|
||||
## at `dest`.
|
||||
## Exactly `size` bytes will be copied. The memory
|
||||
@@ -15,7 +15,7 @@ when notJSnotNims:
|
||||
## memory this is **unsafe**.
|
||||
|
||||
proc moveMem*(dest, source: pointer, size: Natural) {.inline, benign,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
tags: [], raises: [].}
|
||||
## Copies the contents from the memory at `source` to the memory
|
||||
## at `dest`.
|
||||
##
|
||||
@@ -25,7 +25,7 @@ when notJSnotNims:
|
||||
## dealing with raw memory this is still **unsafe**, though.
|
||||
|
||||
proc equalMem*(a, b: pointer, size: Natural): bool {.inline, noSideEffect,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
tags: [], raises: [].}
|
||||
## Compares the memory blocks `a` and `b`. `size` bytes will
|
||||
## be compared.
|
||||
##
|
||||
@@ -34,7 +34,7 @@ when notJSnotNims:
|
||||
## **unsafe**.
|
||||
|
||||
proc cmpMem*(a, b: pointer, size: Natural): int {.inline, noSideEffect,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
tags: [], raises: [].}
|
||||
## Compares the memory blocks `a` and `b`. `size` bytes will
|
||||
## be compared.
|
||||
##
|
||||
|
||||
@@ -35,7 +35,7 @@ type
|
||||
count*: int
|
||||
disabled: bool
|
||||
data*: array[400, LogEntry]
|
||||
TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0, gcsafe.}
|
||||
TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], gcsafe.}
|
||||
|
||||
var
|
||||
gLog*: TrackLog
|
||||
@@ -70,7 +70,7 @@ proc addEntry(entry: LogEntry) =
|
||||
if interesting:
|
||||
gLog.disabled = true
|
||||
cprintf("interesting %s:%ld %s\n", entry.file, entry.line, entry.op)
|
||||
let x = cast[proc() {.nimcall, tags: [], gcsafe, locks: 0, raises: [].}](writeStackTrace)
|
||||
let x = cast[proc() {.nimcall, tags: [], gcsafe, raises: [].}](writeStackTrace)
|
||||
x()
|
||||
quit 1
|
||||
#if gLog.count > high(gLog.data):
|
||||
@@ -85,7 +85,7 @@ proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.co
|
||||
size: size, file: file, line: line, thread: myThreadId())
|
||||
|
||||
proc memTrackerOp*(op: cstring; address: pointer; size: int) {.tags: [],
|
||||
locks: 0, gcsafe.} =
|
||||
gcsafe.} =
|
||||
addEntry LogEntry(op: op, address: address, size: size,
|
||||
file: "", line: 0, thread: myThreadId())
|
||||
|
||||
|
||||
@@ -60,13 +60,13 @@ proc captureStackTrace(f: PFrame, st: var StackTrace) =
|
||||
b = b.prev
|
||||
|
||||
var
|
||||
profilingRequestedHook*: proc (): bool {.nimcall, locks: 0, gcsafe.}
|
||||
profilingRequestedHook*: proc (): bool {.nimcall, gcsafe.}
|
||||
## set this variable to provide a procedure that implements a profiler in
|
||||
## user space. See the `nimprof` module for a reference implementation.
|
||||
|
||||
when defined(memProfiler):
|
||||
type
|
||||
MemProfilerHook* = proc (st: StackTrace, requestedSize: int) {.nimcall, locks: 0, gcsafe.}
|
||||
MemProfilerHook* = proc (st: StackTrace, requestedSize: int) {.nimcall, gcsafe.}
|
||||
|
||||
var
|
||||
profilerHook*: MemProfilerHook
|
||||
|
||||
@@ -22,26 +22,26 @@ when defined(nimStackTraceOverride):
|
||||
## This is the same as the type `uintptr_t` in C.
|
||||
|
||||
StackTraceOverrideGetTracebackProc* = proc (): string {.
|
||||
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
|
||||
nimcall, gcsafe, raises: [], tags: [], noinline.}
|
||||
StackTraceOverrideGetProgramCountersProc* = proc (maxLength: cint): seq[cuintptr_t] {.
|
||||
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
|
||||
nimcall, gcsafe, raises: [], tags: [], noinline.}
|
||||
StackTraceOverrideGetDebuggingInfoProc* =
|
||||
proc (programCounters: seq[cuintptr_t], maxLength: cint): seq[StackTraceEntry] {.
|
||||
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.}
|
||||
nimcall, gcsafe, raises: [], tags: [], noinline.}
|
||||
|
||||
# Default procedures (not normally used, because people opting in on this
|
||||
# override are supposed to register their own versions).
|
||||
var
|
||||
stackTraceOverrideGetTraceback: StackTraceOverrideGetTracebackProc =
|
||||
proc (): string {.nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
|
||||
proc (): string {.nimcall, gcsafe, raises: [], tags: [], noinline.} =
|
||||
discard
|
||||
#result = "Stack trace override procedure not registered.\n"
|
||||
stackTraceOverrideGetProgramCounters: StackTraceOverrideGetProgramCountersProc =
|
||||
proc (maxLength: cint): seq[cuintptr_t] {.nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
|
||||
proc (maxLength: cint): seq[cuintptr_t] {.nimcall, gcsafe, raises: [], tags: [], noinline.} =
|
||||
discard
|
||||
stackTraceOverrideGetDebuggingInfo: StackTraceOverrideGetDebuggingInfoProc =
|
||||
proc (programCounters: seq[cuintptr_t], maxLength: cint): seq[StackTraceEntry] {.
|
||||
nimcall, gcsafe, locks: 0, raises: [], tags: [], noinline.} =
|
||||
nimcall, gcsafe, raises: [], tags: [], noinline.} =
|
||||
discard
|
||||
|
||||
# Custom procedure registration.
|
||||
|
||||
@@ -121,7 +121,7 @@ type
|
||||
|
||||
Callback* = proc (para1: pointer, para2: int32, para3,
|
||||
para4: cstringArray): int32{.cdecl.}
|
||||
Tbind_destructor_func* = proc (para1: pointer){.cdecl, locks: 0, tags: [], gcsafe.}
|
||||
Tbind_destructor_func* = proc (para1: pointer){.cdecl, tags: [], gcsafe.}
|
||||
Create_function_step_func* = proc (para1: Pcontext, para2: int32,
|
||||
para3: PValueArg){.cdecl.}
|
||||
Create_function_func_func* = proc (para1: Pcontext, para2: int32,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>def $1
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe.};;$file;;9;;5;;"Return hello";;100
|
||||
>def $1
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"Return hello";;100
|
||||
def;;skProc;;tdef1.hello;;proc (): string{.noSideEffect, gcsafe.};;$file;;9;;5;;"Return hello";;100
|
||||
"""
|
||||
|
||||
proc hello(): string =
|
||||
|
||||
@@ -15,7 +15,7 @@ discard """
|
||||
$nimsuggest --tester --maxresults:2 $file
|
||||
>sug $1
|
||||
sug;;skProc;;tdot4.main;;proc (inp: string): string;;$file;;6;;5;;"";;100;;None
|
||||
sug;;skFunc;;mstrutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe, locks: 0.};;*fixtures/mstrutils.nim;;9;;5;;"this is a test version of strutils.replace, it simply returns `by`";;100;;None
|
||||
sug;;skFunc;;mstrutils.replace;;proc (s: string, sub: string, by: string): string{.noSideEffect, gcsafe.};;*fixtures/mstrutils.nim;;9;;5;;"this is a test version of strutils.replace, it simply returns `by`";;100;;None
|
||||
"""
|
||||
|
||||
# TODO - determine appropriate behaviour for further suggest output and test it
|
||||
|
||||
@@ -11,7 +11,7 @@ go()
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>def $path/tinclude.nim:7:14
|
||||
def;;skProc;;minclude_import.create;;proc (greeting: string, subject: string): Greet{.noSideEffect, gcsafe, locks: 0.};;*fixtures/minclude_include.nim;;3;;5;;"";;100
|
||||
def;;skProc;;minclude_import.create;;proc (greeting: string, subject: string): Greet{.noSideEffect, gcsafe.};;*fixtures/minclude_include.nim;;3;;5;;"";;100
|
||||
>def $path/fixtures/minclude_include.nim:3:71
|
||||
def;;skType;;minclude_types.Greet;;Greet;;*fixtures/minclude_types.nim;;4;;2;;"";;100
|
||||
>def $path/fixtures/minclude_include.nim:3:71
|
||||
|
||||
@@ -6,7 +6,7 @@ tmp#[!]#
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>sug $1
|
||||
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe, locks: 0.};;$file;;2;;6;;"";;100;;Prefix
|
||||
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe.};;$file;;2;;6;;"";;100;;Prefix
|
||||
sug;;skConverter;;tsug_template.tmpc;;converter ();;$file;;3;;10;;"";;100;;Prefix
|
||||
sug;;skTemplate;;tsug_template.tmpa;;template ();;$file;;1;;9;;"";;100;;Prefix
|
||||
"""
|
||||
|
||||
@@ -14,9 +14,9 @@ proc #[!]#someProc*() =
|
||||
discard """
|
||||
$nimsuggest --tester $file
|
||||
>use $1
|
||||
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"";;100
|
||||
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;12;;0;;"";;100
|
||||
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;9;;5;;"";;100
|
||||
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;12;;0;;"";;100
|
||||
>use $2
|
||||
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;9;;5;;"";;100
|
||||
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe, locks: 0.};;$file;;12;;0;;"";;100
|
||||
def;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;9;;5;;"";;100
|
||||
use;;skProc;;tuse.someProc;;proc (){.noSideEffect, gcsafe.};;$file;;12;;0;;"";;100
|
||||
"""
|
||||
|
||||
@@ -19,11 +19,11 @@ def skField tv3.Foo.bar string $file 5 4 "" 100
|
||||
>outline $1
|
||||
outline skType tv3.Foo Foo $file 4 2 "" 100
|
||||
outline skField tv3.Foo.bar string $file 5 4 "" 100
|
||||
outline skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
|
||||
outline skProc tv3.test proc (f: Foo){.gcsafe.} $file 7 5 "" 100
|
||||
>sug $1
|
||||
sug skField bar string $file 5 4 "" 100 Prefix
|
||||
>globalSymbols test
|
||||
def skProc tv3.test proc (f: Foo){.gcsafe, locks: 0.} $file 7 5 "" 100
|
||||
def skProc tv3.test proc (f: Foo){.gcsafe.} $file 7 5 "" 100
|
||||
>globalSymbols Foo
|
||||
def skType tv3.Foo Foo $file 4 2 "" 100
|
||||
>def $2
|
||||
|
||||
@@ -7,17 +7,17 @@ let a = de#[!]#mo()
|
||||
discard """
|
||||
$nimsuggest --v3 --tester $file
|
||||
>use $1
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
|
||||
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 8 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
|
||||
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 5 8 "" 100
|
||||
>use $2
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
|
||||
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 8 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
|
||||
def skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
|
||||
use skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 5 8 "" 100
|
||||
>declaration $1
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
|
||||
>declaration $2
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
|
||||
>declaration $3
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 1 5 "" 100
|
||||
declaration skProc tv3_forward_definition.demo proc (): int{.noSideEffect, gcsafe.} $file 1 5 "" 100
|
||||
"""
|
||||
|
||||
@@ -7,8 +7,8 @@ proc BBtokenA(): int = 5
|
||||
discard """
|
||||
$nimsuggest --v3 --tester $file
|
||||
>globalSymbols token
|
||||
def skProc tv3_globalSymbols.token proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 4 5 "" 100
|
||||
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 3 5 "" 100
|
||||
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 2 5 "" 100
|
||||
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe, locks: 0.} $file 5 5 "" 100
|
||||
def skProc tv3_globalSymbols.token proc (): int{.noSideEffect, gcsafe.} $file 4 5 "" 100
|
||||
def skProc tv3_globalSymbols.tokenA proc (): int{.noSideEffect, gcsafe.} $file 3 5 "" 100
|
||||
def skProc tv3_globalSymbols.Btoken proc (): int{.noSideEffect, gcsafe.} $file 2 5 "" 100
|
||||
def skProc tv3_globalSymbols.BBtokenA proc (): int{.noSideEffect, gcsafe.} $file 5 5 "" 100
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
cmd: "nim c --gc:arc $file"
|
||||
errormsg: "type mismatch: got <proc (a: string, b: sink string){.noSideEffect, gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc (a: string, b: sink string){.noSideEffect, gcsafe.}>"
|
||||
line: 18
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe.}>"
|
||||
line: 23
|
||||
"""
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ block tclosure:
|
||||
|
||||
# bug #5015
|
||||
|
||||
type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.}
|
||||
type Mutator = proc(matched: string): string {.noSideEffect, gcsafe.}
|
||||
|
||||
proc putMutated(
|
||||
MutatorCount: static[int],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe.}>"
|
||||
line: 12
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "type mismatch: got <proc (){.closure, gcsafe, locks: 0.}> but expected 'A = proc (){.nimcall.}'"
|
||||
errormsg: "type mismatch: got <proc (){.closure, gcsafe.}> but expected 'A = proc (){.nimcall.}'"
|
||||
line: 9
|
||||
"""
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ py
|
||||
py
|
||||
px
|
||||
6
|
||||
proc (){.closure, gcsafe, locks: 0.}
|
||||
proc (){.closure, gcsafe.}
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ proc foo(x: int): string {.nimcall, raises: [ValueError].} =
|
||||
|
||||
var p: MyProcType = foo #[tt.Error
|
||||
^
|
||||
type mismatch: got <proc (x: int): string{.nimcall, noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
|
||||
type mismatch: got <proc (x: int): string{.nimcall, noSideEffect, gcsafe.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
.raise effects differ
|
||||
]#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
action: compile
|
||||
errormsg: "type mismatch: got <proc (x: int){.gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc (x: int){.gcsafe.}>"
|
||||
line: 21
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
action: compile
|
||||
errormsg: "type mismatch: got <proc (i: int){.gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc (i: int){.gcsafe.}>"
|
||||
line: 23
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: '''type mismatch: got <proc (s: string){.locks: 0.}>'''
|
||||
errormsg: '''type mismatch: got <proc (s: string)>'''
|
||||
line: 11
|
||||
"""
|
||||
#5620
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for let. Did you mean to call the macro with '()'?"
|
||||
errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe.}' for let. Did you mean to call the macro with '()'?"
|
||||
line: 9
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for const. Did you mean to call the macro with '()'?"
|
||||
errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe.}' for const. Did you mean to call the macro with '()'?"
|
||||
line: 9
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ discard """
|
||||
errormsg: ""
|
||||
nimout: '''
|
||||
t18886.nim(18, 24) Error: ambiguous identifier: 'bar' -- you need a helper proc to disambiguate the following:
|
||||
t18886.bar: proc (i: ptr int){.noSideEffect, gcsafe, locks: 0.}
|
||||
t18886.bar: proc (i: ptr char){.noSideEffect, gcsafe, locks: 0.}
|
||||
t18886.bar: proc (i: ptr int){.noSideEffect, gcsafe.}
|
||||
t18886.bar: proc (i: ptr char){.noSideEffect, gcsafe.}
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ discard """
|
||||
cmd: "nim check $options --hints:off $file"
|
||||
errormsg: ""
|
||||
nimout: '''
|
||||
t2614.nim(19, 27) Error: type mismatch: got <array[0..1, proc (){.locks: <unknown>.}]> but expected 'array[0..1, proc (){.closure.}]'
|
||||
t2614.nim(19, 27) Error: type mismatch: got <array[0..1, proc ()]> but expected 'array[0..1, proc (){.closure.}]'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
t2614.nim(21, 22) Error: type mismatch: got <seq[proc (){.locks: <unknown>.}]> but expected 'seq[proc (){.closure.}]'
|
||||
t2614.nim(21, 22) Error: type mismatch: got <seq[proc ()]> but expected 'seq[proc (){.closure.}]'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "type mismatch: got <proc [*missing parameters*](x: int) | proc (x: string){.gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <proc [*missing parameters*](x: int) | proc (x: string){.gcsafe.}>"
|
||||
line: 19
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
discard """
|
||||
cmd: "nim check $file"
|
||||
errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>"
|
||||
errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]>"
|
||||
nimout: '''
|
||||
tgcsafety.nim(31, 18) Error: type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>
|
||||
tgcsafety.nim(31, 18) Error: type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]>
|
||||
but expected one of:
|
||||
proc serve(server: AsyncHttpServer; port: Port;
|
||||
callback: proc (request: Request): Future[void] {.closure, gcsafe.};
|
||||
@@ -10,7 +10,7 @@ proc serve(server: AsyncHttpServer; port: Port;
|
||||
Future[void])
|
||||
first type mismatch at position: 3
|
||||
required type for callback: proc (request: Request): Future[system.void]{.closure, gcsafe.}
|
||||
but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.}
|
||||
but expression 'cb' is of type: proc (req: Request): Future[system.void]
|
||||
This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information.
|
||||
|
||||
expression: serve(server, Port(7898), cb)
|
||||
|
||||
@@ -3,36 +3,36 @@ discard """
|
||||
cmd: '''nim check --hints:off $options $file'''
|
||||
nimoutFull: true
|
||||
nimout: '''
|
||||
tproc_mismatch.nim(38, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}'
|
||||
tproc_mismatch.nim(38, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}'
|
||||
Calling convention mismatch: got '{.cdecl.}', but expected '{.closure.}'.
|
||||
tproc_mismatch.nim(42, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}>
|
||||
tproc_mismatch.nim(42, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe.}>
|
||||
but expected one of:
|
||||
proc bar(a: proc ())
|
||||
first type mismatch at position: 1
|
||||
required type for a: proc (){.closure.}
|
||||
but expression 'fn1' is of type: proc (){.inline, noSideEffect, gcsafe, locks: 0.}
|
||||
but expression 'fn1' is of type: proc (){.inline, noSideEffect, gcsafe.}
|
||||
Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'.
|
||||
|
||||
expression: bar(fn1)
|
||||
tproc_mismatch.nim(46, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (){.closure.}'
|
||||
tproc_mismatch.nim(46, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe.}> but expected 'proc (){.closure.}'
|
||||
Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'.
|
||||
tproc_mismatch.nim(51, 8) Error: type mismatch: got <proc (){.locks: 0.}> but expected 'proc (){.closure, noSideEffect.}'
|
||||
tproc_mismatch.nim(51, 8) Error: type mismatch: got <proc ()> but expected 'proc (){.closure, noSideEffect.}'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
Pragma mismatch: got '{..}', but expected '{.noSideEffect.}'.
|
||||
tproc_mismatch.nim(55, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: float){.closure.}'
|
||||
tproc_mismatch.nim(55, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe.}> but expected 'proc (a: float){.closure.}'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
tproc_mismatch.nim(64, 9) Error: type mismatch: got <proc (a: int){.locks: 0.}> but expected 'proc (a: int){.closure, gcsafe.}'
|
||||
tproc_mismatch.nim(64, 9) Error: type mismatch: got <proc (a: int)> but expected 'proc (a: int){.closure, gcsafe.}'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
|
||||
Pragma mismatch: got '{..}', but expected '{.gcsafe.}'.
|
||||
tproc_mismatch.nim(72, 9) Error: type mismatch: got <proc (a: int): int{.nimcall.}> but expected 'proc (a: int): int{.cdecl.}'
|
||||
Calling convention mismatch: got '{.nimcall.}', but expected '{.cdecl.}'.
|
||||
tproc_mismatch.nim(73, 9) Error: type mismatch: got <proc (a: int): int{.cdecl.}> but expected 'proc (a: int): int{.nimcall.}'
|
||||
Calling convention mismatch: got '{.cdecl.}', but expected '{.nimcall.}'.
|
||||
tproc_mismatch.nim(77, 9) Error: type mismatch: got <proc (a: int){.closure, locks: 3.}> but expected 'proc (a: int){.closure, locks: 1.}'
|
||||
Pragma mismatch: got '{.locks: 3.}', but expected '{.locks: 1.}'.
|
||||
lock levels differ
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
|
||||
block: # CallConv mismatch
|
||||
func a(a: int, c: float) {.cdecl.} = discard
|
||||
var b: proc(a: int, c: float) {.noSideEffect.} = a
|
||||
@@ -71,7 +71,4 @@ block: # Indrection through pragmas
|
||||
var fn2: proc(a: int): int {.inl2, p2.}
|
||||
fn2 = fn1
|
||||
fn1 = fn2
|
||||
block: # Lock levels differ
|
||||
var fn1: proc(a: int){.locks: 3.}
|
||||
var fn2: proc(a: int){.locks: 1.}
|
||||
fn2 = fn1
|
||||
|
||||
|
||||
@@ -12,34 +12,34 @@ proc f(b: B)
|
||||
but expression 'A()' is of type: A
|
||||
|
||||
expression: f(A(), "extra")
|
||||
tsigmatch.nim(125, 6) Error: type mismatch: got <(string, proc (){.gcsafe, locks: 0.})>
|
||||
tsigmatch.nim(125, 6) Error: type mismatch: got <(string, proc (){.gcsafe.})>
|
||||
but expected one of:
|
||||
proc foo(x: (string, proc ()))
|
||||
first type mismatch at position: 1
|
||||
required type for x: (string, proc (){.closure.})
|
||||
but expression '("foobar", proc () = echo(["Hello!"]))' is of type: (string, proc (){.gcsafe, locks: 0.})
|
||||
but expression '("foobar", proc () = echo(["Hello!"]))' is of type: (string, proc (){.gcsafe.})
|
||||
|
||||
expression: foo(("foobar", proc () = echo(["Hello!"])))
|
||||
tsigmatch.nim(132, 11) Error: type mismatch: got <proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}>
|
||||
tsigmatch.nim(132, 11) Error: type mismatch: got <proc (s: string): string{.noSideEffect, gcsafe.}>
|
||||
but expected one of:
|
||||
proc foo[T, S](op: proc (x: T): S {.cdecl.}): auto
|
||||
first type mismatch at position: 1
|
||||
required type for op: proc (x: T): S{.cdecl.}
|
||||
but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}
|
||||
but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe.}
|
||||
proc foo[T, S](op: proc (x: T): S {.safecall.}): auto
|
||||
first type mismatch at position: 1
|
||||
required type for op: proc (x: T): S{.safecall.}
|
||||
but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}
|
||||
but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe.}
|
||||
|
||||
expression: foo(fun)
|
||||
tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcsafe, locks: 0.}]>
|
||||
tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcsafe.}]>
|
||||
but expected one of:
|
||||
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}])
|
||||
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe.}])
|
||||
first type mismatch at position: 1
|
||||
required type for fs: openArray[proc (x: int){.closure, gcsafe, locks: 0.}]
|
||||
but expression '[proc (x: int) {.gcsafe, locks: 0.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe, locks: 0.}]
|
||||
required type for fs: openArray[proc (x: int){.closure, gcsafe.}]
|
||||
but expression '[proc (x: int) {.gcsafe.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe.}]
|
||||
|
||||
expression: takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo [x]])
|
||||
expression: takesFuncs([proc (x: int) {.gcsafe.} = echo [x]])
|
||||
tsigmatch.nim(149, 4) Error: type mismatch: got <int literal(10), a0: int literal(5), string>
|
||||
but expected one of:
|
||||
proc f(a0: uint8; b: string)
|
||||
@@ -135,12 +135,12 @@ block:
|
||||
# bug #10285 Function signature don't match when inside seq/array/openArray
|
||||
# Note: the error message now shows `closure` which helps debugging the issue
|
||||
# out why it doesn't match
|
||||
proc takesFunc(f: proc (x: int) {.gcsafe, locks: 0.}) =
|
||||
proc takesFunc(f: proc (x: int) {.gcsafe.}) =
|
||||
echo "takes single Func"
|
||||
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}]) =
|
||||
proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe.}]) =
|
||||
echo "takes multiple Func"
|
||||
takesFunc(proc (x: int) {.gcsafe, locks: 0.} = echo x) # works
|
||||
takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo x]) # fails
|
||||
takesFunc(proc (x: int) {.gcsafe.} = echo x) # works
|
||||
takesFuncs([proc (x: int) {.gcsafe.} = echo x]) # fails
|
||||
|
||||
block:
|
||||
# bug https://github.com/nim-lang/Nim/issues/11061#issuecomment-508970465
|
||||
|
||||
@@ -2,10 +2,10 @@ discard """
|
||||
cmd: "nim check $file"
|
||||
errormsg: ""
|
||||
nimout: '''
|
||||
ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for let
|
||||
ttypeAllowed.nim(17, 7) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for const
|
||||
ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for var
|
||||
ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for result
|
||||
ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for let
|
||||
ttypeAllowed.nim(17, 7) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for const
|
||||
ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for var
|
||||
ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for result
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
10
tests/generics/t7446.nim
Normal file
10
tests/generics/t7446.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
proc foo(x: Natural or SomeUnsignedInt):int =
|
||||
when x is int:
|
||||
result = 1
|
||||
else:
|
||||
result = 2
|
||||
let a = 10
|
||||
doAssert foo(a) == 1
|
||||
|
||||
let b = 10'u8
|
||||
doAssert foo(b) == 2
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "type mismatch: got <TT[seq[string]], proc (v: int){.gcsafe, locks: 0.}>"
|
||||
errormsg: "type mismatch: got <TT[seq[string]], proc (v: int){.gcsafe.}>"
|
||||
line: 20
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "invalid type: 'lent QuadraticExt' in this context: 'proc (r: var QuadraticExt, a: lent QuadraticExt, b: lent QuadraticExt){.noSideEffect, gcsafe, locks: 0.}' for proc"
|
||||
errormsg: "invalid type: 'lent QuadraticExt' in this context: 'proc (r: var QuadraticExt, a: lent QuadraticExt, b: lent QuadraticExt){.noSideEffect, gcsafe.}' for proc"
|
||||
"""
|
||||
|
||||
# bug #16898
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "got <B, proc (b: B){.closure, gcsafe, locks: 0.}>"
|
||||
errormsg: "got <B, proc (b: B){.closure, gcsafe.}>"
|
||||
line: 20
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
discard """
|
||||
matrix: "--mm:arc; --mm:refc"
|
||||
"""
|
||||
|
||||
type SomeBase* = ref object of RootObj
|
||||
type SomeDerived* = ref object of SomeBase
|
||||
memberProc*: proc ()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
errormsg: '''
|
||||
type mismatch: got <proc (a0: int): string{.noSideEffect, gcsafe, locks: 0.}>
|
||||
type mismatch: got <proc (a0: int): string{.noSideEffect, gcsafe.}>
|
||||
'''
|
||||
line: 13
|
||||
"""
|
||||
|
||||
@@ -11,12 +11,12 @@ when not defined(js):
|
||||
proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} =
|
||||
let offset = hours * 3600 + minutes * 60 + seconds
|
||||
|
||||
proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime {.locks: 0.} =
|
||||
proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime =
|
||||
result.isDst = false
|
||||
result.utcOffset = offset
|
||||
result.time = adjTime + initDuration(seconds = offset)
|
||||
|
||||
proc zonedTimeFromTime(time: Time): ZonedTime {.locks: 0.}=
|
||||
proc zonedTimeFromTime(time: Time): ZonedTime =
|
||||
result.isDst = false
|
||||
result.utcOffset = offset
|
||||
result.time = time
|
||||
|
||||
@@ -361,7 +361,7 @@ block: # bug #14340
|
||||
envelopeSin[a]()
|
||||
|
||||
block:
|
||||
type Mutator = proc() {.noSideEffect, gcsafe, locks: 0.}
|
||||
type Mutator = proc() {.noSideEffect, gcsafe.}
|
||||
proc mutator0() = discard
|
||||
const mTable = [Mutator(mutator0)]
|
||||
var i=0
|
||||
|
||||
Reference in New Issue
Block a user