From 39fbd30513fbabb8ff189dcb60991a08f912f6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8F=A1=E7=8C=AB=E7=8C=AB?= <164346864@qq.com> Date: Sat, 18 Nov 2023 05:06:46 +0800 Subject: [PATCH 01/10] Fix OSError `errorCode` field is not assigned a value (#22954) In this PR, the following changes were made: 1. Replaced `raise newException(OSError, osErrorMsg(errno))` in batches with `raiseOSError(errcode)`. 2. Replaced `newException(OSError, osErrorMsg(errno))` in batches with `newOSError(errcode)`. There are still some places that have not been replaced. After checking, they are not system errors in the traditional sense. ```nim proc dlclose(lib: LibHandle) = raise newException(OSError, "dlclose not implemented on Nintendo Switch!") ``` ```nim if not fileExists(result) and not dirExists(result): # consider using: `raiseOSError(osLastError(), result)` raise newException(OSError, "file '" & result & "' does not exist") ``` ```nim proc paramStr*(i: int): string = raise newException(OSError, "paramStr is not implemented on Genode") ``` --- lib/posix/posix_utils.nim | 20 +++++++++---------- lib/pure/asyncdispatch.nim | 38 ++++++++++++++++++------------------- lib/pure/asyncfile.nim | 32 +++++++++++++++---------------- lib/pure/asyncnet.nim | 4 ++-- lib/pure/dynlib.nim | 2 +- tests/async/twinasyncrw.nim | 12 ++++++------ 6 files changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/posix/posix_utils.nim b/lib/posix/posix_utils.nim index b12950f7bbf95..0c668246fc04c 100644 --- a/lib/posix/posix_utils.nim +++ b/lib/posix/posix_utils.nim @@ -34,7 +34,7 @@ proc uname*(): Uname = var u: Utsname if uname(u) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) result.sysname = charArrayToString u.sysname result.nodename = charArrayToString u.nodename @@ -45,17 +45,17 @@ proc uname*(): Uname = proc fsync*(fd: int) = ## synchronize a file's buffer cache to the storage device if fsync(fd.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc stat*(path: string): Stat = ## Returns file status in a `Stat` structure if stat(path.cstring, result) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryLock*(a1: pointer, a2: int) = ## Locks pages starting from a1 for a1 bytes and prevent them from being swapped. if mlock(a1, a2) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryLockAll*(flags: int) = ## Locks all memory for the running process to prevent swapping. @@ -65,23 +65,23 @@ proc memoryLockAll*(flags: int) = ## memoryLockAll(MCL_CURRENT or MCL_FUTURE) ## ``` if mlockall(flags.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryUnlock*(a1: pointer, a2: int) = ## Unlock pages starting from a1 for a1 bytes and allow them to be swapped. if munlock(a1, a2) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc memoryUnlockAll*() = ## Unlocks all memory for the running process to allow swapping. if munlockall() != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc sendSignal*(pid: Pid, signal: int) = ## Sends a signal to a running process by calling `kill`. ## Raise exception in case of failure e.g. process not running. if kill(pid, signal.cint) != 0: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc mkstemp*(prefix: string, suffix=""): (string, File) = ## Creates a unique temporary file from a prefix string. A six-character string @@ -103,14 +103,14 @@ proc mkstemp*(prefix: string, suffix=""): (string, File) = var f: File if open(f, fd, fmReadWrite): return ($tmpl, f) - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) proc mkdtemp*(prefix: string): string = ## Creates a unique temporary directory from a prefix string. Adds a six chars suffix. ## The directory is created with permissions 0700. Returns the directory name. var tmpl = cstring(prefix & "XXXXXX") if mkdtemp(tmpl) == nil: - raise newException(OSError, $strerror(errno)) + raiseOSError(OSErrorCode(errno)) return $tmpl proc osReleaseFile*(): Config {.since: (1, 5).} = diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index e009fee2de3e2..126db7a7f29cc 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -533,7 +533,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(errcode): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if dataBuf.buf != nil: dealloc dataBuf.buf dataBuf.buf = nil @@ -551,7 +551,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) elif ret == 0: # Request completed immediately. if bytesReceived != 0: @@ -603,7 +603,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(errcode): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if dataBuf.buf != nil: dataBuf.buf = nil ) @@ -619,7 +619,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) elif ret == 0: # Request completed immediately. if bytesReceived != 0: @@ -667,7 +667,7 @@ when defined(windows) or defined(nimdoc): if flags.isDisconnectionError(err): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: retFuture.complete() # We don't deallocate `ol` here because even though this completed @@ -702,7 +702,7 @@ when defined(windows) or defined(nimdoc): if errcode == OSErrorCode(-1): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let ret = WSASendTo(socket.SocketHandle, addr dataBuf, 1, addr bytesSent, @@ -712,7 +712,7 @@ when defined(windows) or defined(nimdoc): let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: retFuture.complete() # We don't deallocate `ol` here because even though this completed @@ -746,7 +746,7 @@ when defined(windows) or defined(nimdoc): else: # datagram sockets don't have disconnection, # so we can just raise an exception - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let res = WSARecvFrom(socket.SocketHandle, addr dataBuf, 1, @@ -757,7 +757,7 @@ when defined(windows) or defined(nimdoc): let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. if bytesReceived != 0: @@ -808,7 +808,7 @@ when defined(windows) or defined(nimdoc): else: retFuture.complete(newAcceptFut.read) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) template completeAccept() {.dirty.} = var listenSock = socket @@ -1468,7 +1468,7 @@ else: if flags.isDisconnectionError(lastError): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -1497,7 +1497,7 @@ else: if flags.isDisconnectionError(lastError): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -1563,7 +1563,7 @@ else: let lastError = osLastError() if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -1589,7 +1589,7 @@ else: let lastError = osLastError() if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false else: @@ -1630,7 +1630,7 @@ else: if flags.isDisconnectionError(lastError): return false else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: try: let address = getAddrString(cast[ptr SockAddr](addr sockAddress)) @@ -1763,7 +1763,7 @@ when defined(windows) or defined(nimdoc): socket.SocketHandle.setSockOptInt(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, 1) # 15022 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr, @@ -1781,7 +1781,7 @@ when defined(windows) or defined(nimdoc): # With ERROR_IO_PENDING `ol` will be deallocated in `poll`, # and the future will be completed/failed there, too. GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): owned(Future[void]) = let retFuture = newFuture[void]("doConnect") @@ -1798,7 +1798,7 @@ else: # interrupted, keep waiting return false else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true let ret = connect(socket.SocketHandle, @@ -1812,7 +1812,7 @@ else: if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: addWrite(socket, cb) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped, protocol: Protocol = IPPROTO_RAW) = diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim index 185d59fa69728..0f650434208e9 100644 --- a/lib/pure/asyncfile.nim +++ b/lib/pure/asyncfile.nim @@ -146,7 +146,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if errcode.int32 == ERROR_HANDLE_EOF: retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) ol.offset = DWORD(f.offset and 0xffffffff) ol.offsetHigh = DWORD(f.offset shr 32) @@ -162,7 +162,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = # This happens in Windows Server 2003 retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesRead: DWORD @@ -173,7 +173,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if err.int32 == ERROR_HANDLE_EOF: retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesRead > 0 assert bytesRead <= size @@ -186,7 +186,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -228,7 +228,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if errcode.int32 == ERROR_HANDLE_EOF: retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if buffer != nil: dealloc buffer buffer = nil @@ -251,7 +251,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = # This happens in Windows Server 2003 retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesRead: DWORD @@ -262,7 +262,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if err.int32 == ERROR_HANDLE_EOF: retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesRead > 0 assert bytesRead <= size @@ -279,7 +279,7 @@ proc read*(f: AsyncFile, size: int): Future[string] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. elif res == 0: @@ -350,7 +350,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = assert bytesCount == size.int32 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) ) # passing -1 here should work according to MSDN, but doesn't. For more # information see @@ -367,14 +367,14 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = let err = osLastError() if err.int32 != ERROR_IO_PENDING: GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesWritten: DWORD let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL) if not overlappedRes.bool: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesWritten == size.int32 retFuture.complete() @@ -389,7 +389,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: @@ -423,7 +423,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = assert bytesCount == data.len.int32 retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(errcode))) + retFuture.fail(newOSError(errcode)) if buffer != nil: dealloc buffer buffer = nil @@ -442,14 +442,14 @@ proc write*(f: AsyncFile, data: string): Future[void] = dealloc buffer buffer = nil GC_unref(ol) - retFuture.fail(newException(OSError, osErrorMsg(err))) + retFuture.fail(newOSError(err)) else: # Request completed immediately. var bytesWritten: DWORD let overlappedRes = getOverlappedResult(f.fd.Handle, cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL) if not overlappedRes.bool: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: assert bytesWritten == data.len.int32 retFuture.complete() @@ -470,7 +470,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = if res < 0: let lastError = osLastError() if lastError.int32 != EAGAIN: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: result = false # We still want this callback to be called. else: diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index f69c5bc73b99f..d8dc7a798bd96 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -682,7 +682,7 @@ when defined(posix) and not useNimNetLite: elif ret == EINTR: return false else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true var socketAddr = makeUnixAddr(path) @@ -696,7 +696,7 @@ when defined(posix) and not useNimNetLite: if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: addWrite(AsyncFD(socket.fd), cb) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) proc bindUnix*(socket: AsyncSocket, path: string) {. tags: [ReadIOEffect].} = diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index 1980129af2004..a162fe37fa92a 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -148,7 +148,7 @@ elif defined(genode): # template raiseErr(prc: string) = - raise newException(OSError, prc & " not implemented, compile with POSIX suport") + raise newException(OSError, prc & " not implemented, compile with POSIX support") proc dlclose(lib: LibHandle) = raiseErr(OSError, "dlclose") diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim index ad27ca38f0d07..f0a8f6a62d974 100644 --- a/tests/async/twinasyncrw.nim +++ b/tests/async/twinasyncrw.nim @@ -19,7 +19,7 @@ when defined(windows): retFuture.complete() return true else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true var aiList = getAddrInfo(address, port, domain) @@ -45,7 +45,7 @@ when defined(windows): freeAddrInfo(aiList) if not success: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) return retFuture proc winRecv*(socket: AsyncFD, size: int, @@ -63,7 +63,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) elif res == 0: # Disconnected retFuture.complete("") @@ -88,7 +88,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: retFuture.complete(res) # TODO: The following causes a massive slowdown. @@ -112,7 +112,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: written.inc(res) if res != netSize: @@ -136,7 +136,7 @@ when defined(windows): var client = nativesockets.accept(sock.SocketHandle, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen)) if client == osInvalidSocket: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: retFuture.complete((getAddrString(cast[ptr SockAddr](addr sockAddress)), client.AsyncFD)) From 09ea1b168fc66ec1f921cc0bd603606c5d7cf8e7 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sat, 18 Nov 2023 16:40:28 +0800 Subject: [PATCH 02/10] fixes #22947; static integers in quote do [backport] (#22948) fixes #22947 --- compiler/semexprs.nim | 2 +- tests/stdlib/tmacros.nim | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index e6983910de6d5..28d2647fdd22b 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2286,7 +2286,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode = for i in 1.. Date: Sat, 18 Nov 2023 23:21:01 +0800 Subject: [PATCH 03/10] let `InotifyEvent` type `sizeof`-able (#22958) Since the `InotifyEvent`s are receive through `read()`, user need the size of the type. --- lib/posix/inotify.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim index 109d3680e1f09..7bc1504e5c6c1 100644 --- a/lib/posix/inotify.nim +++ b/lib/posix/inotify.nim @@ -14,7 +14,8 @@ when defined(nimPreviewSlimSystem): # Structure describing an inotify event. type InotifyEvent* {.pure, final, importc: "struct inotify_event", - header: "".} = object ## An Inotify event. + header: "", + completeStruct.} = object ## An Inotify event. wd* {.importc: "wd".}: FileHandle ## Watch descriptor. mask* {.importc: "mask".}: uint32 ## Watch mask. cookie* {.importc: "cookie".}: uint32 ## Cookie to synchronize two events. From 4fc0027b57b83b30797c2439398dc9f6c38674b0 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sat, 18 Nov 2023 17:21:59 +0200 Subject: [PATCH 04/10] Introduced version 4 of the NimSuggest protocol. The InlayHints feature made V4 or later only. (#22953) Since nimsuggest now has a protocol version support detection via `--info:protocolVer`, the InlayHints feature can be moved to protocol V4. This way, the Nim language server can detect the nimsuggest version and avoid sending unsupported `InlayHints` commands to older nimsuggest versions. Related nim language server PR: https://github.com/nim-lang/langserver/pull/60 --- nimsuggest/nimsuggest.nim | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim index b483846ad910d..ca0f5112e1a01 100644 --- a/nimsuggest/nimsuggest.nim +++ b/nimsuggest/nimsuggest.nim @@ -43,7 +43,7 @@ when defined(windows): else: import posix -const HighestSuggestProtocolVersion = 3 +const HighestSuggestProtocolVersion = 4 const DummyEof = "!EOF!" const Usage = """ Nimsuggest - Tool to give every editor IDE like capabilities for Nim @@ -62,6 +62,7 @@ Options: --v1 use version 1 of the protocol; for backwards compatibility --v2 use version 2(default) of the protocol --v3 use version 3 of the protocol + --v4 use version 4 of the protocol --info:X information --info:nimVer return the Nim compiler version that nimsuggest uses internally --info:protocolVer return the newest protocol version that is supported @@ -510,7 +511,11 @@ proc execCmd(cmd: string; graph: ModuleGraph; cachedMsgs: CachedMsgs) = of "chkfile": conf.ideCmd = ideChkFile of "recompile": conf.ideCmd = ideRecompile of "type": conf.ideCmd = ideType - of "inlayhints": conf.ideCmd = ideInlayHints + of "inlayhints": + if conf.suggestVersion >= 4: + conf.ideCmd = ideInlayHints + else: + err() else: err() var dirtyfile = "" var orig = "" @@ -670,6 +675,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) = of "v1": conf.suggestVersion = 1 of "v2": conf.suggestVersion = 0 of "v3": conf.suggestVersion = 3 + of "v4": conf.suggestVersion = 4 of "info": case p.val.normalize of "protocolver": From 6c5283b194ec238c765c2e0a8f252db003643557 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:23:03 +0800 Subject: [PATCH 05/10] enable nimwc testing (#22960) ref https://github.com/ThomasTJdev/nim_websitecreator/pull/145 --- testament/important_packages.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testament/important_packages.nim b/testament/important_packages.nim index 5f5868cfd6ffa..c2b2476e7042d 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -119,7 +119,7 @@ pkg "nimquery" pkg "nimsl" pkg "nimsvg" pkg "nimterop", "nimble minitest", url = "https://github.com/nim-lang/nimterop" -pkg "nimwc", "nim c nimwc.nim", allowFailure = true +pkg "nimwc", "nim c nimwc.nim" pkg "nimx", "nim c test/main.nim", allowFailure = true pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter" pkg "norm", "testament r tests/common/tmodel.nim" From 5dafcf4957a225b1f015d131299e51735e7bb1d3 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 20 Nov 2023 00:52:42 +0800 Subject: [PATCH 06/10] =?UTF-8?q?fixes=20#22913;=20fixes=20#12985=20differ?= =?UTF-8?q?ently=20push-ing=20pragma=20exportc=20genera=E2=80=A6=20(#22941?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …tes invalid C identifiers fixes #22913 fixes #12985 differently `{.push.} now does not apply to generic instantiations` --- compiler/pragmas.nim | 2 +- compiler/seminst.nim | 6 ++++++ tests/pragmas/tpush.nim | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 53b4f53a8a878..d4817ce7a57bf 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1313,7 +1313,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo, if sym != nil and sym.kind != skModule: for it in c.optionStack: let o = it.otherPragmas - if not o.isNil and sfFromGeneric notin sym.flags: # see issue #12985 + if not o.isNil: pushInfoContext(c.config, info) var i = 0 while i < o.len: diff --git a/compiler/seminst.nim b/compiler/seminst.nim index dc25230c20b92..085769bddcd1b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -400,11 +400,17 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, entry.compilesId = c.compilesContextId addToGenericProcCache(c, fn, entry) c.generics.add(makeInstPair(fn, entry)) + # bug #12985 bug #22913 + # TODO: use the context of the declaration of generic functions instead + # TODO: consider fixing options as well + let otherPragmas = c.optionStack[^1].otherPragmas + c.optionStack[^1].otherPragmas = nil if n[pragmasPos].kind != nkEmpty: pragma(c, result, n[pragmasPos], allRoutinePragmas) if isNil(n[bodyPos]): n[bodyPos] = copyTree(getBody(c.graph, fn)) instantiateBody(c, n, fn.typ.n, result, fn) + c.optionStack[^1].otherPragmas = otherPragmas sideEffectsCheck(c, result) if result.magic notin {mSlice, mTypeOf}: # 'toOpenArray' is special and it is allowed to return 'openArray': diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim index 6d7eade91fc4a..6a95f1ca00186 100644 --- a/tests/pragmas/tpush.nim +++ b/tests/pragmas/tpush.nim @@ -38,3 +38,42 @@ proc main(): void = {.push staticBoundChecks: on.} main() + + +proc timnFoo[T](obj: T) {.noSideEffect.} = discard # BUG + +{.push exportc.} +proc foo1() = + var s1 = "bar" + timnFoo(s1) + var s2 = @[1] + timnFoo(s2) +{.pop.} + + +block: # bug #22913 + block: + type r = object + + template std[T](x: T) = + let ttt {.used.} = x + result = $ttt + + proc bar[T](x: T): string = + std(x) + + {.push exportc: "$1".} + proc foo(): r = + let s = bar(123) + {.pop.} + + discard foo() + + block: + type r = object + {.push exportc: "$1".} + proc foo2(): r = + let s = $result + {.pop.} + + discard foo2() From cecaf9c56b1240a44a4de837e03694a0c55ec379 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 20 Nov 2023 00:53:25 +0800 Subject: [PATCH 07/10] =?UTF-8?q?fixes=20#22939;=20fixes=20#16890;=20push?= =?UTF-8?q?=20should=20but=20doesn't=20apply=20to=20importc=20=E2=80=A6=20?= =?UTF-8?q?(#22944)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …var/let symbols fixes #22939 fixes #16890 Besides, it was applied to let/const/var with pragmas, now it is universally applied. ```nim {.push exportc.} proc foo = let bar = 12 echo bar {.pop.} ``` For example, the `bar` variable will be affected by `exportc`. --- compiler/semtypes.nim | 6 ++++++ tests/nimdoc/m13129.nim | 1 + tests/stdlib/tsugar.nim | 35 +++++++++++++++++++---------------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 65eaf1a89df2c..0a0050f2fa72f 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -528,6 +528,12 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, else: discard else: result = semIdentVis(c, kind, n, allowed) + case kind + of skField: implicitPragmas(c, result, n.info, fieldPragmas) + of skVar: implicitPragmas(c, result, n.info, varPragmas) + of skLet: implicitPragmas(c, result, n.info, letPragmas) + of skConst: implicitPragmas(c, result, n.info, constPragmas) + else: discard proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) = let ex = t[branchIndex][currentEx].skipConv diff --git a/tests/nimdoc/m13129.nim b/tests/nimdoc/m13129.nim index 145cae39ca9f9..34e118381d968 100644 --- a/tests/nimdoc/m13129.nim +++ b/tests/nimdoc/m13129.nim @@ -4,6 +4,7 @@ when defined(cpp): {.push header: "".} type Vector[T] {.importcpp: "std::vector".} = object + {.pop.} elif defined(js): proc endsWith*(s, suffix: cstring): bool {.noSideEffect,importjs: "#.endsWith(#)".} elif defined(c): diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim index c22a8608cd3e8..b9cbdd3e378f6 100644 --- a/tests/stdlib/tsugar.nim +++ b/tests/stdlib/tsugar.nim @@ -12,6 +12,23 @@ type # for capture test, ref #20679 FooCapture = ref object x: int +proc mainProc() = + block: # bug #16967 + var s = newSeq[proc (): int](5) + {.push exportc.} + proc bar() = + for i in 0 ..< s.len: + let foo = i + 1 + capture foo: + s[i] = proc(): int = foo + {.pop.} + + bar() + + for i, p in s.pairs: + let foo = i + 1 + doAssert p() == foo + template main() = block: # `=>` block: @@ -86,22 +103,6 @@ template main() = closure2 = () => (i, j) doAssert closure2() == (5, 3) - block: # bug #16967 - var s = newSeq[proc (): int](5) - {.push exportc.} - proc bar() = - for i in 0 ..< s.len: - let foo = i + 1 - capture foo: - s[i] = proc(): int = foo - {.pop.} - - bar() - - for i, p in s.pairs: - let foo = i + 1 - doAssert p() == foo - block: # issue #20679 # this should compile. Previously was broken as `var int` is an `nnkHiddenDeref` # which was not handled correctly @@ -299,6 +300,8 @@ template main() = test() + mainProc() + when not defined(js): # TODO fixme JS VM static: main() From 02be027e9b3c146c0a594c3ea4fae7152fd8b974 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 20 Nov 2023 21:12:13 +0100 Subject: [PATCH 08/10] IC: progress and refactorings (#22961) --- compiler/ast.nim | 34 +-- compiler/ccgtypes.nim | 18 +- compiler/cgmeth.nim | 2 +- compiler/closureiters.nim | 4 +- compiler/commands.nim | 1 + compiler/concepts.nim | 4 +- compiler/enumtostr.nim | 4 +- compiler/errorhandling.nim | 6 +- compiler/guards.nim | 4 +- compiler/ic/bitabs.nim | 6 + compiler/ic/cbackend.nim | 6 +- compiler/ic/dce.nim | 8 +- compiler/ic/ic.nim | 300 +++++++++++++++++---------- compiler/ic/integrity.nim | 12 +- compiler/ic/navigator.nim | 14 +- compiler/ic/packed_ast.nim | 157 ++++++-------- compiler/importer.nim | 3 +- compiler/injectdestructors.nim | 2 +- compiler/lambdalifting.nim | 10 +- compiler/liftdestructors.nim | 4 +- compiler/lowerings.nim | 4 +- compiler/magicsys.nim | 10 +- compiler/main.nim | 12 +- compiler/modulegraphs.nim | 8 +- compiler/nilcheck.nim | 4 +- compiler/options.nim | 22 +- compiler/passes.nim | 6 +- compiler/pipelines.nim | 8 +- compiler/plugins/itersgen.nim | 2 +- compiler/sem.nim | 14 +- compiler/semdata.nim | 26 +-- compiler/semexprs.nim | 6 +- compiler/semfold.nim | 6 +- compiler/semmagic.nim | 12 +- compiler/semobjconstr.nim | 2 +- compiler/semparallel.nim | 2 +- compiler/semstmts.nim | 10 +- compiler/semtypes.nim | 25 +-- compiler/semtypinst.nim | 4 +- compiler/sigmatch.nim | 10 +- compiler/sinkparameter_inference.nim | 2 +- compiler/spawn.nim | 8 +- compiler/types.nim | 4 +- compiler/vm.nim | 4 +- compiler/vmdeps.nim | 6 +- 45 files changed, 456 insertions(+), 360 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 661a82703c5d2..8a71522e6075b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1166,7 +1166,7 @@ proc idGeneratorFromModule*(m: PSym): IdGenerator = proc idGeneratorForPackage*(nextIdWillBe: int32): IdGenerator = result = IdGenerator(module: PackageModuleId, symId: nextIdWillBe - 1'i32, typeId: 0, disambTable: initCountTable[PIdent]()) -proc nextSymId*(x: IdGenerator): ItemId {.inline.} = +proc nextSymId(x: IdGenerator): ItemId {.inline.} = assert(not x.sealed) inc x.symId result = ItemId(module: x.module, item: x.symId) @@ -1547,7 +1547,8 @@ iterator items*(t: PType): PType = iterator pairs*(n: PType): tuple[i: int, n: PType] = for i in 0..= 0: diff --git a/compiler/ic/dce.nim b/compiler/ic/dce.nim index 49669e4e2c1d0..6eb36431ea040 100644 --- a/compiler/ic/dce.nim +++ b/compiler/ic/dce.nim @@ -109,13 +109,13 @@ proc aliveCode(c: var AliveContext; g: PackedModuleGraph; tree: PackedTree; n: N discard "ignore non-sym atoms" of nkSym: # This symbol is alive and everything its body references. - followLater(c, g, c.thisModule, n.operand) + followLater(c, g, c.thisModule, tree[n].soperand) of nkModuleRef: let (n1, n2) = sons2(tree, n) assert n1.kind == nkNone assert n2.kind == nkNone let m = n1.litId - let item = n2.operand + let item = tree[n2].soperand let otherModule = toFileIndexCached(c.decoder, g, c.thisModule, m).int followLater(c, g, otherModule, item) of nkMacroDef, nkTemplateDef, nkTypeSection, nkTypeOfExpr, @@ -131,7 +131,7 @@ proc aliveCode(c: var AliveContext; g: PackedModuleGraph; tree: PackedTree; n: N rangeCheckAnalysis(c, g, tree, n) of nkProcDef, nkConverterDef, nkMethodDef, nkFuncDef, nkIteratorDef: if n.firstSon.kind == nkSym and isNotGeneric(n): - let item = n.firstSon.operand + let item = tree[n.firstSon].soperand if isExportedToC(c, g, item): # This symbol is alive and everything its body references. followLater(c, g, c.thisModule, item) @@ -153,7 +153,7 @@ proc computeAliveSyms*(g: PackedModuleGraph; conf: ConfigRef): AliveSyms = var c = AliveContext(stack: @[], decoder: PackedDecoder(config: conf), thisModule: -1, alive: newSeq[IntSet](g.len), options: conf.options) - for i in countdown(high(g), 0): + for i in countdown(len(g)-1, 0): if g[i].status != undefined: c.thisModule = i for p in allNodes(g[i].fromDisk.topLevel): diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim index 1b52c82b0e0e3..b244d7afb7a76 100644 --- a/compiler/ic/ic.nim +++ b/compiler/ic/ic.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -import std/[hashes, tables, intsets] +import std/[hashes, tables, intsets, monotimes] import packed_ast, bitabs, rodfiles import ".." / [ast, idents, lineinfos, msgs, ropes, options, pathutils, condsyms, packages, modulepaths] @@ -43,8 +43,8 @@ type bodies*: PackedTree # other trees. Referenced from typ.n and sym.ast by their position. #producedGenerics*: Table[GenericKey, SymId] exports*: seq[(LitId, int32)] - hidden*: seq[(LitId, int32)] - reexports*: seq[(LitId, PackedItemId)] + hidden: seq[(LitId, int32)] + reexports: seq[(LitId, PackedItemId)] compilerProcs*: seq[(LitId, int32)] converters*, methods*, trmacros*, pureEnums*: seq[int32] @@ -88,22 +88,22 @@ proc toString*(tree: PackedTree; pos: NodePos; m: PackedModule; nesting: int; of nkEmpty, nkNilLit, nkType: discard of nkIdent, nkStrLit..nkTripleStrLit: result.add " " - result.add m.strings[LitId tree[pos].operand] + result.add m.strings[LitId tree[pos].uoperand] of nkSym: result.add " " - result.add m.strings[m.syms[tree[pos].operand].name] + result.add m.strings[m.syms[tree[pos].soperand].name] of directIntLit: result.add " " - result.addInt tree[pos].operand + result.addInt tree[pos].soperand of externSIntLit: result.add " " - result.addInt m.numbers[LitId tree[pos].operand] + result.addInt m.numbers[LitId tree[pos].uoperand] of externUIntLit: result.add " " - result.addInt cast[uint64](m.numbers[LitId tree[pos].operand]) + result.addInt cast[uint64](m.numbers[LitId tree[pos].uoperand]) of nkFloatLit..nkFloat128Lit: result.add " " - result.addFloat cast[BiggestFloat](m.numbers[LitId tree[pos].operand]) + result.addFloat cast[BiggestFloat](m.numbers[LitId tree[pos].uoperand]) else: result.add "(\n" for i in 1..(nesting+1)*2: result.add ' ' @@ -233,10 +233,14 @@ proc addImportFileDep*(c: var PackedEncoder; m: var PackedModule; f: FileIndex) m.imports.add toLitId(f, c, m) proc addHidden*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + assert s.kind != skUnknown let nameId = getOrIncl(m.strings, s.name.s) m.hidden.add((nameId, s.itemId.item)) + assert s.itemId.module == c.thisModule proc addExported*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + assert s.kind != skUnknown + assert s.itemId.module == c.thisModule let nameId = getOrIncl(m.strings, s.name.s) m.exports.add((nameId, s.itemId.item)) @@ -255,6 +259,8 @@ proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) = m.methods.add s.itemId.item proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + assert s.kind != skUnknown + if s.kind == skModule: return let nameId = getOrIncl(m.strings, s.name.s) m.reexports.add((nameId, PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item))) @@ -339,7 +345,7 @@ proc storeTypeLater(t: PType; c: var PackedEncoder; m: var PackedModule): Packed proc storeSymLater(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId = if s.isNil: return nilItemId assert s.itemId.module >= 0 - assert s.itemId.module >= 0 + assert s.itemId.item >= 0 result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) if s.itemId.module == c.thisModule: # the sym belongs to this module, so serialize it here, eventually. @@ -424,8 +430,13 @@ proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = ## add a remote symbol reference to the tree let info = n.info.toPackedInfo(c, m) - ir.addNode(kind = nkModuleRef, operand = 3.int32, # spans 3 nodes in total - typeId = storeTypeLater(n.typ, c, m), info = info) + if n.typ != n.sym.typ: + ir.addNode(kind = nkModuleRef, operand = 3.int32, # spans 3 nodes in total + info = info, + typeId = storeTypeLater(n.typ, c, m)) + else: + ir.addNode(kind = nkModuleRef, operand = 3.int32, # spans 3 nodes in total + info = info) ir.addNode(kind = nkNone, info = info, operand = toLitId(n.sym.itemId.module.FileIndex, c, m).int32) ir.addNode(kind = nkNone, info = info, @@ -450,8 +461,13 @@ proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pa # it is a symbol that belongs to the module we're currently # packing: let id = n.sym.storeSymLater(c, m).item - ir.addNode(kind = nkSym, flags = n.flags, operand = id, - typeId = storeTypeLater(n.typ, c, m), info = info) + if n.typ != n.sym.typ: + ir.addNode(kind = nkSym, flags = n.flags, operand = id, + info = info, + typeId = storeTypeLater(n.typ, c, m)) + else: + ir.addNode(kind = nkSym, flags = n.flags, operand = id, + info = info) else: # store it as an external module reference: addModuleRef(n, ir, c, m) @@ -565,6 +581,20 @@ proc toRodFile*(conf: ConfigRef; f: AbsoluteFile; ext = RodExt): AbsoluteFile = result = changeFileExt(completeGeneratedFilePath(conf, mangleModuleName(conf, f).AbsoluteFile), ext) +const + BenchIC* = false + +when BenchIC: + var gloadBodies: MonoTime + + template bench(x, body) = + let start = getMonoTime() + body + x = x + (getMonoTime() - start) + +else: + template bench(x, body) = body + proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef; ignoreConfig = false): RodFileError = var f = rodfiles.open(filename.string) @@ -589,42 +619,45 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef loadTabSection stringsSection, m.strings loadSeqSection checkSumsSection, m.includes - if not includesIdentical(m, config): + if config.cmd != cmdM and not includesIdentical(m, config): f.err = includeFileChanged loadSeqSection depsSection, m.imports - loadTabSection numbersSection, m.numbers + bench gloadBodies: + + loadTabSection numbersSection, m.numbers - loadSeqSection exportsSection, m.exports - loadSeqSection hiddenSection, m.hidden - loadSeqSection reexportsSection, m.reexports + loadSeqSection exportsSection, m.exports + loadSeqSection hiddenSection, m.hidden + loadSeqSection reexportsSection, m.reexports - loadSeqSection compilerProcsSection, m.compilerProcs + loadSeqSection compilerProcsSection, m.compilerProcs - loadSeqSection trmacrosSection, m.trmacros + loadSeqSection trmacrosSection, m.trmacros - loadSeqSection convertersSection, m.converters - loadSeqSection methodsSection, m.methods - loadSeqSection pureEnumsSection, m.pureEnums + loadSeqSection convertersSection, m.converters + loadSeqSection methodsSection, m.methods + loadSeqSection pureEnumsSection, m.pureEnums - loadTabSection toReplaySection, m.toReplay - loadTabSection topLevelSection, m.topLevel - loadTabSection bodiesSection, m.bodies - loadSeqSection symsSection, m.syms - loadSeqSection typesSection, m.types + loadTabSection toReplaySection, m.toReplay + loadTabSection topLevelSection, m.topLevel - loadSeqSection typeInstCacheSection, m.typeInstCache - loadSeqSection procInstCacheSection, m.procInstCache - loadSeqSection attachedOpsSection, m.attachedOps - loadSeqSection methodsPerTypeSection, m.methodsPerType - loadSeqSection enumToStringProcsSection, m.enumToStringProcs - loadSeqSection typeInfoSection, m.emittedTypeInfo + loadTabSection bodiesSection, m.bodies + loadSeqSection symsSection, m.syms + loadSeqSection typesSection, m.types - f.loadSection backendFlagsSection - f.loadPrim m.backendFlags + loadSeqSection typeInstCacheSection, m.typeInstCache + loadSeqSection procInstCacheSection, m.procInstCache + loadSeqSection attachedOpsSection, m.attachedOps + loadSeqSection methodsPerTypeSection, m.methodsPerType + loadSeqSection enumToStringProcsSection, m.enumToStringProcs + loadSeqSection typeInfoSection, m.emittedTypeInfo - f.loadSection sideChannelSection + f.loadSection backendFlagsSection + f.loadPrim m.backendFlags + + f.loadSection sideChannelSection f.load m.man close(f) @@ -736,13 +769,29 @@ type # PackedItemId so that it works with reexported symbols too # ifaceHidden includes private symbols - PackedModuleGraph* = seq[LoadedModule] # indexed by FileIndex +type + PackedModuleGraph* = object + pm*: seq[LoadedModule] # indexed by FileIndex + when BenchIC: + depAnalysis: MonoTime + loadBody: MonoTime + loadSym, loadType, loadBodies: MonoTime + +when BenchIC: + proc echoTimes*(m: PackedModuleGraph) = + echo "analysis: ", m.depAnalysis, " loadBody: ", m.loadBody, " loadSym: ", + m.loadSym, " loadType: ", m.loadType, " all bodies: ", gloadBodies + +template `[]`*(m: PackedModuleGraph; i: int): LoadedModule = m.pm[i] +template len*(m: PackedModuleGraph): int = m.pm.len proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; t: PackedItemId): PType proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s: PackedItemId): PSym proc toFileIndexCached*(c: var PackedDecoder; g: PackedModuleGraph; thisModule: int; f: LitId): FileIndex = - if c.lastLit == f and c.lastModule == thisModule: + if f == LitId(0): + result = InvalidFileIdx + elif c.lastLit == f and c.lastModule == thisModule: result = c.lastFile else: result = toFileIndex(f, g[thisModule].fromDisk, c.config) @@ -769,14 +818,13 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; result.flags = n.flags case k - of nkEmpty, nkNilLit, nkType: + of nkNone, nkEmpty, nkNilLit, nkType: discard of nkIdent: result.ident = getIdent(c.cache, g[thisModule].fromDisk.strings[n.litId]) of nkSym: - result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree[n].operand)) - of directIntLit: - result.intVal = tree[n].operand + result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree[n].soperand)) + if result.typ == nil: result.typ = result.sym.typ of externIntLit: result.intVal = g[thisModule].fromDisk.numbers[n.litId] of nkStrLit..nkTripleStrLit: @@ -788,7 +836,8 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; assert n1.kind == nkNone assert n2.kind == nkNone transitionNoneToSym(result) - result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree[n2].operand)) + result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree[n2].soperand)) + if result.typ == nil: result.typ = result.sym.typ else: for n0 in sonsReadonly(tree, n): result.addAllowNil loadNodes(c, g, thisModule, tree, n0) @@ -885,11 +934,22 @@ proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; result.loc.flags = s.locFlags result.instantiatedFrom = loadSym(c, g, si, s.instantiatedFrom) +proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; + fileIdx: FileIndex; cachedModules: var seq[FileIndex]): bool +proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; + fileIdx: FileIndex; m: var LoadedModule) + proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s: PackedItemId): PSym = if s == nilItemId: result = nil else: let si = moduleIndex(c, g, thisModule, s) + if g[si].status == undefined and c.config.cmd == cmdM: + var cachedModules: seq[FileIndex] = @[] + discard needsRecompile(g, c.config, c.cache, FileIndex(si), cachedModules) + for m in cachedModules: + loadToReplayNodes(g, c.config, c.cache, m, g[int m]) + assert g[si].status in {loaded, storing, stored} if not g[si].symsInit: g[si].symsInit = true @@ -904,6 +964,7 @@ proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s: else: result = g[si].module assert result != nil + g[si].syms[s.item] = result else: result = g[si].syms[s.item] @@ -948,9 +1009,11 @@ proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; t # store it here early on, so that recursions work properly: g[si].types[t.item] = result typeBodyFromPacked(c, g, g[si].fromDisk.types[t.item], si, t.item, result) + #assert result.itemId.item == t.item, $(result.itemId.item, t.item) + assert result.itemId.item > 0, $(result.itemId.item, t.item) else: result = g[si].types[t.item] - assert result.itemId.item > 0 + assert result.itemId.item > 0, "2" proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex; m: var LoadedModule) = @@ -1000,30 +1063,36 @@ proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache # Does the file belong to the fileIdx need to be recompiled? let m = int(fileIdx) if m >= g.len: - g.setLen(m+1) + g.pm.setLen(m+1) case g[m].status of undefined: g[m].status = loading let fullpath = msgs.toFullPath(conf, fileIdx) let rod = toRodFile(conf, AbsoluteFile fullpath) - let err = loadRodFile(rod, g[m].fromDisk, conf) + let err = loadRodFile(rod, g[m].fromDisk, conf, ignoreConfig = conf.cmd == cmdM) if err == ok: - result = optForceFullMake in conf.globalOptions - # check its dependencies: - for dep in g[m].fromDisk.imports: - let fid = toFileIndex(dep, g[m].fromDisk, conf) - # Warning: we need to traverse the full graph, so - # do **not use break here**! - if needsRecompile(g, conf, cache, fid, cachedModules): - result = true - - if not result: + if conf.cmd == cmdM: setupLookupTables(g, conf, cache, fileIdx, g[m]) cachedModules.add fileIdx g[m].status = loaded + result = false else: - g[m] = LoadedModule(status: outdated, module: g[m].module) + result = optForceFullMake in conf.globalOptions + # check its dependencies: + for dep in g[m].fromDisk.imports: + let fid = toFileIndex(dep, g[m].fromDisk, conf) + # Warning: we need to traverse the full graph, so + # do **not use break here**! + if needsRecompile(g, conf, cache, fid, cachedModules): + result = true + + if not result: + setupLookupTables(g, conf, cache, fileIdx, g[m]) + cachedModules.add fileIdx + g[m].status = loaded + else: + g.pm[m] = LoadedModule(status: outdated, module: g[m].module) else: loadError(err, rod, conf) g[m].status = outdated @@ -1038,12 +1107,13 @@ proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache proc moduleFromRodFile*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex; cachedModules: var seq[FileIndex]): PSym = ## Returns 'nil' if the module needs to be recompiled. - if needsRecompile(g, conf, cache, fileIdx, cachedModules): - result = nil - else: - result = g[int fileIdx].module - assert result != nil - assert result.position == int(fileIdx) + bench g.depAnalysis: + if needsRecompile(g, conf, cache, fileIdx, cachedModules): + result = nil + else: + result = g[int fileIdx].module + assert result != nil + assert result.position == int(fileIdx) for m in cachedModules: loadToReplayNodes(g, conf, cache, m, g[int m]) @@ -1057,46 +1127,49 @@ template setupDecoder() {.dirty.} = proc loadProcBody*(config: ConfigRef, cache: IdentCache; g: var PackedModuleGraph; s: PSym): PNode = - let mId = s.itemId.module - var decoder = PackedDecoder( - lastModule: int32(-1), - lastLit: LitId(0), - lastFile: FileIndex(-1), - config: config, - cache: cache) - let pos = g[mId].fromDisk.syms[s.itemId.item].ast - assert pos != emptyNodeId - result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos) - -proc loadTypeFromId*(config: ConfigRef, cache: IdentCache; - g: var PackedModuleGraph; module: int; id: PackedItemId): PType = - if id.item < g[module].types.len: - result = g[module].types[id.item] - else: - result = nil - if result == nil: + bench g.loadBody: + let mId = s.itemId.module var decoder = PackedDecoder( lastModule: int32(-1), lastLit: LitId(0), lastFile: FileIndex(-1), config: config, cache: cache) - result = loadType(decoder, g, module, id) + let pos = g[mId].fromDisk.syms[s.itemId.item].ast + assert pos != emptyNodeId + result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos) + +proc loadTypeFromId*(config: ConfigRef, cache: IdentCache; + g: var PackedModuleGraph; module: int; id: PackedItemId): PType = + bench g.loadType: + if id.item < g[module].types.len: + result = g[module].types[id.item] + else: + result = nil + if result == nil: + var decoder = PackedDecoder( + lastModule: int32(-1), + lastLit: LitId(0), + lastFile: FileIndex(-1), + config: config, + cache: cache) + result = loadType(decoder, g, module, id) proc loadSymFromId*(config: ConfigRef, cache: IdentCache; g: var PackedModuleGraph; module: int; id: PackedItemId): PSym = - if id.item < g[module].syms.len: - result = g[module].syms[id.item] - else: - result = nil - if result == nil: - var decoder = PackedDecoder( - lastModule: int32(-1), - lastLit: LitId(0), - lastFile: FileIndex(-1), - config: config, - cache: cache) - result = loadSym(decoder, g, module, id) + bench g.loadSym: + if id.item < g[module].syms.len: + result = g[module].syms[id.item] + else: + result = nil + if result == nil: + var decoder = PackedDecoder( + lastModule: int32(-1), + lastLit: LitId(0), + lastFile: FileIndex(-1), + config: config, + cache: cache) + result = loadSym(decoder, g, module, id) proc translateId*(id: PackedItemId; g: PackedModuleGraph; thisModule: int; config: ConfigRef): ItemId = if id.module == LitId(0): @@ -1160,7 +1233,7 @@ proc initRodIter*(it: var RodIter; config: ConfigRef, cache: IdentCache; result = nil proc initRodIterAllSyms*(it: var RodIter; config: ConfigRef, cache: IdentCache; - g: var PackedModuleGraph; module: FileIndex, importHidden: bool): PSym = + g: var PackedModuleGraph; module: FileIndex; importHidden: bool): PSym = it.decoder = PackedDecoder( lastModule: int32(-1), lastLit: LitId(0), @@ -1221,7 +1294,7 @@ proc rodViewer*(rodfile: AbsoluteFile; config: ConfigRef, cache: IdentCache) = if err != ok: config.quitOrRaise "Error: could not load: " & $rodfile.string & " reason: " & $err - when true: + when false: echo "exports:" for ex in m.exports: echo " ", m.strings[ex[0]], " local ID: ", ex[1] @@ -1237,13 +1310,32 @@ proc rodViewer*(rodfile: AbsoluteFile; config: ConfigRef, cache: IdentCache) = for ex in m.hidden: echo " ", m.strings[ex[0]], " local ID: ", ex[1] - echo "all symbols" - for i in 0..high(m.syms): - if m.syms[i].name != LitId(0): - echo " ", m.strings[m.syms[i].name], " local ID: ", i, " kind ", m.syms[i].kind - else: - echo " local ID: ", i, " kind ", m.syms[i].kind + when false: + echo "all symbols" + for i in 0..high(m.syms): + if m.syms[i].name != LitId(0): + echo " ", m.strings[m.syms[i].name], " local ID: ", i, " kind ", m.syms[i].kind + else: + echo " local ID: ", i, " kind ", m.syms[i].kind echo "symbols: ", m.syms.len, " types: ", m.types.len, " top level nodes: ", m.topLevel.len, " other nodes: ", m.bodies.len, " strings: ", m.strings.len, " numbers: ", m.numbers.len + + echo "SIZES:" + echo "symbols: ", m.syms.len * sizeof(PackedSym), " types: ", m.types.len * sizeof(PackedType), + " top level nodes: ", m.topLevel.len * sizeof(PackedNode), + " other nodes: ", m.bodies.len * sizeof(PackedNode), + " strings: ", sizeOnDisc(m.strings) + when false: + var tt = 0 + var fc = 0 + for x in m.topLevel: + if x.kind == nkSym or x.typeId == nilItemId: inc tt + if x.flags == {}: inc fc + for x in m.bodies: + if x.kind == nkSym or x.typeId == nilItemId: inc tt + if x.flags == {}: inc fc + let total = float(m.topLevel.len + m.bodies.len) + echo "nodes with nil type: ", tt, " in % ", tt.float / total + echo "nodes with empty flags: ", fc.float / total diff --git a/compiler/ic/integrity.nim b/compiler/ic/integrity.nim index 00014f15a3a4d..0ffd87c2f5f8b 100644 --- a/compiler/ic/integrity.nim +++ b/compiler/ic/integrity.nim @@ -72,15 +72,16 @@ proc checkForeignSym(c: var CheckedContext; symId: PackedItemId) = c.thisModule = oldThisModule proc checkNode(c: var CheckedContext; tree: PackedTree; n: NodePos) = - if tree[n].typeId != nilItemId: - checkType(c, tree[n].typeId) + let t = findType(tree, n) + if t != nilItemId: + checkType(c, t) case n.kind of nkEmpty, nkNilLit, nkType, nkNilRodNode: discard of nkIdent: assert c.g.packed[c.thisModule].fromDisk.strings.hasLitId n.litId of nkSym: - checkLocalSym(c, tree[n].operand) + checkLocalSym(c, tree[n].soperand) of directIntLit: discard of externIntLit, nkFloatLit..nkFloat128Lit: @@ -91,7 +92,7 @@ proc checkNode(c: var CheckedContext; tree: PackedTree; n: NodePos) = let (n1, n2) = sons2(tree, n) assert n1.kind == nkNone assert n2.kind == nkNone - checkForeignSym(c, PackedItemId(module: n1.litId, item: tree[n2].operand)) + checkForeignSym(c, PackedItemId(module: n1.litId, item: tree[n2].soperand)) else: for n0 in sonsReadonly(tree, n): checkNode(c, tree, n0) @@ -140,7 +141,7 @@ proc checkModule(c: var CheckedContext; m: PackedModule) = proc checkIntegrity*(g: ModuleGraph) = var c = CheckedContext(g: g) - for i in 0..high(g.packed): + for i in 0.. nkNilLit + let k = tree.nodes[pos].kind + assert k > nkNilLit let distance = int32(tree.nodes.len - pos) - tree.nodes[pos].operand = distance + assert distance > 0 + tree.nodes[pos].x = toX(k, cast[uint32](distance)) proc len*(tree: PackedTree): int {.inline.} = tree.nodes.len proc `[]`*(tree: PackedTree; i: NodePos): lent PackedNode {.inline.} = tree.nodes[i.int] +template rawSpan(n: PackedNode): int = int(uoperand(n)) + proc nextChild(tree: PackedTree; pos: var int) {.inline.} = if tree.nodes[pos].kind > nkNilLit: - assert tree.nodes[pos].operand > 0 - inc pos, tree.nodes[pos].operand + assert tree.nodes[pos].uoperand > 0 + inc pos, tree.nodes[pos].rawSpan else: inc pos iterator sonsReadonly*(tree: PackedTree; n: NodePos): NodePos = var pos = n.int assert tree.nodes[pos].kind > nkNilLit - let last = pos + tree.nodes[pos].operand + let last = pos + tree.nodes[pos].rawSpan inc pos while pos < last: yield NodePos pos @@ -190,7 +204,7 @@ iterator isons*(dest: var PackedTree; tree: PackedTree; iterator sonsFrom1*(tree: PackedTree; n: NodePos): NodePos = var pos = n.int assert tree.nodes[pos].kind > nkNilLit - let last = pos + tree.nodes[pos].operand + let last = pos + tree.nodes[pos].rawSpan inc pos if pos < last: nextChild tree, pos @@ -204,7 +218,7 @@ iterator sonsWithoutLast2*(tree: PackedTree; n: NodePos): NodePos = inc count var pos = n.int assert tree.nodes[pos].kind > nkNilLit - let last = pos + tree.nodes[pos].operand + let last = pos + tree.nodes[pos].rawSpan inc pos while pos < last and count > 2: yield NodePos pos @@ -214,7 +228,7 @@ iterator sonsWithoutLast2*(tree: PackedTree; n: NodePos): NodePos = proc parentImpl(tree: PackedTree; n: NodePos): NodePos = # finding the parent of a node is rather easy: var pos = n.int - 1 - while pos >= 0 and (isAtom(tree, pos) or (pos + tree.nodes[pos].operand - 1 < n.int)): + while pos >= 0 and (isAtom(tree, pos) or (pos + tree.nodes[pos].rawSpan - 1 < n.int)): dec pos #assert pos >= 0, "node has no parent" result = NodePos(pos) @@ -240,20 +254,32 @@ proc firstSon*(tree: PackedTree; n: NodePos): NodePos {.inline.} = proc kind*(tree: PackedTree; n: NodePos): TNodeKind {.inline.} = tree.nodes[n.int].kind proc litId*(tree: PackedTree; n: NodePos): LitId {.inline.} = - LitId tree.nodes[n.int].operand + LitId tree.nodes[n.int].uoperand proc info*(tree: PackedTree; n: NodePos): PackedLineInfo {.inline.} = tree.nodes[n.int].info +proc findType*(tree: PackedTree; n: NodePos): PackedItemId = + for x in tree.withTypes: + if x[0] == int32(n): return x[1] + if x[0] > int32(n): return nilItemId + return nilItemId + +proc findFlags*(tree: PackedTree; n: NodePos): TNodeFlags = + for x in tree.withFlags: + if x[0] == int32(n): return x[1] + if x[0] > int32(n): return {} + return {} + template typ*(n: NodePos): PackedItemId = - tree.nodes[n.int].typeId + tree.findType(n) template flags*(n: NodePos): TNodeFlags = - tree.nodes[n.int].flags + tree.findFlags(n) -template operand*(n: NodePos): int32 = - tree.nodes[n.int].operand +template uoperand*(n: NodePos): uint32 = + tree.nodes[n.int].uoperand proc span*(tree: PackedTree; pos: int): int {.inline.} = - if isAtom(tree, pos): 1 else: tree.nodes[pos].operand + if isAtom(tree, pos): 1 else: tree.nodes[pos].rawSpan proc sons2*(tree: PackedTree; n: NodePos): (NodePos, NodePos) = assert(not isAtom(tree, n.int)) @@ -283,38 +309,12 @@ when false: template kind*(n: NodePos): TNodeKind = tree.nodes[n.int].kind template info*(n: NodePos): PackedLineInfo = tree.nodes[n.int].info -template litId*(n: NodePos): LitId = LitId tree.nodes[n.int].operand +template litId*(n: NodePos): LitId = LitId tree.nodes[n.int].uoperand -template symId*(n: NodePos): SymId = SymId tree.nodes[n.int].operand +template symId*(n: NodePos): SymId = SymId tree.nodes[n.int].soperand proc firstSon*(n: NodePos): NodePos {.inline.} = NodePos(n.int+1) -when false: - # xxx `nkStrLit` or `nkStrLit..nkTripleStrLit:` below? - proc strLit*(tree: PackedTree; n: NodePos): lent string = - assert n.kind == nkStrLit - result = tree.sh.strings[LitId tree.nodes[n.int].operand] - - proc strVal*(tree: PackedTree; n: NodePos): string = - assert n.kind == nkStrLit - result = tree.sh.strings[LitId tree.nodes[n.int].operand] - #result = cookedStrLit(raw) - - proc filenameVal*(tree: PackedTree; n: NodePos): string = - case n.kind - of nkStrLit: - result = strVal(tree, n) - of nkIdent: - result = tree.sh.strings[n.litId] - of nkSym: - result = tree.sh.strings[tree.sh.syms[int n.symId].name] - else: - result = "" - - proc identAsStr*(tree: PackedTree; n: NodePos): lent string = - assert n.kind == nkIdent - result = tree.sh.strings[LitId tree.nodes[n.int].operand] - const externIntLit* = {nkCharLit, nkIntLit, @@ -332,17 +332,6 @@ const externUIntLit* = {nkUIntLit, nkUInt8Lit, nkUInt16Lit, nkUInt32Lit, nkUInt64Lit} directIntLit* = nkNone -when false: - proc identIdImpl(tree: PackedTree; n: NodePos): LitId = - if n.kind == nkIdent: - result = n.litId - elif n.kind == nkSym: - result = tree.sh.syms[int n.symId].name - else: - result = LitId(0) - - template identId*(n: NodePos): LitId = identIdImpl(tree, n) - template copyInto*(dest, n, body) = let patchPos = prepare(dest, tree, n) body @@ -353,28 +342,8 @@ template copyIntoKind*(dest, kind, info, body) = body patch dest, patchPos -when false: - proc hasPragma*(tree: PackedTree; n: NodePos; pragma: string): bool = - let litId = tree.sh.strings.getKeyId(pragma) - if litId == LitId(0): - return false - assert n.kind == nkPragma - for ch0 in sonsReadonly(tree, n): - if ch0.kind == nkExprColonExpr: - if ch0.firstSon.identId == litId: - return true - elif ch0.identId == litId: - return true - proc getNodeId*(tree: PackedTree): NodeId {.inline.} = NodeId tree.nodes.len -when false: - proc produceError*(dest: var PackedTree; tree: PackedTree; n: NodePos; msg: string) = - let patchPos = prepare(dest, nkError, n.info) - dest.add nkStrLit, msg, n.info - copyTree(dest, tree, n) - patch dest, patchPos - iterator allNodes*(tree: PackedTree): NodePos = var p = 0 while p < tree.len: @@ -387,6 +356,10 @@ proc toPackedItemId*(item: int32): PackedItemId {.inline.} = proc load*(f: var RodFile; t: var PackedTree) = loadSeq f, t.nodes + loadSeq f, t.withFlags + loadSeq f, t.withTypes proc store*(f: var RodFile; t: PackedTree) = storeSeq f, t.nodes + storeSeq f, t.withFlags + storeSeq f, t.withTypes diff --git a/compiler/importer.nim b/compiler/importer.nim index ff1f9f63ef049..a8de1e8bcf533 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -230,7 +230,7 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym; im else: for i in 0..n.safeLen-1: importForwarded(c, n[i], exceptSet, fromMod, importSet) - + proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool): PSym = result = realModule template createModuleAliasImpl(ident): untyped = @@ -313,6 +313,7 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym = result = nil proc afterImport(c: PContext, m: PSym) = + if isCachedModule(c.graph, m): return # fixes bug #17510, for re-exported symbols let realModuleId = c.importModuleMap[m.id] for s in allSyms(c.graph, m): diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index a278f7c49a3f9..4870ca1a39894 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -214,7 +214,7 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string; inferredFr localError(c.graph.config, ri.info, errGenerated, m) proc makePtrType(c: var Con, baseType: PType): PType = - result = newType(tyPtr, nextTypeId c.idgen, c.owner) + result = newType(tyPtr, c.idgen, c.owner) addSonSkipIntLit(result, baseType, c.idgen) proc genOp(c: var Con; op: PSym; dest: PNode): PNode = diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 248effcaf8ff1..9345ac114baa2 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -135,10 +135,10 @@ proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator) var n = newNodeI(nkRange, iter.info) n.add newIntNode(nkIntLit, -1) n.add newIntNode(nkIntLit, 0) - result = newType(tyRange, nextTypeId(idgen), iter) + result = newType(tyRange, idgen, iter) result.n = n var intType = nilOrSysInt(g) - if intType.isNil: intType = newType(tyInt, nextTypeId(idgen), iter) + if intType.isNil: intType = newType(tyInt, idgen, iter) rawAddSon(result, intType) proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym = @@ -342,7 +342,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = result = c.ownerToType.getOrDefault(owner.id) if result.isNil: - result = newType(tyRef, nextTypeId(c.idgen), owner) + result = newType(tyRef, c.idgen, owner) let obj = createEnvObj(c.graph, c.idgen, owner, info) rawAddSon(result, obj) c.ownerToType[owner.id] = result @@ -350,7 +350,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; proc asOwnedRef(c: var DetectionPass; t: PType): PType = if optOwnedRefs in c.graph.config.globalOptions: assert t.kind == tyRef - result = newType(tyOwned, nextTypeId(c.idgen), t.owner) + result = newType(tyOwned, c.idgen, t.owner) result.flags.incl tfHasOwned result.rawAddSon t else: @@ -359,7 +359,7 @@ proc asOwnedRef(c: var DetectionPass; t: PType): PType = proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = var r = c.getEnvTypeForOwner(owner, info) - result = newType(tyPtr, nextTypeId(c.idgen), owner) + result = newType(tyPtr, c.idgen, owner) rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr})) proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index ea0d6e6f8b018..8995e1073bf18 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -1057,7 +1057,7 @@ proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttache res.typ = typ src.typ = typ - result.typ = newType(tyProc, nextTypeId idgen, owner) + result.typ = newType(tyProc, idgen, owner) result.typ.n = newNodeI(nkFormalParams, info) rawAddSon(result.typ, res.typ) result.typ.n.add newNodeI(nkEffectList, info) @@ -1102,7 +1102,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp else: src.typ = typ - result.typ = newProcType(info, nextTypeId(idgen), owner) + result.typ = newProcType(info, idgen, owner) result.typ.addParam dest if kind notin {attachedDestructor, attachedWasMoved}: result.typ.addParam src diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 42d0f1790c0d5..f8ae67f411d9b 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -144,7 +144,7 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNod result.add newFastAsgnStmt(n[2], tempAsNode) proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType = - result = newType(tyObject, nextTypeId(idgen), owner) + result = newType(tyObject, idgen, owner) if final: rawAddSon(result, nil) incl result.flags, tfFinal @@ -320,7 +320,7 @@ proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode = proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode = result = newNodeI(nkAddr, n.info, 1) result[0] = n - result.typ = newType(typeKind, nextTypeId(idgen), n.typ.owner) + result.typ = newType(typeKind, idgen, n.typ.owner) result.typ.rawAddSon(n.typ) proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index 63fe0369c8f74..dcde49bfffa05 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -18,7 +18,7 @@ export createMagic proc nilOrSysInt*(g: ModuleGraph): PType = g.sysTypes[tyInt] proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType = - result = newType(kind, nextTypeId(g.idgen), g.systemModule) + result = newType(kind, g.idgen, g.systemModule) result.size = size result.align = size.int16 @@ -27,7 +27,7 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym = if result == nil: localError(g.config, info, "system module needs: " & name) result = newSym(skError, getIdent(g.cache, name), g.idgen, g.systemModule, g.systemModule.info, {}) - result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule) + result.typ = newType(tyError, g.idgen, g.systemModule) proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym = result = nil @@ -40,7 +40,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy if result != nil: return result localError(g.config, info, "system module needs: " & name) result = newSym(skError, id, g.idgen, g.systemModule, g.systemModule.info, {}) - result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule) + result.typ = newType(tyError, g.idgen, g.systemModule) proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType = result = getSysSym(g, info, name).typ @@ -93,7 +93,7 @@ proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = proc skipIntLit*(t: PType; id: IdGenerator): PType {.inline.} = if t.n != nil and t.kind in {tyInt, tyFloat}: - result = copyType(t, nextTypeId(id), t.owner) + result = copyType(t, id, t.owner) result.n = nil else: result = t @@ -151,7 +151,7 @@ proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym = "can't find magic equals operator for type kind " & $t.kind) proc makePtrType*(baseType: PType; idgen: IdGenerator): PType = - result = newType(tyPtr, nextTypeId idgen, baseType.owner) + result = newType(tyPtr, idgen, baseType.owner) addSonSkipIntLit(result, baseType, idgen) proc makeAddr*(n: PNode; idgen: IdGenerator): PNode = diff --git a/compiler/main.nim b/compiler/main.nim index 6651128ebf730..d9c3baa0905ea 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -28,8 +28,7 @@ import nir / nir when defined(nimPreviewSlimSystem): import std/[syncio, assertions] -import ic / [cbackend, integrity, navigator] -from ic / ic import rodViewer +import ic / [cbackend, integrity, navigator, ic] import ../dist/checksums/src/checksums/sha1 @@ -335,7 +334,10 @@ proc mainCommand*(graph: ModuleGraph) = ## process all commands case conf.cmd - of cmdBackends: compileToBackend() + of cmdBackends: + compileToBackend() + when BenchIC: + echoTimes graph.packed of cmdTcc: when hasTinyCBackend: extccomp.setCC(conf, "tcc", unknownLineInfo) @@ -431,6 +433,10 @@ proc mainCommand*(graph: ModuleGraph) = for it in conf.searchPaths: msgWriteln(conf, it.string) of cmdCheck: commandCheck(graph) + of cmdM: + graph.config.symbolFiles = v2Sf + setUseIc(graph.config.symbolFiles != disabledSf) + commandCheck(graph) of cmdParse: wantMainModule(conf) discard parseFile(conf.projectMainIdx, cache, conf) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 5c23325e82dd2..99175815b4264 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -212,10 +212,10 @@ proc strTableAdds*(g: ModuleGraph, m: PSym, s: PSym) = proc isCachedModule(g: ModuleGraph; module: int): bool {.inline.} = result = module < g.packed.len and g.packed[module].status == loaded -proc isCachedModule(g: ModuleGraph; m: PSym): bool {.inline.} = +proc isCachedModule*(g: ModuleGraph; m: PSym): bool {.inline.} = isCachedModule(g, m.position) -proc simulateCachedModule*(g: ModuleGraph; moduleSym: PSym; m: PackedModule) = +proc simulateCachedModule(g: ModuleGraph; moduleSym: PSym; m: PackedModule) = when false: echo "simulating ", moduleSym.name.s, " ", moduleSym.position simulateLoadedModule(g.packed, g.config, g.cache, moduleSym, m) @@ -378,7 +378,7 @@ proc loadCompilerProc*(g: ModuleGraph; name: string): PSym = if g.config.symbolFiles == disabledSf: return nil # slow, linear search, but the results are cached: - for module in 0..high(g.packed): + for module in 0..= 0: @@ -435,7 +435,7 @@ proc registerModule*(g: ModuleGraph; m: PSym) = setLen(g.ifaces, m.position + 1) if m.position >= g.packed.len: - setLen(g.packed, m.position + 1) + setLen(g.packed.pm, m.position + 1) g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[], uniqueName: rope(uniqueModuleName(g.config, FileIndex(m.position)))) diff --git a/compiler/nilcheck.nim b/compiler/nilcheck.nim index 1713a888f80fc..2a6de8733659c 100644 --- a/compiler/nilcheck.nim +++ b/compiler/nilcheck.nim @@ -918,7 +918,7 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode = newSymNode(op, r.info), l, r) - result.typ = newType(tyBool, nextTypeId ctx.idgen, nil) + result.typ = newType(tyBool, ctx.idgen, nil) proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode = var cache = newIdentCache() @@ -928,7 +928,7 @@ proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode = result = nkPrefix.newTree( newSymNode(op, node.info), node) - result.typ = newType(tyBool, nextTypeId ctx.idgen, nil) + result.typ = newType(tyBool, ctx.idgen, nil) proc infixEq(ctx: NilCheckerContext, l: PNode, r: PNode): PNode = infix(ctx, l, r, mEqRef) diff --git a/compiler/options.nim b/compiler/options.nim index 704248d789365..e50acbf493bcc 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -150,6 +150,7 @@ type cmdCrun # compile and run in nimache cmdTcc # run the project via TCC backend cmdCheck # semantic checking for whole project + cmdM # only compile a single cmdParse # parse a single file (for debugging) cmdRod # .rod to some text representation (for debugging) cmdIdeTools # ide tools (e.g. nimsuggest) @@ -819,16 +820,17 @@ proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir = else: "_d" # XXX projectName should always be without a file extension! - result = if not conf.nimcacheDir.isEmpty: - conf.nimcacheDir - elif conf.backend == backendJs: - if conf.outDir.isEmpty: - conf.projectPath / genSubDir - else: - conf.outDir / genSubDir - else: - AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name & - nimcacheSuffix(conf)) + result = + if not conf.nimcacheDir.isEmpty: + conf.nimcacheDir + elif conf.backend == backendJs: + if conf.outDir.isEmpty: + conf.projectPath / genSubDir + else: + conf.outDir / genSubDir + else: + AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name & + nimcacheSuffix(conf)) proc pathSubs*(conf: ConfigRef; p, config: string): string = let home = removeTrailingDirSep(os.getHomeDir()) diff --git a/compiler/passes.nim b/compiler/passes.nim index 87a9d05c8af2e..d6b1410786132 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -165,13 +165,13 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fr template processModuleAux(moduleStatus) = onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule) - var s: PLLStream + var s: PLLStream = nil if sfMainModule in flags: if graph.config.projectIsStdin: s = stdin.llStreamOpen elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput) discard processModule(graph, result, idGeneratorFromModule(result), s) if result == nil: - var cachedModules: seq[FileIndex] + var cachedModules: seq[FileIndex] = @[] result = moduleFromRodFile(graph, fileIdx, cachedModules) let filename = AbsoluteFile toFullPath(graph.config, fileIdx) if result == nil: @@ -185,7 +185,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fr partialInitModule(result, graph, fileIdx, filename) for m in cachedModules: registerModuleById(graph, m) - replayStateChanges(graph.packed[m.int].module, graph) + replayStateChanges(graph.packed.pm[m.int].module, graph) replayGenericCacheInformation(graph, m.int) elif graph.isDirty(result): result.flags.excl sfDirty diff --git a/compiler/pipelines.nim b/compiler/pipelines.nim index 8f40ac031da7f..c3b7a8b7ecb16 100644 --- a/compiler/pipelines.nim +++ b/compiler/pipelines.nim @@ -228,7 +228,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator closeRodFile(graph, module) result = true -proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym = +proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags; fromModule: PSym = nil): PSym = var flags = flags if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule result = graph.getModule(fileIdx) @@ -252,10 +252,14 @@ proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymF else: if sfSystemModule in flags: graph.systemModule = result + if sfMainModule in flags and graph.config.cmd == cmdM: + result.flags.incl flags + registerModule(graph, result) + processModuleAux("import") partialInitModule(result, graph, fileIdx, filename) for m in cachedModules: registerModuleById(graph, m) - replayStateChanges(graph.packed[m.int].module, graph) + replayStateChanges(graph.packed.pm[m.int].module, graph) replayGenericCacheInformation(graph, m.int) elif graph.isDirty(result): result.flags.excl sfDirty diff --git a/compiler/plugins/itersgen.nim b/compiler/plugins/itersgen.nim index 1a291c04d2808..c5e9dc853471c 100644 --- a/compiler/plugins/itersgen.nim +++ b/compiler/plugins/itersgen.nim @@ -32,7 +32,7 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode = let body = liftIterToProc(c.graph, iter.sym, getBody(c.graph, iter.sym), t, c.idgen) let prc = newSym(skProc, n[3].ident, c.idgen, iter.sym.owner, iter.sym.info) - prc.typ = copyType(iter.sym.typ, nextTypeId c.idgen, prc) + prc.typ = copyType(iter.sym.typ, c.idgen, prc) excl prc.typ.flags, tfCapturesEnv prc.typ.n.add newSymNode(getEnvParam(iter.sym)) prc.typ.rawAddSon t diff --git a/compiler/sem.nim b/compiler/sem.nim index 1908b5a0de728..568db0d0f9f66 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -145,8 +145,8 @@ proc commonType*(c: PContext; x, y: PType): PType = # turn any concrete typedesc into the abstract typedesc type if a.len == 0: result = a else: - result = newType(tyTypeDesc, nextTypeId(c.idgen), a.owner) - rawAddSon(result, newType(tyNone, nextTypeId(c.idgen), a.owner)) + result = newType(tyTypeDesc, c.idgen, a.owner) + rawAddSon(result, newType(tyNone, c.idgen, a.owner)) elif b.kind in {tyArray, tySet, tySequence} and a.kind == b.kind: # check for seq[empty] vs. seq[int] @@ -159,7 +159,7 @@ proc commonType*(c: PContext; x, y: PType): PType = let bEmpty = isEmptyContainer(b[i]) if aEmpty != bEmpty: if nt.isNil: - nt = copyType(a, nextTypeId(c.idgen), a.owner) + nt = copyType(a, c.idgen, a.owner) copyTypeProps(c.graph, c.idgen.module, nt, a) nt[i] = if aEmpty: b[i] else: a[i] @@ -206,7 +206,7 @@ proc commonType*(c: PContext; x, y: PType): PType = # ill-formed AST, no need for additional tyRef/tyPtr if k != tyNone and x.kind != tyGenericInst: let r = result - result = newType(k, nextTypeId(c.idgen), r.owner) + result = newType(k, c.idgen, r.owner) result.addSonSkipIntLit(r, c.idgen) proc endsInNoReturn(n: PNode): bool = @@ -638,7 +638,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool, ch result.add newTree(nkExprColonExpr, recNode, asgnExpr) return - let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), recNode.typ.owner) + let asgnType = newType(tyTypeDesc, c.idgen, recNode.typ.owner) rawAddSon(asgnType, recNode.typ) let asgnExpr = newTree(nkCall, newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)), @@ -744,8 +744,8 @@ proc addCodeForGenerics(c: PContext, n: PNode) = proc preparePContext*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PContext = result = newContext(graph, module) result.idgen = idgen - result.enforceVoidContext = newType(tyTyped, nextTypeId(idgen), nil) - result.voidType = newType(tyVoid, nextTypeId(idgen), nil) + result.enforceVoidContext = newType(tyTyped, idgen, nil) + result.voidType = newType(tyVoid, idgen, nil) if result.p != nil: internalError(graph.config, module.info, "sem.preparePContext") result.semConstExpr = semConstExpr diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 91b15d5c77298..a24fa4fb5afcc 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -182,12 +182,12 @@ proc getIntLitType*(c: PContext; literal: PNode): PType = result = c.intTypeCache[value.int] if result == nil: let ti = getSysType(c.graph, literal.info, tyInt) - result = copyType(ti, nextTypeId(c.idgen), ti.owner) + result = copyType(ti, c.idgen, ti.owner) result.n = literal c.intTypeCache[value.int] = result else: let ti = getSysType(c.graph, literal.info, tyInt) - result = copyType(ti, nextTypeId(c.idgen), ti.owner) + result = copyType(ti, c.idgen, ti.owner) result.n = literal proc setIntLitType*(c: PContext; result: PNode) = @@ -220,12 +220,11 @@ proc setIntLitType*(c: PContext; result: PNode) = internalError(c.config, result.info, "invalid int size") proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = - result.genericSym = s - result.inst = inst + result = TInstantiationPair(genericSym: s, inst: inst) proc filename*(c: PContext): string = # the module's filename - return toFilename(c.config, FileIndex c.module.position) + result = toFilename(c.config, FileIndex c.module.position) proc scopeDepth*(c: PContext): int {.inline.} = result = if c.currentScope != nil: c.currentScope.depthLevel @@ -328,7 +327,8 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = result.features = graph.config.features if graph.config.symbolFiles != disabledSf: let id = module.position - assert graph.packed[id].status in {undefined, outdated} + if graph.config.cmd != cmdM: + assert graph.packed[id].status in {undefined, outdated} graph.packed[id].status = storing graph.packed[id].module = module initEncoder graph, module @@ -397,10 +397,10 @@ proc addToLib*(lib: PLib, sym: PSym) = sym.annex = lib proc newTypeS*(kind: TTypeKind, c: PContext, sons: seq[PType] = @[]): PType = - result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c), sons = sons) + result = newType(kind, c.idgen, getCurrOwner(c), sons = sons) proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType = - result = newType(tyPtr, nextTypeId(idgen), owner) + result = newType(tyPtr, idgen, owner) addSonSkipIntLit(result, baseType, idgen) proc makePtrType*(c: PContext, baseType: PType): PType = @@ -428,7 +428,7 @@ proc makeVarType*(owner: PSym, baseType: PType; idgen: IdGenerator; kind = tyVar if baseType.kind == kind: result = baseType else: - result = newType(kind, nextTypeId(idgen), owner) + result = newType(kind, idgen, owner) addSonSkipIntLit(result, baseType, idgen) proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = @@ -447,15 +447,15 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType = proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]; idgen: IdGenerator): PType = - result = newType(kind, nextTypeId(idgen), owner, sons = sons) + result = newType(kind, idgen, owner, sons = sons) proc newTypeWithSons*(c: PContext, kind: TTypeKind, sons: seq[PType]): PType = - result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c), sons = sons) + result = newType(kind, c.idgen, getCurrOwner(c), sons = sons) proc newTypeWithSons*(c: PContext, kind: TTypeKind, parent: PType): PType = - result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c), parent = parent) + result = newType(kind, c.idgen, getCurrOwner(c), parent = parent) proc makeStaticExpr*(c: PContext, n: PNode): PNode = result = newNodeI(nkStaticExpr, n.info) @@ -471,7 +471,7 @@ proc makeAndType*(c: PContext, t1, t2: PType): PType = result.flags.incl tfHasMeta proc makeOrType*(c: PContext, t1, t2: PType): PType = - + if t1.kind != tyOr and t2.kind != tyOr: result = newTypeS(tyOr, c, sons = @[t1, t2]) else: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 28d2647fdd22b..b7fac6046c99f 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1827,7 +1827,7 @@ proc goodLineInfo(arg: PNode): TLineInfo = proc makeTupleAssignments(c: PContext; n: PNode): PNode = ## expand tuple unpacking assignment into series of assignments - ## + ## ## mirrored with semstmts.makeVarTupleSection let lhs = n[0] let value = semExprWithType(c, n[1], {efTypeAllowed}) @@ -2384,7 +2384,7 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode = result = semDirectOp(c, n, flags) proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType = - result = newType(tyGenericInvocation, nextTypeId c.idgen, c.module) + result = newType(tyGenericInvocation, c.idgen, c.module) addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ, c.idgen) addSonSkipIntLit(result, t, c.idgen) result = instGenericContainer(c, info, result, allowMetaTypes = false) @@ -2538,7 +2538,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P let expected = expectedType.skipTypes(abstractRange-{tyDistinct}); expected.kind in {tySequence, tyOpenArray}): # seq type inference - var arrayType = newType(tyOpenArray, nextTypeId(c.idgen), expected.owner) + var arrayType = newType(tyOpenArray, c.idgen, expected.owner) arrayType.rawAddSon(expected[0]) if n[0].kind == nkSym and sfFromGeneric in n[0].sym.flags: # may have been resolved to `@`[empty] at some point, diff --git a/compiler/semfold.nim b/compiler/semfold.nim index e722f932fd20b..faa609584b8be 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -23,13 +23,13 @@ when defined(nimPreviewSlimSystem): proc errorType*(g: ModuleGraph): PType = ## creates a type representing an error state - result = newType(tyError, nextTypeId(g.idgen), g.owners[^1]) + result = newType(tyError, g.idgen, g.owners[^1]) result.flags.incl tfCheckedForDestructor proc getIntLitTypeG(g: ModuleGraph; literal: PNode; idgen: IdGenerator): PType = # we cache some common integer literal types for performance: let ti = getSysType(g, literal.info, tyInt) - result = copyType(ti, nextTypeId(idgen), ti.owner) + result = copyType(ti, idgen, ti.owner) result.n = literal proc newIntNodeT*(intVal: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = @@ -513,7 +513,7 @@ proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode = result = newSymNode(s, info) if s.typ.kind != tyTypeDesc: - result.typ = newType(tyTypeDesc, idgen.nextTypeId, s.owner) + result.typ = newType(tyTypeDesc, idgen, s.owner) result.typ.addSonSkipIntLit(s.typ, idgen) else: result.typ = s.typ diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 6f2ddd95a6317..548b922fe93c0 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -136,7 +136,7 @@ proc uninstantiate(t: PType): PType = else: t proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode = - var resType = newType(tyTypeDesc, nextTypeId c.idgen, sym) + var resType = newType(tyTypeDesc, c.idgen, sym) rawAddSon(resType, typ) result = toNode(resType, info) @@ -177,7 +177,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) result.info = traitCall.info of "arity": result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc)) - result.typ = newType(tyInt, nextTypeId c.idgen, context) + result.typ = newType(tyInt, c.idgen, context) result.info = traitCall.info of "genericHead": var arg = operand @@ -189,7 +189,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) # result = toNode(resType, traitCall.info) # doesn't work yet else: localError(c.config, traitCall.info, "expected generic type, got: type $2 of kind $1" % [arg.kind.toHumanStr, typeToString(operand)]) - result = newType(tyError, nextTypeId c.idgen, context).toNode(traitCall.info) + result = newType(tyError, c.idgen, context).toNode(traitCall.info) of "stripGenericParams": result = uninstantiate(operand).toNode(traitCall.info) of "supportsCopyMem": @@ -387,7 +387,7 @@ proc semUnown(c: PContext; n: PNode): PNode = elems[i] = unownedType(c, t[i]) if elems[i] != t[i]: someChange = true if someChange: - result = newType(tyTuple, nextTypeId c.idgen, t.owner) + result = newType(tyTuple, c.idgen, t.owner) # we have to use 'rawAddSon' here so that type flags are # properly computed: for e in elems: result.rawAddSon(e) @@ -398,7 +398,7 @@ proc semUnown(c: PContext; n: PNode): PNode = tyGenericInst, tyAlias: let b = unownedType(c, t[^1]) if b != t[^1]: - result = copyType(t, nextTypeId c.idgen, t.owner) + result = copyType(t, c.idgen, t.owner) copyTypeProps(c.graph, c.idgen.module, result, t) result[^1] = b @@ -441,7 +441,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym # proc body: result.ast = transform(c, orig.ast, origParamType, newParamType, oldParam, newParam) # proc signature: - result.typ = newProcType(result.info, nextTypeId c.idgen, result) + result.typ = newProcType(result.info, c.idgen, result) result.typ.addParam newParam proc semQuantifier(c: PContext; n: PNode): PNode = diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 33278af2fbc33..37c939bcd9cb9 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -180,7 +180,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode, constrCtx: var ObjConstrContext, defaults: var seq[PNode]) = let res = collectMissingCaseFields(c, branchNode, constrCtx, defaults) for sym in res: - let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), sym.typ.owner) + let asgnType = newType(tyTypeDesc, c.idgen, sym.typ.owner) let recTyp = sym.typ.skipTypes(defaultFieldsSkipTypes) rawAddSon(asgnType, recTyp) let asgnExpr = newTree(nkCall, diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index af77a197273f5..d5fc72760a907 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -405,7 +405,7 @@ proc transformSlices(g: ModuleGraph; idgen: IdGenerator; n: PNode): PNode = let op = n[0].sym if op.name.s == "[]" and op.fromSystem: result = copyNode(n) - var typ = newType(tyOpenArray, nextTypeId(g.idgen), result.typ.owner) + var typ = newType(tyOpenArray, idgen, result.typ.owner) typ.add result.typ[0] result.typ = typ let opSlice = newSymNode(createMagic(g, idgen, "slice", mSlice)) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 336c80c20c31a..48447c0eb894b 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -603,7 +603,7 @@ const proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSymKind, origResult: var PNode): PNode = ## expand tuple unpacking assignments into new var/let/const section - ## + ## ## mirrored with semexprs.makeTupleAssignments if typ.kind != tyTuple: localError(c.config, a.info, errTupleUnpackingTupleExpected % @@ -1499,7 +1499,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = localError(c.config, name.info, "{.exportc.} not allowed for type aliases") elif s.typ.kind == tyGenericBody: localError(c.config, name.info, "{.exportc.} not allowed for generic types") - + if tfBorrowDot in s.typ.flags: let body = s.typ.skipTypes({tyGenericBody}) if body.kind != tyDistinct: @@ -2076,7 +2076,7 @@ proc finishMethod(c: PContext, s: PSym) = if hasObjParam(s): methodDef(c.graph, c.idgen, s) -proc semCppMember(c: PContext; s: PSym; n: PNode) = +proc semCppMember(c: PContext; s: PSym; n: PNode) = if sfImportc notin s.flags: let isVirtual = sfVirtual in s.flags let isCtor = sfConstructor in s.flags @@ -2107,7 +2107,7 @@ proc semCppMember(c: PContext; s: PSym; n: PNode) = pragmaName & " procs must be defined in the same scope as the type they are virtual for and it must be a top level scope") else: localError(c.config, n.info, pragmaName & " procs are only supported in C++") - else: + else: var typ = s.typ[0] if typ != nil and typ.kind == tyObject and typ.itemId notin c.graph.initializersPerType: var initializerCall = newTree(nkCall, newSymNode(s)) @@ -2344,7 +2344,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, if sfCppMember * s.flags != {}: semCppMember(c, s, n) - + if n[bodyPos].kind != nkEmpty and sfError notin s.flags: # for DLL generation we allow sfImportc to have a body, for use in VM if c.config.ideCmd in {ideSug, ideCon} and s.kind notin {skMacro, skTemplate} and not diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 0a0050f2fa72f..ebbf75e351048 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -42,7 +42,8 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext, sons: seq[PType]): if prev == nil or prev.kind == tyGenericBody: result = newTypeS(kind, c, sons = sons) else: - result = newType(prev, sons) + result = prev + result.setSons(sons) if result.kind == tyForward: result.kind = kind #if kind == tyError: result.flags.incl tfCheckedForDestructor @@ -927,7 +928,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType sfSystemModule notin c.module.flags: message(c.config, n.info, warnInheritFromException, "") if not tryAddInheritedFields(c, check, pos, concreteBase, n): - return newType(tyError, nextTypeId c.idgen, result.owner) + return newType(tyError, c.idgen, result.owner) elif concreteBase.kind == tyForward: c.skipTypes.add n #we retry in the final pass @@ -949,7 +950,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType else: # partial object so add things to the check if not tryAddInheritedFields(c, check, pos, result, n, isPartial = true): - return newType(tyError, nextTypeId c.idgen, result.owner) + return newType(tyError, c.idgen, result.owner) semRecordNodeAux(c, n[2], check, pos, result.n, result) if n[0].kind != nkEmpty: @@ -1189,7 +1190,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyGenericInst: result = nil if paramType.lastSon.kind == tyUserTypeClass: - var cp = copyType(paramType, nextTypeId c.idgen, getCurrOwner(c)) + var cp = copyType(paramType, c.idgen, getCurrOwner(c)) copyTypeProps(c.graph, c.idgen.module, cp, paramType) cp.kind = tyUserTypeClassInst @@ -1229,7 +1230,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyConcept: result = addImplicitGeneric(c, - copyType(paramType, nextTypeId c.idgen, getCurrOwner(c)), paramTypId, + copyType(paramType, c.idgen, getCurrOwner(c)), paramTypId, info, genericParams, paramName) of tyGenericParam: @@ -1385,7 +1386,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, let finalType = if lifted != nil: lifted else: typ.skipIntLit(c.idgen) arg.typ = finalType arg.position = counter - if constraint != nil: + if constraint != nil: #only replace the constraint when it has been set as arg could contain codegenDecl arg.constraint = constraint inc(counter) @@ -1398,7 +1399,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, onDef(a[j].info, arg) a[j] = newSymNode(arg) - var r: PType = + var r: PType = if n[0].kind != nkEmpty: semTypeNode(c, n[0], nil) else: @@ -1514,7 +1515,7 @@ proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): b var newf = newNodeI(nkRecList, n.info) semRecordNodeAux(c, t.n, check, pos, newf, t) -proc containsGenericInvocationWithForward(n: PNode): bool = +proc containsGenericInvocationWithForward(n: PNode): bool = if n.kind == nkSym and n.sym.ast != nil and n.sym.ast.len > 1 and n.sym.ast[2].kind == nkObjectTy: for p in n.sym.ast[2][^1]: if p.kind == nkIdentDefs and p[1].typ != nil and p[1].typ.kind == tyGenericInvocation and @@ -1535,7 +1536,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = addSonSkipIntLit(result, t, c.idgen) template addToResult(typ, skip) = - + if typ.isNil: internalAssert c.config, false rawAddSon(result, typ) @@ -1655,7 +1656,7 @@ proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType = proc freshType(c: PContext; res, prev: PType): PType {.inline.} = if prev.isNil or prev.kind == tyGenericBody: - result = copyType(res, nextTypeId c.idgen, res.owner) + result = copyType(res, c.idgen, res.owner) copyTypeProps(c.graph, c.idgen.module, result, res) else: result = res @@ -2046,7 +2047,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semTypeNode(c, n[0], nil) if result != nil: let old = result - result = copyType(result, nextTypeId c.idgen, getCurrOwner(c)) + result = copyType(result, c.idgen, getCurrOwner(c)) copyTypeProps(c.graph, c.idgen.module, result, old) for i in 1.. Date: Tue, 21 Nov 2023 07:12:54 +1100 Subject: [PATCH 09/10] Don't provide suggestions for enum fields (#22959) Currently the suggestions create a lot of noise when creating enum fields. I don't see any way of a macro creating fields (when called inside an enum) so it should be safe to not show suggestions --------- Co-authored-by: Andreas Rumpf --- compiler/suggest.nim | 3 +++ nimsuggest/tests/tenum_field.nim | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 nimsuggest/tests/tenum_field.nim diff --git a/compiler/suggest.nim b/compiler/suggest.nim index aa8709b16b85c..5053fe66919a1 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -732,6 +732,9 @@ proc suggestDecl*(c: PContext, n: PNode; s: PSym) = if attached: inc(c.inTypeContext) defer: if attached: dec(c.inTypeContext) + # If user is typing out an enum field, then don't provide suggestions + if s.kind == skEnumField and c.config.cmd == cmdIdeTools and exactEquals(c.config.m.trackPos, n.info): + suggestQuit() suggestExpr(c, n) proc suggestStmt*(c: PContext, n: PNode) = diff --git a/nimsuggest/tests/tenum_field.nim b/nimsuggest/tests/tenum_field.nim new file mode 100644 index 0000000000000..4ceb3e0216a09 --- /dev/null +++ b/nimsuggest/tests/tenum_field.nim @@ -0,0 +1,17 @@ +discard """ +$nimsuggest --tester $file +>sug $1 +>sug $2 +sug;;skConst;;tenum_field.BarFoo;;int literal(1);;$file;;10;;6;;"";;100;;Prefix +""" + +proc something() = discard + +const BarFoo = 1 + +type + Foo = enum + # Test that typing the name doesn't give suggestions + somethi#[!]# + # Test that the right hand side still gets suggestions + another = BarFo#[!]# From 8c56e806ae6a9db9928340a4b87ba50f87a035a2 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Tue, 21 Nov 2023 04:17:20 +0800 Subject: [PATCH 10/10] closes #12464; adds a test case (#22967) closes #12464 --- tests/assign/tvariantasgn.nim | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/assign/tvariantasgn.nim b/tests/assign/tvariantasgn.nim index 1c3deeae15494..4c3c38ca58beb 100644 --- a/tests/assign/tvariantasgn.nim +++ b/tests/assign/tvariantasgn.nim @@ -24,3 +24,16 @@ s = TAny(kind: nkInt, intVal: 78) # s = nr # works nr = s # fails! echo "came here" + +block: # bug #12464 + type + Foo = object + case isFunc: bool + of false: nil + of true: + fun: proc(): int + + const i = Foo(isFunc: false) + + let j = i + doAssert not j.isFunc