Showing with 1,478 additions and 312 deletions.
  1. +3 −3 .github/workflows/ci_bench.yml
  2. +3 −3 .github/workflows/ci_packages.yml
  3. +3 −3 .github/workflows/ci_publish.yml
  4. +1 −0 compiler/ast.nim
  5. +7 −2 compiler/ccgexprs.nim
  6. +18 −8 compiler/cgen.nim
  7. +2 −2 compiler/docgen.nim
  8. +0 −3 compiler/hlo.nim
  9. +6 −2 compiler/injectdestructors.nim
  10. +1 −2 compiler/liftdestructors.nim
  11. +3 −0 compiler/lowerings.nim
  12. +1 −0 compiler/modulegraphs.nim
  13. +19 −1 compiler/options.nim
  14. +60 −5 compiler/sem.nim
  15. +12 −3 compiler/semcall.nim
  16. +1 −6 compiler/semexprs.nim
  17. +11 −0 compiler/semgnrc.nim
  18. +3 −2 compiler/semmagic.nim
  19. +9 −3 compiler/semstmts.nim
  20. +7 −1 compiler/semtempl.nim
  21. +1 −0 compiler/semtypes.nim
  22. +3 −2 compiler/semtypinst.nim
  23. +3 −1 compiler/sigmatch.nim
  24. +92 −46 compiler/suggest.nim
  25. +20 −5 compiler/types.nim
  26. +17 −2 compiler/vm.nim
  27. +1 −1 compiler/vmdef.nim
  28. +52 −16 compiler/vmgen.nim
  29. +2 −2 config/nimdoc.cfg
  30. +2 −0 lib/impure/nre.nim
  31. +1 −0 lib/posix/posix_linux_amd64_consts.nim
  32. +2 −2 lib/posix/posix_other.nim
  33. +1 −0 lib/posix/posix_other_consts.nim
  34. +4 −12 lib/pure/base64.nim
  35. +22 −22 lib/pure/collections/lists.nim
  36. +2 −2 lib/pure/colors.nim
  37. +2 −0 lib/pure/concurrency/threadpool.nim
  38. +14 −6 lib/pure/hashes.nim
  39. +38 −9 lib/pure/nativesockets.nim
  40. +2 −2 lib/pure/os.nim
  41. +1 −1 lib/pure/pegs.nim
  42. +4 −4 lib/system.nim
  43. +1 −1 lib/system/compilation.nim
  44. +3 −1 lib/system/jssys.nim
  45. +1 −1 lib/system/mm/malloc.nim
  46. +2 −5 lib/system/seqs_v2.nim
  47. +3 −1 lib/system/sets.nim
  48. +64 −43 lib/system/strs_v2.nim
  49. +22 −0 lib/system/sysstr.nim
  50. +4 −2 nimdoc/rsttester.nim
  51. +4 −2 nimdoc/tester.nim
  52. +83 −5 nimsuggest/nimsuggest.nim
  53. +34 −0 nimsuggest/procmonitor.nim
  54. +15 −0 nimsuggest/tests/tuse_enum.nim
  55. +10 −10 testament/important_packages.nim
  56. +16 −0 tests/align/talign.nim
  57. +9 −6 tests/arc/tcomputedgoto.nim
  58. +7 −4 tests/arc/tcomputedgotocopy.nim
  59. +17 −0 tests/collections/tseq.nim
  60. +12 −2 tests/controlflow/tunreachable.nim
  61. +1 −1 tests/effects/teffects1.nim
  62. +36 −0 tests/exprs/t22604.nim
  63. +7 −0 tests/generics/m22373a.nim
  64. +18 −0 tests/generics/m22373b.nim
  65. +25 −0 tests/generics/t17509.nim
  66. +16 −0 tests/generics/t22373.nim
  67. +20 −1 tests/generics/timplicit_and_explicit.nim
  68. +5 −0 tests/generics/timports.nim
  69. +11 −0 tests/generics/treentranttypes.nim
  70. +16 −0 tests/generics/tuninstantiated_failure.nim
  71. +62 −0 tests/generics/tuninstantiatedgenericcalls.nim
  72. +79 −0 tests/iter/t22619.nim
  73. +31 −0 tests/macros/tmacros_various.nim
  74. +7 −4 tests/misc/trunner.nim
  75. +32 −0 tests/objects/twhen1.nim
  76. +3 −0 tests/statictypes/t5780.nim
  77. +4 −0 tests/stdlib/tbase64.nim
  78. +13 −0 tests/stdlib/tmacros.nim
  79. +2 −1 tests/system/tensuremove.nim
  80. +1 −1 tests/system/tensuremove2.nim
  81. +2 −1 tests/system/tgcnone.nim
  82. +32 −0 tests/template/mdotcall.nim
  83. +8 −0 tests/template/t21532.nim
  84. +12 −0 tests/template/tdotcall.nim
  85. +4 −0 tests/template/template_issues.nim
  86. +36 −0 tests/template/template_various.nim
  87. +80 −0 tests/template/tgenericparam.nim
  88. +17 −8 tests/template/tobjectdeclfield.nim
  89. +32 −0 tests/types/t5648.nim
  90. +15 −26 tests/types/tissues_types.nim
  91. +32 −0 tests/vm/tnoreturn.nim
  92. +18 −0 tests/vm/ttypedesc.nim
  93. +3 −0 tests/vm/tunsupportedintfloatcast.nim
  94. +34 −2 tests/vm/tvmmisc.nim
  95. +1 −0 tools/detect/detect.nim
6 changes: 3 additions & 3 deletions .github/workflows/ci_bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
with:
fetch-depth: 2

- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'

- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci_packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ jobs:
with:
fetch-depth: 2

- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'

- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
with:
fetch-depth: 2

- name: 'Install node.js 16.x'
uses: actions/setup-node@v3
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'

- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
Expand Down
1 change: 1 addition & 0 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ type
info*: TLineInfo
when defined(nimsuggest):
endInfo*: TLineInfo
hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
owner*: PSym
flags*: TSymFlags
ast*: PNode # syntax tree of proc, iterator, etc.:
Expand Down
9 changes: 7 additions & 2 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
getSeqPayloadType(p.module, seqtype),
])
else:
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false) # bug #22560
putIntoDest(p, d, e, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
Expand Down Expand Up @@ -1550,6 +1551,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =

var tmp: TLoc
var r: Rope
let needsZeroMem = p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc} or nfAllFieldsSet notin e.flags
if useTemp:
getTemp(p, t, tmp)
r = rdLoc(tmp)
Expand All @@ -1558,10 +1560,13 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
t = t.lastSon.skipTypes(abstractInstOwned)
r = "(*$1)" % [r]
gcUsage(p.config, e)
else:
elif needsZeroMem:
constructLoc(p, tmp)
else:
genObjectInit(p, cpsStmts, t, tmp, constructObj)
else:
resetLoc(p, d)
if needsZeroMem: resetLoc(p, d)
else: genObjectInit(p, cpsStmts, d.t, d, if isRef: constructRefObj else: constructObj)
r = rdLoc(d)
discard getTypeDesc(p.module, t)
let ty = getUniqueType(t)
Expand Down
26 changes: 18 additions & 8 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,10 @@ proc genLineDir(p: BProc, t: PNode) =
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
if freshLine:
if lastFileIndex == t.info.fileIndex:
linefmt(p, cpsStmts, "nimln_($1);\n",
linefmt(p, cpsStmts, "nimln_($1);",
[line])
else:
linefmt(p, cpsStmts, "nimlf_($1, $2);\n",
linefmt(p, cpsStmts, "nimlf_($1, $2);",
[line, quotedFilename(p.config, t.info)])

proc accessThreadLocalVar(p: BProc, s: PSym)
Expand Down Expand Up @@ -986,22 +986,26 @@ proc closureSetup(p: BProc, prc: PSym) =
linefmt(p, cpsStmts, "$1 = ($2) ClE_0;$n",
[rdLoc(env.loc), getTypeDesc(p.module, env.typ)])

const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs

proc containsResult(n: PNode): bool =
result = false
case n.kind
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkFormalParams:
of succ(nkEmpty)..pred(nkSym), succ(nkSym)..nkNilLit, harmless:
discard
of nkReturnStmt:
for i in 0..<n.len:
if containsResult(n[i]): return true
result = n.len > 0 and n[0].kind == nkEmpty
of nkSym:
if n.sym.kind == skResult:
result = true
else:
for i in 0..<n.len:
if containsResult(n[i]): return true

const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs

proc easyResultAsgn(n: PNode): PNode =
case n.kind
of nkStmtList, nkStmtListExpr:
Expand Down Expand Up @@ -1175,7 +1179,13 @@ proc genProcAux*(m: BModule, prc: PSym) =
# declare the result symbol:
assignLocalVar(p, resNode)
assert(res.loc.r != "")
initLocalVar(p, res, immediateAsgn=false)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc} and
allPathsAsgnResult(procBody) == InitSkippable:
# In an ideal world the codegen could rely on injectdestructors doing its job properly
# and then the analysis step would not be required.
discard "result init optimized out"
else:
initLocalVar(p, res, immediateAsgn=false)
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
elif sfConstructor in prc.flags:
fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)
Expand Down
4 changes: 2 additions & 2 deletions compiler/docgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
"moduledesc", d.modDescFinal, "date", getDateStr(), "time", getClockStr(),
"content", content, "author", d.meta[metaAuthor],
"version", esc(d.target, d.meta[metaVersion]), "analytics", d.analytics,
"deprecationMsg", d.modDeprecationMsg]
"deprecationMsg", d.modDeprecationMsg, "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
else:
code = content
result = code
Expand Down Expand Up @@ -1907,7 +1907,7 @@ proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"")
"title", "Index",
"subtitle", "", "tableofcontents", "", "moduledesc", "",
"date", getDateStr(), "time", getClockStr(),
"content", content, "author", "", "version", "", "analytics", ""]
"content", content, "author", "", "version", "", "analytics", "", "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
# no analytics because context is not available

try:
Expand Down
3 changes: 0 additions & 3 deletions compiler/hlo.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
# This include implements the high level optimization pass.
# included from sem.nim

when defined(nimPreviewSlimSystem):
import std/assertions

proc hlo(c: PContext, n: PNode): PNode

proc evalPattern(c: PContext, n, orig: PNode): PNode =
Expand Down
8 changes: 6 additions & 2 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ proc isCursor(n: PNode): bool =
template isUnpackedTuple(n: PNode): bool =
## we move out all elements of unpacked tuples,
## hence unpacked tuples themselves don't need to be destroyed
(n.kind == nkSym and n.sym.kind == skTemp and n.sym.typ.kind == tyTuple)
## except it's already a cursor
(n.kind == nkSym and n.sym.kind == skTemp and
n.sym.typ.kind == tyTuple and sfCursor notin n.sym.flags)

proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string; inferredFromCopy = false) =
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
Expand Down Expand Up @@ -850,7 +852,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
result[i][1] = p(n[i][1], c, s, m)
else:
result[i] = p(n[i], c, s, m)
if mode == normal and isRefConstr:
if mode == normal and (isRefConstr or (hasDestructor(c, t) and
getAttachedOp(c.graph, t, attachedDestructor) != nil and
sfOverridden in getAttachedOp(c.graph, t, attachedDestructor).flags)):
result = ensureDestruction(result, n, c, s)
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
Expand Down
3 changes: 1 addition & 2 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
if c.filterDiscriminator != nil: return
let f = n.sym
let b = if c.kind == attachedTrace: y else: y.dotField(f)
if (sfCursor in f.flags and f.typ.skipTypes(abstractInst).kind in {tyRef, tyProc} and
c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcHooks}) or
if (sfCursor in f.flags and c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcHooks}) or
enforceDefaultOp:
defaultOp(c, f.typ, body, x.dotField(f), b)
else:
Expand Down
3 changes: 3 additions & 0 deletions compiler/lowerings.nim
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
field.typ = t
if s.kind in {skLet, skVar, skField, skForVar}:
#field.bitsize = s.bitsize
field.alignment = s.alignment
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = obj.n.len
Expand Down
1 change: 1 addition & 0 deletions compiler/modulegraphs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type
SymInfoPair* = object
sym*: PSym
info*: TLineInfo
isDecl*: bool

PipelinePass* = enum
NonePass
Expand Down
20 changes: 19 additions & 1 deletion compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ type
IdeCmd* = enum
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints

Feature* = enum ## experimental features; DO NOT RENAME THESE!
dotOperators,
Expand Down Expand Up @@ -280,9 +280,24 @@ type
version*: int
endLine*: uint16
endCol*: int
inlayHintInfo*: SuggestInlayHint

Suggestions* = seq[Suggest]

SuggestInlayHintKind* = enum
sihkType = "Type",
sihkParameter = "Parameter"

SuggestInlayHint* = ref object
kind*: SuggestInlayHintKind
line*: int # Starts at 1
column*: int # Starts at 0
label*: string
paddingLeft*: bool
paddingRight*: bool
allowInsert*: bool
tooltip*: string

ProfileInfo* = object
time*: float
count*: int
Expand Down Expand Up @@ -417,6 +432,8 @@ type
expandNodeResult*: string
expandPosition*: TLineInfo

clientProcessId*: int


proc parseNimVersion*(a: string): NimVer =
# could be moved somewhere reusable
Expand Down Expand Up @@ -1057,6 +1074,7 @@ proc `$`*(c: IdeCmd): string =
of ideRecompile: "recompile"
of ideChanged: "changed"
of ideType: "type"
of ideInlayHints: "inlayHints"

proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
Expand Down
65 changes: 60 additions & 5 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ when not defined(leanCompiler):
import spawn

when defined(nimPreviewSlimSystem):
import std/formatfloat
import std/[
formatfloat,
assertions,
]

# implementation

Expand Down Expand Up @@ -206,12 +209,58 @@ proc commonType*(c: PContext; x, y: PType): PType =
result.addSonSkipIntLit(r, c.idgen)

proc endsInNoReturn(n: PNode): bool =
# check if expr ends in raise exception or call of noreturn proc
## check if expr ends the block like raising or call of noreturn procs do
result = false # assume it does return

template checkBranch(branch) =
if not endsInNoReturn(branch):
# proved a branch returns
return false

var it = n
# skip these beforehand, no special handling needed
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
it = it.lastSon
result = it.kind in nkLastBlockStmts or
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags

case it.kind
of nkIfStmt:
var hasElse = false
for branch in it:
checkBranch:
if branch.len == 2:
branch[1]
elif branch.len == 1:
hasElse = true
branch[0]
else:
raiseAssert "Malformed `if` statement during endsInNoReturn"
# none of the branches returned
result = hasElse # Only truly a no-return when it's exhaustive
of nkCaseStmt:
for i in 1 ..< it.len:
let branch = it[i]
checkBranch:
case branch.kind
of nkOfBranch:
branch[^1]
of nkElifBranch:
branch[1]
of nkElse:
branch[0]
else:
raiseAssert "Malformed `case` statement in endsInNoReturn"
# none of the branches returned
result = true
of nkTryStmt:
checkBranch(it[0])
for i in 1 ..< it.len:
let branch = it[i]
checkBranch(branch[^1])
# none of the branches returned
result = true
else:
result = it.kind in nkLastBlockStmts or
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags

proc commonType*(c: PContext; x: PType, y: PNode): PType =
# ignore exception raising branches in case/if expressions
Expand Down Expand Up @@ -462,7 +511,13 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# we now know the supplied arguments
var paramTypes = newIdTable()
for param, value in genericParamsInMacroCall(s, call):
idTablePut(paramTypes, param.typ, value.typ)
var givenType = value.typ
# the sym nodes used for the supplied generic arguments for
# templates and macros leave type nil so regular sem can handle it
# in this case, get the type directly from the sym
if givenType == nil and value.kind == nkSym and value.sym.typ != nil:
givenType = value.sym.typ
idTablePut(paramTypes, param.typ, givenType)

retType = generateTypeInstance(c, paramTypes,
macroResult.info, retType)
Expand Down
15 changes: 12 additions & 3 deletions compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,12 @@ proc semResolvedCall(c: PContext, x: TCandidate,
else:
x.call.add c.graph.emptyNode
of skType:
x.call.add newSymNode(s, n.info)
var tn = newSymNode(s, n.info)
# this node will be used in template substitution,
# pretend this is an untyped node and let regular sem handle the type
# to prevent problems where a generic parameter is treated as a value
tn.typ = nil
x.call.add tn
else:
internalAssert c.config, false

Expand Down Expand Up @@ -665,14 +670,18 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
onUse(info, s)
result = newSymNode(newInst, info)

proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
proc setGenericParams(c: PContext, n: PNode) =
## sems generic params in subscript expression
for i in 1..<n.len:
let e = semExprWithType(c, n[i])
if e.typ == nil:
n[i].typ = errorType(c)
else:
n[i].typ = e.typ.skipTypes({tyTypeDesc})

proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
setGenericParams(c, n)
var s = s
var a = n[0]
if a.kind == nkSym:
Expand Down
Loading