diff --git a/changelog.md b/changelog.md index e86e42b339c61..ba67bd2a1cc72 100644 --- a/changelog.md +++ b/changelog.md @@ -62,7 +62,6 @@ - Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom`. UDP functionality. -- `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble. - `dollars.$` now works for unsigned ints with `nim js` - Improvements to the `bitops` module, including bitslices, non-mutating versions @@ -111,6 +110,8 @@ - new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` for json serialization/deserialization of custom types. - new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``. +- Add `rstgen.rstToLatex` convenience proc for `renderRstToOut` and `initRstGenerator` with `outLatex` output. + ## Language changes - In the newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this: diff --git a/compiler/ast.nim b/compiler/ast.nim index 76b1d8c912609..bc26defd4531c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -434,8 +434,8 @@ type # instantiation and prior to this it has the potential to # be any type. - tyOpt - # Builtin optional type + tyOptDeprecated + # deadcode: was `tyOpt`, Builtin optional type tyVoid # now different from tyEmpty, hurray! @@ -658,7 +658,7 @@ type mNewString, mNewStringOfCap, mParseBiggestFloat, mMove, mWasMoved, mDestroy, mDefault, mUnown, mAccessEnv, mReset, - mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs, + mArray, mOpenArray, mRange, mSet, mSeq, mVarargs, mRef, mPtr, mVar, mDistinct, mVoid, mTuple, mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, @@ -1492,7 +1492,7 @@ proc isGCedMem*(t: PType): bool {.inline.} = t.kind == tyProc and t.callConv == ccClosure proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) = - const HaveTheirOwnEmpty = {tySequence, tyOpt, tySet, tyPtr, tyRef, tyProc} + const HaveTheirOwnEmpty = {tySequence, tySet, tyPtr, tyRef, tyProc} owner.flags = owner.flags + (elem.flags * {tfHasMeta, tfTriggersCompileTime}) if tfNotNil in elem.flags: if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}: @@ -1505,7 +1505,7 @@ proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) = if mask != {} and propagateHasAsgn: let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink}) if o2.kind in {tyTuple, tyObject, tyArray, - tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}: + tySequence, tySet, tyDistinct, tyOpenArray, tyVarargs}: o2.flags.incl mask owner.flags.incl mask diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index f7eb1bc34773a..199d5c91893cc 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -367,7 +367,7 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope = if result != nil: return result = getTypePre(m, typ, sig) if result != nil: return - let concrete = typ.skipTypes(abstractInst + {tyOpt}) + let concrete = typ.skipTypes(abstractInst) case concrete.kind of tySequence, tyTuple, tyObject: result = getTypeName(m, typ, sig) diff --git a/compiler/commands.nim b/compiler/commands.nim index 2d84181398d47..c945a633a977c 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -98,7 +98,7 @@ proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) = CPU[conf.target.hostCPU].name, CompileDate]), {msgStdout}) - const gitHash = gorge("git log -n 1 --format=%H").strip + const gitHash {.strdefine.} = gorge("git log -n 1 --format=%H").strip when gitHash.len == 40: msgWriteln(conf, "git hash: " & gitHash, {msgStdout}) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index b7f7100f123ce..9807db79a6b39 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -77,7 +77,7 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasUserErrors") defineSymbol("nimUncheckedArrayTyp") defineSymbol("nimHasTypeof") - defineSymbol("nimErrorProcCanHaveBody") + defineSymbol("nimErrorProcCanHaveBody") # since #9665 but now unused defineSymbol("nimHasInstantiationOfInMacro") defineSymbol("nimHasHotCodeReloading") defineSymbol("nimHasNilSeqs") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 9f022882b3d01..99d2bc4f205b0 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -193,7 +193,7 @@ proc mapType(typ: PType): TJSTypeKind = of tyBool: result = etyBool of tyFloat..tyFloat128: result = etyFloat of tySet: result = etyObject # map a set to a table - of tyString, tySequence, tyOpt: result = etySeq + of tyString, tySequence: result = etySeq of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs, tyUncheckedArray: result = etyObject of tyNil: result = etyNull @@ -210,6 +210,7 @@ proc mapType(typ: PType): TJSTypeKind = else: result = etyNone of tyProc: result = etyProc of tyCString: result = etyString + of tyOptDeprecated: doAssert false proc mapType(p: PProc; typ: PType): TJSTypeKind = result = mapType(typ) @@ -1041,7 +1042,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = # we don't care if it's an etyBaseIndex (global) of a string, it's # still a string that needs to be copied properly: - if x.typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString}: + if x.typ.skipTypes(abstractInst).kind in {tySequence, tyString}: xtyp = etySeq case xtyp of etySeq: @@ -1086,7 +1087,7 @@ proc genFastAsgn(p: PProc, n: PNode) = # See bug #5933. So we try to be more compatible with the C backend semantics # here for 'shallowCopy'. This is an educated guess and might require further # changes later: - let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString} + let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyString} genAsgnAux(p, n[0], n[1], noCopyNeeded=noCopy) proc genSwap(p: PProc, n: PNode) = @@ -1697,7 +1698,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = result = putToSeq("null", indirect) of tySequence, tyString: result = putToSeq("[]", indirect) - of tyCString, tyOpt, tyProc: + of tyCString, tyProc: result = putToSeq("null", indirect) of tyStatic: if t.n != nil: diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 2d8655caef705..0346f6c671a32 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -703,7 +703,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = case t.kind of tyNone, tyEmpty, tyVoid: discard of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, - tyPtr, tyOpt, tyUncheckedArray, tyVar, tyLent: + tyPtr, tyUncheckedArray, tyVar, tyLent: defaultOp(c, t, body, x, y) of tyRef: if c.g.config.selectedGC in {gcArc, gcOrc}: @@ -785,6 +785,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = of tyOrdinal, tyRange, tyInferred, tyGenericInst, tyAlias, tySink: fillBody(c, lastSon(t), body, x, y) + of tyOptDeprecated: doAssert false proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym = diff --git a/compiler/reorder.nim b/compiler/reorder.nim index 5e380a199bcf1..28e12ca2aaa80 100644 --- a/compiler/reorder.nim +++ b/compiler/reorder.nim @@ -290,13 +290,13 @@ proc hasAccQuoted(n: PNode): bool = if hasAccQuoted(a): return true -const extandedProcDefs = procDefs + {nkMacroDef, nkTemplateDef} +const extendedProcDefs = procDefs + {nkMacroDef, nkTemplateDef} proc hasAccQuotedDef(n: PNode): bool = # Checks if the node is a function, macro, template ... # with a quoted name or if it contains one case n.kind - of extandedProcDefs: + of extendedProcDefs: result = n[0].hasAccQuoted of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt: for a in n: @@ -316,7 +316,7 @@ proc hasBody(n: PNode): bool = case n.kind of nkCommand, nkCall: result = true - of extandedProcDefs: + of extendedProcDefs: result = n[^1].kind == nkStmtList of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt: for a in n: diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim index 994a2d3429cf8..13ab03426a492 100644 --- a/compiler/scriptconfig.nim +++ b/compiler/scriptconfig.nim @@ -141,12 +141,10 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; setResult(a, options.existsConfigVar(conf, a.getString 0)) cbconf nimcacheDir: setResult(a, options.getNimcacheDir(conf).string) - result.registerCallback "stdlib.os." & astToStr(paramStr), - proc (a: VmArgs) = - setResult(a, os.paramStr(int a.getInt 0)) - result.registerCallback "stdlib.os." & astToStr(paramCount), - proc (a: VmArgs) = - setResult(a, os.paramCount()) + cbconf paramStr: + setResult(a, os.paramStr(int a.getInt 0)) + cbconf paramCount: + setResult(a, os.paramCount()) cbconf cmpIgnoreStyle: setResult(a, strutils.cmpIgnoreStyle(a.getString 0, a.getString 1)) cbconf cmpIgnoreCase: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 77da403fa517d..313328385ae14 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1814,7 +1814,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semContainer(c, n, tySequence, "seq", prev) if optSeqDestructors in c.config.globalOptions: incl result.flags, tfHasAsgn - of mOpt: result = semContainer(c, n, tyOpt, "opt", prev) of mVarargs: result = semVarargs(c, n, prev) of mTypeDesc, mType, mTypeOf: result = makeTypeDesc(c, semTypeNode(c, n[1], nil)) diff --git a/compiler/types.nim b/compiler/types.nim index e1b283f8752cd..aaaa8e99ffa28 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -608,10 +608,6 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = "seq" if t.len > 0: result &= "[" & typeToString(t[0]) & ']' - of tyOpt: - result = "opt" - if t.len > 0: - result &= "opt[" & typeToString(t[0]) & ']' of tyOrdinal: result = "ordinal" if t.len > 0: @@ -1150,7 +1146,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink, tyUncheckedArray, tyArray, tyProc, tyVarargs, tyOrdinal, tyCompositeTypeClass, tyUserTypeClass, tyUserTypeClassInst, - tyAnd, tyOr, tyNot, tyAnything, tyOpt, tyOwned: + tyAnd, tyOr, tyNot, tyAnything, tyOwned: cycleCheck() if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n result = sameChildrenAux(a, b, c) @@ -1173,6 +1169,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = cycleCheck() result = sameTypeAux(a.lastSon, b.lastSon, c) of tyNone: result = false + of tyOptDeprecated: doAssert false proc sameBackendType*(x, y: PType): bool = var c = initSameTypeClosure() @@ -1365,7 +1362,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = t else: result = typeAllowedAux(marker, lastSon(t), kind, flags-{taHeap}) - of tySequence, tyOpt: + of tySequence: if t[0].kind != tyEmpty: result = typeAllowedAux(marker, t[0], kind, flags+{taHeap}) elif kind in {skVar, skLet}: @@ -1408,6 +1405,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = typeAllowedAux(marker, t.lastSon, kind, flags+{taHeap}) else: result = t + of tyOptDeprecated: doAssert false proc typeAllowed*(t: PType, kind: TSymKind; flags: TTypeAllowedFlags = {}): PType = # returns 'nil' on success and otherwise the part of the type that is diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 7cfba046ab023..6f90b79189f43 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -224,7 +224,6 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; of tyLent: result = mapTypeToBracket("lent", mBuiltinType, t, info) of tySink: result = mapTypeToBracket("sink", mBuiltinType, t, info) of tySequence: result = mapTypeToBracket("seq", mSeq, t, info) - of tyOpt: result = mapTypeToBracket("opt", mOpt, t, info) of tyProc: if inst: result = newNodeX(nkProcTy) @@ -298,6 +297,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; if t.n != nil: result.add t.n.copyTree of tyOwned: result = mapTypeToBracket("owned", mBuiltinType, t, info) + of tyOptDeprecated: doAssert false proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = result = mapTypeToAstX(cache, t, info, inst=false, allowRecursionX=true) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index b408db08b0f99..52b7b6eb3e75f 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1820,8 +1820,6 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode = result.add getNullValue(t[i], info, conf) of tySet: result = newNodeIT(nkCurly, info, t) - of tyOpt: - result = newNodeIT(nkNilLit, info, t) of tySequence: result = newNodeIT(nkBracket, info, t) else: diff --git a/doc/advopt.txt b/doc/advopt.txt index a668be5c023b0..e522973cdc47d 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -113,7 +113,7 @@ Advanced options: --skipUserCfg:on|off do not read the user's configuration file --skipParentCfg:on|off do not read the parent dirs' configuration files --skipProjCfg:on|off do not read the project's configuration file - --gc:refc|markAndSweep|boehm|go|none|regions + --gc:refc|arc|orc|markAndSweep|boehm|go|none|regions select the GC to use; default is 'refc' --exceptions:setjmp|cpp|goto|quirky select the exception handling implementation diff --git a/doc/manual.rst b/doc/manual.rst index 451359dca70f8..6eec8bef970c7 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -4354,7 +4354,7 @@ caught by reference. Example: fn() **Note:** `getCurrentException()` and `getCurrentExceptionMsg()` are not available -for imported exceptions. One needs to use the `except ImportedException as x:` syntax +for imported exceptions from C++. One needs to use the `except ImportedException as x:` syntax and rely on functionality of the `x` object to get exception details. diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 9e17b665a4b64..3590a162bf77c 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -106,7 +106,7 @@ type ntyError, ntyBuiltinTypeClass, ntyUserTypeClass, ntyUserTypeClassInst, ntyCompositeTypeClass, ntyInferred, ntyAnd, ntyOr, ntyNot, - ntyAnything, ntyStatic, ntyFromExpr, ntyOpt, ntyVoid + ntyAnything, ntyStatic, ntyFromExpr, ntyOptDeprecated, ntyVoid TNimTypeKinds* {.deprecated.} = set[NimTypeKind] NimSymKind* = enum diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index 6a7b33cc05ea8..2ec25cc6e4e19 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -29,6 +29,7 @@ import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils, algorithm, parseutils import "$lib/../compiler/nimpaths" import "$lib/../compiler/pathutils" +import ../../std/private/since const HtmlExt = "html" @@ -1344,6 +1345,16 @@ proc rstToHtml*(s: string, options: RstParseOptions, renderRstToOut(d, rst, result) +proc rstToLatex*(rstSource: string; options: RstParseOptions): string {.inline, since: (1, 3).} = + ## Convenience proc for `renderRstToOut` and `initRstGenerator`. + runnableExamples: doAssert rstToLatex("*Hello* **world**", {}) == """\emph{Hello} \textbf{world}""" + if rstSource.len == 0: return + var option: bool + var rstGenera: RstGenerator + rstGenera.initRstGenerator(outLatex, defaultConfig(), "input", options) + rstGenera.renderRstToOut(rstParse(rstSource, "", 1, 1, option, options), result) + + when isMainModule: assert rstToHtml("*Hello* **world**!", {}, newStringTable(modeStyleInsensitive)) == diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 42735ad4ecb29..1ac3ae185722f 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -457,7 +457,7 @@ proc sendFile(socket: Socket | AsyncSocket, file.close() proc redirection(status: string): bool = - const redirectionNRs = ["301", "302", "303", "307"] + const redirectionNRs = ["301", "302", "303", "307", "308"] for i in items(redirectionNRs): if status.startsWith(i): return true diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index 78cb66ded9d09..9c51887cbd3be 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -66,6 +66,7 @@ const Http304* = HttpCode(304) Http305* = HttpCode(305) Http307* = HttpCode(307) + Http308* = HttpCode(308) Http400* = HttpCode(400) Http401* = HttpCode(401) Http403* = HttpCode(403) @@ -272,6 +273,7 @@ proc `$`*(code: HttpCode): string = of 304: "304 Not Modified" of 305: "305 Use Proxy" of 307: "307 Temporary Redirect" + of 308: "308 Permanent Redirect" of 400: "400 Bad Request" of 401: "401 Unauthorized" of 403: "403 Forbidden" diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 97e414d44935e..a289287fabff7 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -75,8 +75,8 @@ elif defined(posix): else: {.error: "OS module not ported to your operating system!".} -when weirdTarget and defined(nimErrorProcCanHaveBody): - {.pragma: noNimScript, error: "this proc is not available on the NimScript target".} +when weirdTarget: + template noNimScript(body): untyped = discard else: {.pragma: noNimScript.} @@ -2708,23 +2708,7 @@ when defined(nimdoc): ## else: ## # Do something else! -elif defined(nimscript): - proc paramStr*(i: int): string = - ## Retrieves the ``i``'th command line parameter. - discard - - proc paramCount*(): int = - ## Retrieves the number of command line parameters. - discard - -elif defined(js): - proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} = - raise newException(OSError, "paramStr is not implemented on JavaScript") - - proc paramCount*(): int {.tags: [ReadIOEffect].} = - raise newException(OSError, "paramCount is not implemented on JavaScript") - -elif defined(nintendoswitch): +elif defined(nintendoswitch) or weirdTarget: proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} = raise newException(OSError, "paramStr is not implemented on Nintendo Switch") @@ -3120,7 +3104,7 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped = assert(path != "") # symlinks can't occur for file handles formalInfo.kind = getSymlinkFileKind(path) -when defined(js) or defined(nimscript): +when defined(js): when not declared(FileHandle): type FileHandle = distinct int32 when not declared(File): diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 63c1a5448b250..b77f7ccde9c43 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -69,7 +69,7 @@ type tyAnythingHidden, tyStaticHidden, tyFromExprHidden, - tyOpt, + tyOptDeprecated, tyVoidHidden TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index da5c291fa4e23..ceaaef01350a5 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -56,6 +56,14 @@ proc rawExec(cmd: string): int {.tags: [ExecIOEffect], raises: [OSError].} = proc warningImpl(arg, orig: string) = discard proc hintImpl(arg, orig: string) = discard +proc paramStr*(i: int): string = + ## Retrieves the ``i``'th command line parameter. + builtin + +proc paramCount*(): int = + ## Retrieves the number of command line parameters. + builtin + proc switch*(key: string, val="") = ## Sets a Nim compiler command line switch, for ## example ``switch("checks", "on")``. @@ -272,9 +280,6 @@ proc selfExec*(command: string) {. raise newException(OSError, "FAILED: " & c) checkOsError() -from os import paramCount, paramStr -export paramCount, paramStr - proc put*(key, value: string) = ## Sets a configuration 'key' like 'gcc.options.always' to its value. builtin diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index dbf9bcf06f129..06e605a7bbd78 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -15,6 +15,13 @@ # we don't use refcounts because that's a behaviour # the programmer may not want + +proc dataPointer(a: PGenericSeq, elemAlign: int): pointer = + cast[pointer](cast[ByteAddress](a) +% align(GenericSeqSize, elemAlign)) + +proc dataPointer(a: PGenericSeq, elemAlign, elemSize, index: int): pointer = + cast[pointer](cast[ByteAddress](a) +% align(GenericSeqSize, elemAlign) +% (index*%elemSize)) + proc resize(old: int): int {.inline.} = if old <= 0: result = 4 elif old < 65536: result = old * 2 @@ -267,9 +274,6 @@ proc incrSeqV2(seq: PGenericSeq, elemSize, elemAlign: int): PGenericSeq {.compil result = cast[PGenericSeq](growObj(result, align(GenericSeqSize, elemAlign) + elemSize * r)) result.reserved = r -template `+!`(p: pointer, s: int): pointer = - cast[pointer](cast[int](p) +% s) - proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} = if s == nil: result = cast[PGenericSeq](newSeq(typ, 1)) @@ -281,7 +285,7 @@ proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} = when defined(nimIncrSeqV3): result = cast[PGenericSeq](newSeq(typ, r)) result.len = s.len - copyMem(result +! align(GenericSeqSize, typ.base.align), s +! align(GenericSeqSize, typ.base.align), s.len * typ.base.size) + copyMem(dataPointer(result, typ.base.align), dataPointer(s, typ.base.align), s.len * typ.base.size) # since we steal the content from 's', it's crucial to set s's len to 0. s.len = 0 else: @@ -303,7 +307,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, elemAlign, newLen: int): PGenericS when false: # compileOption("gc", "v2"): for i in newLen..result.len-1: let len0 = gch.tempStack.len - forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +% (i*%elemSize)), + forAllChildrenAux(dataPointer(result, elemAlign, elemSize, i), extGetCellType(result).base, waPush) let len1 = gch.tempStack.len for i in len0 ..< len1: @@ -312,8 +316,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, elemAlign, newLen: int): PGenericS else: if ntfNoRefs notin extGetCellType(result).base.flags: for i in newLen..result.len-1: - forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% - align(GenericSeqSize, elemAlign) +% (i*%elemSize)), + forAllChildrenAux(dataPointer(result, elemAlign, elemSize, i), extGetCellType(result).base, waZctDecRef) # XXX: zeroing out the memory can still result in crashes if a wiped-out @@ -322,8 +325,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, elemAlign, newLen: int): PGenericS # presence of user defined destructors, the user will expect the cell to be # "destroyed" thus creating the same problem. We can destroy the cell in the # finalizer of the sequence, but this makes destruction non-deterministic. - zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +% - (newLen*%elemSize)), (result.len-%newLen) *% elemSize) + zeroMem(dataPointer(result, elemAlign, elemSize, newLen), (result.len-%newLen) *% elemSize) result.len = newLen proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. @@ -338,7 +340,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. if s.space < newLen: let r = max(resize(s.space), newLen) result = cast[PGenericSeq](newSeq(typ, r)) - copyMem(result +! align(GenericSeqSize, elemAlign), s +! align(GenericSeqSize, elemAlign), s.len * elemSize) + copyMem(dataPointer(result, elemAlign), dataPointer(s, elemAlign), s.len * elemSize) # since we steal the content from 's', it's crucial to set s's len to 0. s.len = 0 elif newLen < s.len: @@ -349,8 +351,7 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. not defined(gcRegions): if ntfNoRefs notin typ.base.flags: for i in newLen..result.len-1: - forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% - align(GenericSeqSize, elemAlign) +% (i*%elemSize)), + forAllChildrenAux(dataPointer(result, elemAlign, elemSize, i), extGetCellType(result).base, waZctDecRef) # XXX: zeroing out the memory can still result in crashes if a wiped-out @@ -359,10 +360,10 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. # presence of user defined destructors, the user will expect the cell to be # "destroyed" thus creating the same problem. We can destroy the cell in the # finalizer of the sequence, but this makes destruction non-deterministic. - zeroMem(cast[pointer](cast[ByteAddress](result) +% align(GenericSeqSize, elemAlign) +% - (newLen*%elemSize)), (result.len-%newLen) *% elemSize) + zeroMem(dataPointer(result, elemAlign, elemSize, newLen), (result.len-%newLen) *% elemSize) else: result = s + zeroMem(dataPointer(result, elemAlign, elemSize, result.len), (newLen-%result.len) *% elemSize) result.len = newLen else: result = setLengthSeq(s, typ.base.size, newLen) diff --git a/testament/important_packages.nim b/testament/important_packages.nim index 19e11e322cb1f..5a28fa3dd2bf4 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -40,7 +40,8 @@ pkg1 "delaunay" pkg1 "docopt" pkg1 "easygl", true, "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl" pkg1 "elvis" -pkg1 "fidget", true, "nim c -d:release -r tests/runNative.nim" +# pkg1 "fidget", true, "nim c -d:release -r tests/runNative.nim" + # Error: cannot open 'tests/runNative.nim' pkg1 "fragments", false, "nim c -r fragments/dsl.nim" pkg1 "gara" pkg1 "ggplotnim", true, "nim c -d:noCairo -r -d:nimWorkaround14447 tests/tests.nim" diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim index c20df29e5b409..f7487525af136 100644 --- a/tests/async/tioselectors.nim +++ b/tests/async/tioselectors.nim @@ -145,14 +145,15 @@ when not defined(windows): proc timer_notification_test(): bool = var selector = newSelector[int]() var timer = selector.registerTimer(100, false, 0) - var rc1 = selector.select(140) - var rc2 = selector.select(140) + var rc1 = selector.select(10000) + var rc2 = selector.select(10000) + # if this flakes, see tests/m14634.nim assert len(rc1) == 1 and len(rc2) == 1, $(len(rc1), len(rc2)) selector.unregister(timer) discard selector.select(0) selector.registerTimer(100, true, 0) - var rc4 = selector.select(120) - var rc5 = selector.select(120) + var rc4 = selector.select(10000) + var rc5 = selector.select(1000) # this will be an actual wait, keep it small assert len(rc4) == 1 and len(rc5) == 0, $(len(rc4), len(rc5)) assert(selector.isEmpty()) selector.close() diff --git a/tests/collections/tseq.nim b/tests/collections/tseq.nim index ac68e5636025c..263a571bf3b0d 100644 --- a/tests/collections/tseq.nim +++ b/tests/collections/tseq.nim @@ -206,4 +206,11 @@ block ttoseq: stdout.write("\n") block tseqmapitchain: - doAssert @[101, 102] == [1, 2].mapIt(func (x: int): int = it + x).mapIt(it(100)) \ No newline at end of file + doAssert @[101, 102] == [1, 2].mapIt(func (x: int): int = it + x).mapIt(it(100)) + + +for i in 0..100: + # fix #14655 + var test = newSeqOfCap[uint32](1) + test.setLen(1) + doAssert test[0] == 0, $(test[0], i) diff --git a/tests/m14634.nim b/tests/m14634.nim new file mode 100644 index 0000000000000..56a3d9034e249 --- /dev/null +++ b/tests/m14634.nim @@ -0,0 +1,48 @@ +#[ +Tool to investigate underlying reasons for https://github.com/nim-lang/Nim/pull/14634 +nim r --threads:on -d:threadsafe tests/m14634.nim +]# + +when not defined(windows): + import std/selectors + + type TestData = object + s1, s2, s3: int + + proc timerNotificationTestImpl(data: var TestData) = + var selector = newSelector[int]() + let t0 = 5 + var timer = selector.registerTimer(t0, false, 0) + let t = 2000 + # values too close to `t0` cause the test to be flaky in CI on OSX+freebsd + # When running locally, t0=100, t=98 will succeed some of the time which indicates + # there is some lag involved. Note that the higher `t-t0` is, the less times + # the test fails. + var rc1 = selector.select(t) + var rc2 = selector.select(t) + assert len(rc1) <= 1 and len(rc2) <= 1 + data.s1 += ord(len(rc1) == 1) + data.s2 += ord(len(rc2) == 1) + selector.unregister(timer) + discard selector.select(0) + selector.registerTimer(t0, true, 0) + # same comment as above + var rc4 = selector.select(t) + let t2 = 100 + # this can't be too large as it'll actually wait that long: + # timer_notification_test.n * t2 + var rc5 = selector.select(t2) + assert len(rc4) + len(rc5) <= 1 + data.s3 += ord(len(rc4) + len(rc5) == 1) + assert(selector.isEmpty()) + selector.close() + + proc timerNotificationTest() = + var data: TestData + let n = 10 + for i in 0..