mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-27 00:51:39 +00:00
Merge branch 'devel' into pr_proc_type_revisit
This commit is contained in:
@@ -81,6 +81,9 @@ parameter and result types, not just their source-level shape. Use
|
||||
- `std/re` and `std/nre` are deprecated as PCRE library is obsolete.
|
||||
Use https://github.com/nitely/nim-regex or `std/nre2`.
|
||||
See: https://github.com/nim-lang/Nim/issues/23668.
|
||||
- `std/pegs` now correctly lexes UTF-8 bytes inside bare identifier-style
|
||||
terminals, so case-insensitive matching of non-ASCII terms (e.g. ``\i café``)
|
||||
works without single-quoting.
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
@@ -2816,9 +2816,9 @@ proc genWasMoved(p: BProc; n: PNode) =
|
||||
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
|
||||
|
||||
proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref, lfPrepareForMutation})
|
||||
if n.len == 4:
|
||||
# generated by liftdestructors:
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref, lfPrepareForMutation})
|
||||
var src: TLoc = initLocExpr(p, n[2])
|
||||
let destVal = rdLoc(a)
|
||||
let srcVal = rdLoc(src)
|
||||
@@ -2838,29 +2838,16 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
else:
|
||||
if d.k == locNone: d = getTemp(p, n.typ)
|
||||
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcYrc}:
|
||||
genAssignment(p, d, a, {})
|
||||
var op = getAttachedOp(p.module.g.graph, n.typ, attachedWasMoved)
|
||||
if op == nil:
|
||||
if op == nil or sfOverridden notin op.flags:
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref, lfPrepareForMutation})
|
||||
genAssignment(p, d, a, {})
|
||||
resetLoc(p, a)
|
||||
else:
|
||||
var b = initLocExpr(p, newSymNode(op))
|
||||
case skipTypes(a.t, abstractVar+{tyStatic}).kind
|
||||
of tyOpenArray, tyVarargs: # todo fixme generated `wasMoved` hooks for
|
||||
# openarrays, but it probably shouldn't?
|
||||
let ra = rdLoc(a)
|
||||
var s: string
|
||||
if reifiedOpenArray(a.lode):
|
||||
if a.t.kind in {tyVar, tyLent}:
|
||||
s = derefField(ra, "Field0") & cArgumentSeparator & derefField(ra, "Field1")
|
||||
else:
|
||||
s = dotField(ra, "Field0") & cArgumentSeparator & dotField(ra, "Field1")
|
||||
else:
|
||||
s = ra & cArgumentSeparator & ra & "Len_0"
|
||||
p.s(cpsStmts).addCallStmt(rdLoc(b), s)
|
||||
else:
|
||||
let val = if p.module.compileToCpp: rdLoc(a) else: byRefLoc(p, a)
|
||||
p.s(cpsStmts).addCallStmt(rdLoc(b), val)
|
||||
n[1] = makeAddr(n[1], p.module.idgen)
|
||||
genCall(p, n, d)
|
||||
else:
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref, lfPrepareForMutation})
|
||||
genAssignment(p, d, a, {})
|
||||
resetLoc(p, a)
|
||||
|
||||
|
||||
@@ -341,9 +341,9 @@ proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
|
||||
call[i][0]
|
||||
else:
|
||||
call[i]
|
||||
if param.kind != nkBracketExpr or param.typ.kind in
|
||||
if not param.typ.isCompileTimeOnly and (param.kind != nkBracketExpr or param.typ.kind in
|
||||
{tyRef, tyPtr, tyUncheckedArray, tyArray, tyOpenArray,
|
||||
tyVarargs, tySequence, tyString, tyCstring, tyTuple}:
|
||||
tyVarargs, tySequence, tyString, tyCstring, tyTuple}):
|
||||
let tempLoc = initLocExprSingleUse(p, param)
|
||||
didGenTemp = didGenTemp or tempLoc.k == locTemp
|
||||
genOtherArg(p, call, i, typ, res, argBuilder)
|
||||
|
||||
@@ -930,7 +930,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
if m.len == 0:
|
||||
localError(conf, info, "Cannot resolve filename: " & arg)
|
||||
else:
|
||||
conf.implicitImports.add m
|
||||
conf.implicitImports.add(if arg.startsWith(stdPrefix): arg else: m)
|
||||
of "include":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
|
||||
@@ -13,7 +13,7 @@ import
|
||||
ast, msgs, options, idents, lookups,
|
||||
semdata, modulepaths, sigmatch, lineinfos,
|
||||
modulegraphs, wordrecg
|
||||
from std/strutils import `%`, startsWith
|
||||
from std/strutils import `%`, startsWith, replace
|
||||
from std/sequtils import addUnique
|
||||
import std/[sets, tables, intsets]
|
||||
|
||||
@@ -304,9 +304,9 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym =
|
||||
var prefix = ""
|
||||
if realModule.constraint != nil: prefix = realModule.constraint.strVal & "; "
|
||||
message(c.config, n.info, warnDeprecated, prefix & realModule.name.s & " is deprecated")
|
||||
let moduleName = getModuleName(c.config, n)
|
||||
if belongsToStdlib(c.graph, result) and not startsWith(moduleName, stdPrefix) and
|
||||
not startsWith(moduleName, "system/") and not startsWith(moduleName, "packages/"):
|
||||
let moduleNameNorm = getModuleName(c.config, n).replace("\\", "/")
|
||||
if belongsToStdlib(c.graph, result) and not startsWith(moduleNameNorm, stdPrefix) and
|
||||
not startsWith(moduleNameNorm, "system/") and not startsWith(moduleNameNorm, "packages/"):
|
||||
message(c.config, n.info, warnStdPrefix, realModule.name.s)
|
||||
|
||||
proc suggestMod(n: PNode; s: PSym) =
|
||||
|
||||
@@ -1349,7 +1349,7 @@ proc rawGetTok*(L: var Lexer, tok: var Token) =
|
||||
lexMessage(L, errGenerated, "invalid token: no whitespace between number and identifier")
|
||||
of '-':
|
||||
if L.buf[L.bufpos+1] in {'0'..'9'} and
|
||||
(L.bufpos-1 == 0 or L.buf[L.bufpos-1] in UnaryMinusWhitelist):
|
||||
(L.bufpos == 0 or L.buf[L.bufpos-1] in UnaryMinusWhitelist):
|
||||
# x)-23 # binary minus
|
||||
# ,-23 # unary minus
|
||||
# \n-78 # unary minus? Yes.
|
||||
|
||||
@@ -637,6 +637,11 @@ proc renderNotLValue*(n: PNode): string =
|
||||
elif n.kind in {nkHiddenStdConv, nkHiddenSubConv} and n.len == 2:
|
||||
result = typeToString(n.typ.skipTypes(abstractVar)) & "(" & result & ")"
|
||||
|
||||
proc isSsoStringIndex*(conf: ConfigRef; n: PNode): bool =
|
||||
result = conf.usesSso() and n.kind == nkBracketExpr and n.len >= 1 and
|
||||
n[0].typ != nil and
|
||||
n[0].typ.skipTypes(abstractVar + abstractInst - {tyTypeDesc}).kind == tyString
|
||||
|
||||
proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||
result = parampatterns.isAssignable(c.p.owner, n)
|
||||
|
||||
|
||||
@@ -809,6 +809,10 @@ proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; ar
|
||||
markSideEffect(tracked, a, n.info)
|
||||
let paramType = if formals != nil and argIndex < formals.signatureLen: formals[argIndex] else: nil
|
||||
if paramType != nil and paramType.kind in {tyVar}:
|
||||
let arg = n.skipAddr()
|
||||
if isSsoStringIndex(tracked.config, arg):
|
||||
localError(tracked.config, arg.info,
|
||||
"expression '$1' is immutable, not 'var'" % renderNotLValue(arg))
|
||||
invalidateFacts(tracked.guards, n)
|
||||
if n.kind == nkSym and isLocalSym(tracked, n.sym):
|
||||
makeVolatile(tracked, n.sym)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module implements threadpool's ``spawn``.
|
||||
|
||||
import ast, types, idents, magicsys, msgs, options, modulegraphs,
|
||||
lowerings, liftdestructors, renderer
|
||||
lowerings, liftdestructors, renderer, trees
|
||||
from trees import getMagic, getRoot
|
||||
|
||||
proc callProc(a: PNode): PNode =
|
||||
@@ -53,6 +53,24 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
|
||||
if t.kind in {tyVar, tyLent, tySequence}: t = t.elementType
|
||||
result = not containsGarbageCollectedRef(t)
|
||||
|
||||
proc newSpawnMoveStmt(g: ModuleGraph; idgen: IdGenerator; le, ri: PNode): PNode =
|
||||
let op = getAttachedOp(g, ri.typ.skipTypes({tyGenericInst, tyAlias, tyVar, tySink}), attachedWasMoved)
|
||||
if op != nil and sfOverridden in op.flags:
|
||||
result = newNodeI(nkStmtList, le.info)
|
||||
result.add newFastAsgnStmt(le, ri)
|
||||
|
||||
let wasMovedCall = newNodeI(nkCall, ri.info)
|
||||
wasMovedCall.add newSymNode(op)
|
||||
|
||||
if op.typ != nil and op.typ.signatureLen > 1 and op.typ.firstParamType.kind != tyVar:
|
||||
wasMovedCall.add ri.skipAddr
|
||||
else:
|
||||
wasMovedCall.add makeAddr(ri.skipAddr, idgen)
|
||||
|
||||
result.add wasMovedCall
|
||||
else:
|
||||
result = newFastMoveStmt(g, le, ri)
|
||||
|
||||
proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator; owner: PSym; typ: PType;
|
||||
v: PNode; useShallowCopy=false): PSym =
|
||||
result = newSym(skTemp, getIdent(g.cache, genPrefix), idgen, owner, varSection.info,
|
||||
@@ -68,10 +86,10 @@ proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator;
|
||||
if varInit != nil:
|
||||
if g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc, gcYrc}:
|
||||
# inject destructors pass will do its own analysis
|
||||
varInit.add newFastMoveStmt(g, newSymNode(result), v)
|
||||
varInit.add newSpawnMoveStmt(g, idgen, newSymNode(result), v)
|
||||
else:
|
||||
if useShallowCopy and typeNeedsNoDeepCopy(typ) or optTinyRtti in g.config.globalOptions:
|
||||
varInit.add newFastMoveStmt(g, newSymNode(result), v)
|
||||
varInit.add newSpawnMoveStmt(g, idgen, newSymNode(result), v)
|
||||
else:
|
||||
let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
|
||||
deepCopyCall[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy))
|
||||
|
||||
@@ -34,10 +34,10 @@ To learn how to compile Nim programs and generate documentation see
|
||||
the [Compiler User Guide](nimc.html) and the [DocGen Tools Guide](docgen.html).
|
||||
|
||||
The language constructs are explained using an extended BNF, in which `(a)*`
|
||||
means 0 or more `a`'s, `a+` means 1 or more `a`'s, and `(a)?` means an
|
||||
means 0 or more *a*'s, `a+` means 1 or more *a*'s, and `(a)?` means an
|
||||
optional *a*. Parentheses may be used to group elements.
|
||||
|
||||
`&` is the lookahead operator; `&a` means that an `a` is expected but
|
||||
`&` is the lookahead operator; `&a` means that an *a* is expected but
|
||||
not consumed. It will be consumed in the following rule.
|
||||
|
||||
The `|`, `/` symbols are used to mark alternatives and have the lowest
|
||||
@@ -8874,7 +8874,7 @@ Byref pragma
|
||||
The `byref` pragma can be applied to an object or tuple type or a proc param.
|
||||
When applied to a type it instructs the compiler to pass the type by reference
|
||||
(hidden pointer) to procs. When applied to a param it will take precedence, even
|
||||
if the the type was marked as `bycopy`. When an `importc` type has a `byref` pragma or
|
||||
if the type was marked as `bycopy`. When an `importc` type has a `byref` pragma or
|
||||
parameters are marked as `byref` in an `importc` proc, these params translate to pointers.
|
||||
When an `importcpp` type has a `byref` pragma, these params translate to
|
||||
C++ references `&`.
|
||||
|
||||
@@ -1144,7 +1144,7 @@ there is a difference between the `$` and `repr` outputs:
|
||||
echo myCharacter, ":", repr(myCharacter)
|
||||
# --> n:'n'
|
||||
echo myString, ":", repr(myString)
|
||||
# --> nim:0x10fa8c050"nim"
|
||||
# --> nim:"nim"
|
||||
echo myInteger, ":", repr(myInteger)
|
||||
# --> 42:42
|
||||
echo myFloat, ":", repr(myFloat)
|
||||
|
||||
@@ -495,13 +495,16 @@ func `$`*[T](c: CritBitTree[T]): string =
|
||||
const avgItemLen = 16
|
||||
result = newStringOfCap(c.count * avgItemLen)
|
||||
result.add("{")
|
||||
var first = true
|
||||
when T is void:
|
||||
for key in keys(c):
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.addQuoted(key)
|
||||
else:
|
||||
for key, val in pairs(c):
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.addQuoted(key)
|
||||
result.add(": ")
|
||||
result.addQuoted(val)
|
||||
|
||||
@@ -454,8 +454,10 @@ proc `$`*[T](deq: Deque[T]): string =
|
||||
assert $a == "[10, 20, 30]"
|
||||
|
||||
result = "["
|
||||
var first = true
|
||||
for x in deq:
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.addQuoted(x)
|
||||
result.add("]")
|
||||
|
||||
|
||||
@@ -260,7 +260,9 @@ proc `$`*[T](heap: HeapQueue[T]): string =
|
||||
assert $heap == "[1, 2]"
|
||||
|
||||
result = "["
|
||||
var first = true
|
||||
for x in heap.data:
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.addQuoted(x)
|
||||
result.add("]")
|
||||
|
||||
@@ -304,8 +304,10 @@ proc `$`*[T](L: SomeLinkedCollection[T]): string =
|
||||
assert $a == "[1, 2, 3, 4]"
|
||||
|
||||
result = "["
|
||||
var first = true
|
||||
for x in nodes(L):
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.addQuoted(x.value)
|
||||
result.add("]")
|
||||
|
||||
|
||||
@@ -1668,7 +1668,10 @@ func getSymbol(c: var PegLexer, tok: var Token) =
|
||||
while pos < c.buf.len:
|
||||
add(tok.literal, c.buf[pos])
|
||||
inc(pos)
|
||||
if pos < c.buf.len and c.buf[pos] notin strutils.IdentChars: break
|
||||
if pos < c.buf.len:
|
||||
let ch = c.buf[pos]
|
||||
# Keep non-ASCII bytes so UTF-8 terminals reach the rune-aware matchers.
|
||||
if ch notin strutils.IdentChars and ord(ch) < 0x80: break
|
||||
c.bufpos = pos
|
||||
tok.kind = tkIdentifier
|
||||
|
||||
|
||||
@@ -380,8 +380,10 @@ proc `$`*(t: StringTableRef): string {.rtlFunc, extern: "nstDollar".} =
|
||||
result = "{:}"
|
||||
else:
|
||||
result = "{"
|
||||
var first = true
|
||||
for key, val in pairs(t):
|
||||
if result.len > 1: result.add(", ")
|
||||
if first: first = false
|
||||
else: result.add(", ")
|
||||
result.add(key)
|
||||
result.add(": ")
|
||||
result.add(val)
|
||||
|
||||
@@ -166,7 +166,7 @@ proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.}
|
||||
## it was "moved" and to signify its destructor should do nothing and
|
||||
## ideally be optimized away.
|
||||
|
||||
proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
|
||||
proc move*[T](x: var T): T {.magic: "Move", noSideEffect, nodestroy.} =
|
||||
result = x
|
||||
{.cast(raises: []), cast(tags: []).}:
|
||||
`=wasMoved`(x)
|
||||
@@ -2694,7 +2694,9 @@ when hasAlloc or defined(nimscript):
|
||||
setLen(x, xl+item.len)
|
||||
var j = xl-1
|
||||
while j >= i:
|
||||
when defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc):
|
||||
when defined(nimsso):
|
||||
x[j+item.len] = x[j]
|
||||
elif defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc):
|
||||
x[j+item.len] = move x[j]
|
||||
else:
|
||||
shallowCopy(x[j+item.len], x[j])
|
||||
|
||||
@@ -691,7 +691,7 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
|
||||
removeChunkFromMatrix2(a, result, fl, sl)
|
||||
if result.size >= size + PageSize:
|
||||
splitChunk(a, result, size)
|
||||
# set 'used' to to true:
|
||||
# set 'used' to true:
|
||||
result.prevSize = 1
|
||||
track("setUsedToFalse", addr result.size, sizeof(int))
|
||||
sysAssert result.owner == addr a, "getBigChunk: No owner set!"
|
||||
@@ -708,7 +708,7 @@ proc getHugeChunk(a: var MemRegion; size: int): PBigChunk =
|
||||
result.next = nil
|
||||
result.prev = nil
|
||||
result.size = size
|
||||
# set 'used' to to true:
|
||||
# set 'used' to true:
|
||||
result.prevSize = 1
|
||||
result.owner = addr a
|
||||
incl(a, a.chunkStarts, pageIndex(result))
|
||||
|
||||
@@ -143,7 +143,7 @@ when nimCoroutines:
|
||||
|
||||
proc find(first: var GcStack, bottom: pointer): ptr GcStack =
|
||||
## Find stack struct based on bottom pointer. If `bottom` is nil then main
|
||||
## thread stack is is returned.
|
||||
## thread stack is returned.
|
||||
if bottom == nil:
|
||||
return addr(gch.stack)
|
||||
|
||||
|
||||
@@ -59,16 +59,35 @@ template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val)
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
(when i is BackwardsIndex: s.len - int(i) else: int(i))
|
||||
|
||||
template spliceImpl(s, a, L, b: typed): untyped =
|
||||
template spliceStringImpl(s, a, L, b: typed): untyped =
|
||||
# make room for additional elements or cut:
|
||||
var shift = b.len - max(0,L) # ignore negative slice size
|
||||
var newLen = s.len + shift
|
||||
if shift > 0:
|
||||
# enlarge:
|
||||
setLen(s, newLen)
|
||||
for i in countdown(newLen-1, a+b.len): movingCopy(s[i], s[i-shift])
|
||||
for i in countdown(newLen-1, a+b.len):
|
||||
s[i] = s[i-shift]
|
||||
else:
|
||||
for i in countup(a+b.len, newLen-1): movingCopy(s[i], s[i-shift])
|
||||
for i in countup(a+b.len, newLen-1):
|
||||
s[i] = s[i-shift]
|
||||
# cut down:
|
||||
setLen(s, newLen)
|
||||
# fill the hole:
|
||||
for i in 0 ..< b.len: s[a+i] = b[i]
|
||||
|
||||
template spliceSeqImpl(s, a, L, b: typed): untyped =
|
||||
# make room for additional elements or cut:
|
||||
var shift = b.len - max(0,L) # ignore negative slice size
|
||||
var newLen = s.len + shift
|
||||
if shift > 0:
|
||||
# enlarge:
|
||||
setLen(s, newLen)
|
||||
for i in countdown(newLen-1, a+b.len):
|
||||
movingCopy(s[i], s[i-shift])
|
||||
else:
|
||||
for i in countup(a+b.len, newLen-1):
|
||||
movingCopy(s[i], s[i-shift])
|
||||
# cut down:
|
||||
setLen(s, newLen)
|
||||
# fill the hole:
|
||||
@@ -102,7 +121,7 @@ proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) {.systemRa
|
||||
if L == b.len:
|
||||
for i in 0..<L: s[i+a] = b[i]
|
||||
else:
|
||||
spliceImpl(s, a, L, b)
|
||||
spliceStringImpl(s, a, L, b)
|
||||
|
||||
proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
|
||||
## Slice operation for arrays.
|
||||
@@ -162,4 +181,4 @@ proc `[]=`*[T; U, V: Ordinal](s: var seq[T], x: HSlice[U, V], b: openArray[T]) {
|
||||
if L == b.len:
|
||||
for i in 0 ..< L: s[i+a] = b[i]
|
||||
else:
|
||||
spliceImpl(s, a, L, b)
|
||||
spliceSeqImpl(s, a, L, b)
|
||||
|
||||
@@ -224,13 +224,14 @@ proc cmpStringPtrs(a, b: ptr SmallString): int {.inline.} =
|
||||
minLen - AlwaysAvail)
|
||||
if result == 0: result = aslen - bslen
|
||||
return
|
||||
# At least one is long. Hot prefix: inlinePtr[0..AlwaysAvail-1] mirrors heap data.
|
||||
let pfxLen = min(min(aslen, bslen), AlwaysAvail)
|
||||
result = cmpInlineBytes(inlinePtrOf(a), inlinePtrOf(b), pfxLen)
|
||||
if result != 0: return
|
||||
# At least one is long. Hot prefix mirrors heap data, but only up to fullLen:
|
||||
# shrinking can leave stale bytes in the inline cache past the logical length.
|
||||
let la = if aslen > PayloadSize: a.more.fullLen else: aslen
|
||||
let lb = if bslen > PayloadSize: b.more.fullLen else: bslen
|
||||
let minLen = min(la, lb)
|
||||
let pfxLen = min(minLen, AlwaysAvail)
|
||||
result = cmpInlineBytes(inlinePtrOf(a), inlinePtrOf(b), pfxLen)
|
||||
if result != 0: return
|
||||
if minLen <= AlwaysAvail:
|
||||
result = la - lb
|
||||
return
|
||||
|
||||
13
tests/ccgbugs2/m25294/c.nim
Normal file
13
tests/ccgbugs2/m25294/c.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
template a(T: type): int =
|
||||
when T is uint64: 1 else: 2
|
||||
|
||||
type
|
||||
M*[T] = object
|
||||
data*: seq[T]
|
||||
b: seq[int]
|
||||
indices*: array[a(T), int64]
|
||||
U = distinct uint64
|
||||
D* = object
|
||||
c: M[U]
|
||||
v: array[180000, int64]
|
||||
g*: M[uint64]
|
||||
5
tests/ccgbugs2/m25294/t.nim
Normal file
5
tests/ccgbugs2/m25294/t.nim
Normal file
@@ -0,0 +1,5 @@
|
||||
import ./c
|
||||
|
||||
proc p*(): D =
|
||||
let c = M[uint64](data: @[0], indices: [1])
|
||||
result = D(g: c)
|
||||
7
tests/ccgbugs2/m25800.h
Normal file
7
tests/ccgbugs2/m25800.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/*TYPESECTION*/
|
||||
struct CppRef {
|
||||
int* data;
|
||||
CppRef() : data(new int(42)) {}
|
||||
~CppRef() { delete data; data = nullptr; }
|
||||
void reset() { delete data; data = nullptr; }
|
||||
};
|
||||
18
tests/ccgbugs2/t25294.nim
Normal file
18
tests/ccgbugs2/t25294.nim
Normal file
@@ -0,0 +1,18 @@
|
||||
discard """
|
||||
matrix: "--mm:refc; --mm:orc"
|
||||
"""
|
||||
|
||||
import ./m25294/[c, t]
|
||||
|
||||
block:
|
||||
let a = new D
|
||||
a[] = p()
|
||||
discard a[]
|
||||
block:
|
||||
let a = new D
|
||||
a[] = p()
|
||||
discard a[]
|
||||
block:
|
||||
let a = new D
|
||||
a[] = p()
|
||||
discard a[]
|
||||
23
tests/ccgbugs2/t25800.nim
Normal file
23
tests/ccgbugs2/t25800.nim
Normal file
@@ -0,0 +1,23 @@
|
||||
discard """
|
||||
cmd: "nim cpp $file"
|
||||
action: "compile"
|
||||
"""
|
||||
|
||||
# Bug Report 1: {.importcpp.} on =wasMoved generates invalid preprocessor directive #.
|
||||
|
||||
|
||||
type CppRef* {.importcpp, bycopy, noInit, header: "m25800.h".} = object
|
||||
|
||||
proc `=destroy`(x: var CppRef) {.importcpp: "#.~CppRef()".}
|
||||
proc `=wasMoved`(x: var CppRef) {.importcpp: "#.reset()".}
|
||||
proc `=copy`(dest: var CppRef; src: CppRef) {.importcpp: "dest = src".}
|
||||
proc `=sink`(dest: var CppRef; src: CppRef) {.importcpp: "dest = std::move(src)".}
|
||||
|
||||
# This triggers =wasMoved when passing to sink parameter
|
||||
proc consume(x: sink CppRef) = discard
|
||||
|
||||
proc test() =
|
||||
var x: CppRef
|
||||
consume(move(x)) # =wasMoved MUST be called here after the move
|
||||
|
||||
test()
|
||||
10
tests/compiler/tcmdline_import_std_prefix.nim
Normal file
10
tests/compiler/tcmdline_import_std_prefix.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
discard """
|
||||
matrix: "-d:nimPreviewSlimSystem --warning:StdPrefix:on --warningAsError:StdPrefix:on --import:std/objectdollar"
|
||||
output: "(a: 23, b: 45)"
|
||||
"""
|
||||
|
||||
type Foo = object
|
||||
a, b: int
|
||||
|
||||
let x = Foo(a: 23, b: 45)
|
||||
echo x
|
||||
@@ -12,3 +12,51 @@ proc foo =
|
||||
doAssert m.id == 999
|
||||
|
||||
foo()
|
||||
|
||||
block:
|
||||
type Foo = object
|
||||
a,b,c: int
|
||||
|
||||
var dest: Foo
|
||||
|
||||
# proc `=wasMoved`(x: var Foo) =
|
||||
# debugEcho "wasMoved called"
|
||||
|
||||
proc main() =
|
||||
var x = Foo(a:11, b:12, c:13)
|
||||
dest = move(x)
|
||||
|
||||
main()
|
||||
|
||||
block:
|
||||
type Foo = object
|
||||
a,b,c: int
|
||||
|
||||
var dest: Foo
|
||||
|
||||
proc `=wasMoved`(x: var Foo) =
|
||||
discard "wasMoved called"
|
||||
|
||||
proc main() =
|
||||
var x = Foo(a:11, b:12, c:13)
|
||||
dest = move(x)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
import std/threadpool
|
||||
|
||||
block:
|
||||
type Foo = object
|
||||
data: string
|
||||
|
||||
proc `=wasMoved`(x: var Foo) =
|
||||
discard
|
||||
|
||||
proc work(x: Foo) =
|
||||
discard
|
||||
|
||||
var x = Foo(data: "hello")
|
||||
spawn work(x)
|
||||
sync()
|
||||
|
||||
|
||||
13
tests/errmsgs/tsso_string_index_var.nim
Normal file
13
tests/errmsgs/tsso_string_index_var.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
discard """
|
||||
cmd: "nim check --strings:sso --mm:orc --hints:off $file"
|
||||
action: "reject"
|
||||
nimout: '''
|
||||
tsso_string_index_var.nim(13, 12) Error: expression 's[0]' is immutable, not 'var'
|
||||
'''
|
||||
"""
|
||||
|
||||
proc passByVar(c: var char) =
|
||||
c = 'x'
|
||||
|
||||
var s = "abc"
|
||||
passByVar(s[0])
|
||||
@@ -241,3 +241,12 @@ proc main() =
|
||||
|
||||
static: main()
|
||||
main()
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/18583
|
||||
# $ separator must be emitted even when the item's string repr is empty
|
||||
type EmptyStr18583 = object
|
||||
proc `$`(x: EmptyStr18583): string = ""
|
||||
|
||||
block:
|
||||
var d = [EmptyStr18583(), EmptyStr18583()].toDeque
|
||||
doAssert $d == "[, ]", "got: " & $d
|
||||
|
||||
@@ -104,3 +104,15 @@ template main() =
|
||||
|
||||
static: main()
|
||||
main()
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/18583
|
||||
type EmptyStr18583HeapQ = object
|
||||
proc `$`(x: EmptyStr18583HeapQ): string = ""
|
||||
proc `<`(a, b: EmptyStr18583HeapQ): bool = false
|
||||
|
||||
block:
|
||||
var h = initHeapQueue[EmptyStr18583HeapQ]()
|
||||
push(h, EmptyStr18583HeapQ())
|
||||
push(h, EmptyStr18583HeapQ())
|
||||
let s = $h
|
||||
doAssert s == "[, ]", "got: " & s
|
||||
|
||||
@@ -287,3 +287,14 @@ template main =
|
||||
|
||||
static: main()
|
||||
main()
|
||||
|
||||
# https://github.com/nim-lang/Nim/issues/18583
|
||||
type EmptyStr18583List = object
|
||||
proc `$`(x: EmptyStr18583List): string = ""
|
||||
|
||||
block:
|
||||
var L: SinglyLinkedList[EmptyStr18583List]
|
||||
L.prepend(EmptyStr18583List())
|
||||
L.prepend(EmptyStr18583List())
|
||||
let s = $L
|
||||
doAssert s == "[, ]", "got: " & s
|
||||
|
||||
@@ -259,6 +259,11 @@ block:
|
||||
doAssert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+")
|
||||
doAssert(not match("456678", peg"(\letter)+"))
|
||||
|
||||
block:
|
||||
doAssert match("CAFÉ", peg"\i café")
|
||||
doAssert match("Café", peg"\i café")
|
||||
doAssert "two cafés: Café and CAFÉ".findAll(peg"\i café").len == 3
|
||||
|
||||
doAssert("var1 = key; var2 = key2".replacef(
|
||||
peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") ==
|
||||
"var1<-keykey;var2<-key2key2")
|
||||
|
||||
@@ -544,6 +544,12 @@ proc main() =
|
||||
var x = 5
|
||||
doAssert fmt"{(x=7;123.456)=:13e}" == "(x=7;123.456)= 1.234560e+02"
|
||||
doAssert x==7
|
||||
|
||||
block: # binary operators in interpolated expressions
|
||||
let n = 1
|
||||
doAssert &"{n-1}" == "0"
|
||||
doAssert fmt"{n-1}" == "0"
|
||||
|
||||
block: #curly bracket expressions and tuples
|
||||
proc formatValue(result: var string; value:Table|bool|JsonNode; specifier:string) = result.add $value
|
||||
|
||||
|
||||
Reference in New Issue
Block a user