fixes#25008
It seems that `semOverloadedCall` evaluates the same node twice using
`tryConstExpr` in order for `efExplain` to print all the diagnostic
output. The problem is that `tryConstExpr` has side effects, i.e., it
changes the slot index of variables after VM execution.
(cherry picked from commit 130eac2f93)
fixes#25240
> Deque items behavior is not the same on 2.0.16 and 2.2.0
The behavior seems to be caused by the temp introduced for the parameter
`deq.len`, which prevents it from being evaluated multiple times
(cherry picked from commit b7c02e9bad)
There might be a way to do this but I couldn't find anything about it.
This is a very simple thing that goes a long way in certain situations.
Trying to avoid needing to switch to nimscript just to get:
```nim
# config.nims
import os
let srcDir = currentSourcePath.parentDir()
switch("define", &"ProjPath:\"{srcDir}\"")
```
with this change just needs:
```
# nim.cfg
d %= "ProjPath=$srcDir"
```
(cherry picked from commit 544c26c0b8)
fixes#25123; fixes#11862
follow up https://github.com/nim-lang/Nim/pull/24442
ref https://github.com/nim-lang/Nim/pull/24441
> To fix this, fields from inactive branches are now detected in
semmacrosanity.annotateType (called in fixupTypeAfterEval) and marked to
prevent the codegen of their assignments. In
https://github.com/nim-lang/Nim/pull/24441 these fields were excluded
from the resulting node, but this causes issues when the node is
directly supposed to go back into the VM, for example as const values. I
don't know if this is the only case where this happens, so I wasn't sure
about how to keep that implementation working.
Object variants fields coming from inactive branches from VM are now
flagged `nfPreventCg`. We can ignore them, as done by the C backends.
(cherry picked from commit 5abd21dfa5)
fixes#25208
```nim
type Conf = object
val: int
const defaultConf = Conf(val: 123)
static:
var conf: Conf
conf = defaultConf
```
```nim
# opcLdConst is now always valid. We produce the necessary copy in the
# assignments now:
```
A `opcLdConst` is generated for `defaultConf` in `conf = defaultConf`.
According to the comment above, we need to handle the copy for
assignments of `opcLdConst`
(cherry picked from commit f009ea6c3e)
fixes#25046
```nim
proc makeiter(v: string): iterator(): string =
return iterator(): string =
yield v
# loops
for c in makeiter("test")():
echo "loops ", c
```
becomes
```nim
var temp = makeiter("test")
for c in temp():
echo "loops ", c
```
for closures that might have side effects
(cherry picked from commit 31d64b57d5)
fixes #25048
```nim
proc canFormAcycleAux =
of tyObject:
# Inheritance can introduce cyclic types, however this is not relevant
# as the type that is passed to 'new' is statically known!
# er but we use it also for the write barrier ...
if tfFinal notin t.flags:
# damn inheritance may introduce cycles:
result = true
```
It seems that all objects without `tfFinal` in their flags are
registering cycles. It doesn't seem that `Env` can be a cyclic type
because of inheritance since it is not going to be inherited after all
by another `Env` object type
(cherry picked from commit f191ba8ddd)
- Nim requires `SSL_library_init`, OpenSSL 3.x removed
`SSL_library_init`, Windows defaults to OpenSSL 3.x, then install
OpenSSL 1.x on Windows.
- Keep `jiro4989/setup-nim-action` at `v1`, because `v2` uses a YAML
"hardcoded" matrix of Nim versions, but this Bisect "dynamically" finds
the Nim version with a bug, therefore we cant hardcode Nim versions in
the YAML, the Bisect programmatically installs required Nim versions as
it goes bisecting commit-by-commit.
- Update `actions/checkout` from `v4` to `v5`.
- Add support for Nim `2.2.4`.
@ringabout
(cherry picked from commit 1ef81f4190)
fixes#25204
```nim
of mUnaryMinusI..mAbsI: unaryArithOverflow(p, e, d, op)
of mAddI..mPred: binaryArithOverflow(p, e, d, op)
```
Arithmetic operations may raise exceptions. So we cannot entrust the
optimizer to skip `result` initialization in this situation, as
complained righteously by `gcc` and `clang`: `warning: ‘result’ may be
used uninitialized [-Wmaybe-uninitialize]`.
With this PR, `clang -c -Wuninitialized -O1 @psystem.nim.c` no longer
gives warnings
(cherry picked from commit 7c65d9e747)
fixes#25205fixes#14873
```nim
type
SysLockObj {.importc: "pthread_mutex_t", pure, final,
header: """#include <sys/types.h>
#include <pthread.h>""", byref.} = object
when defined(linux) and defined(amd64):
abi: array[40 div sizeof(clong), clong]
```
Before this PR, in refc, `resetLoc` generates field assignments for each
fields of `importc` object. But the field `abi` is not a genuine field,
which doesn't exits in the struct. We could use `zeroMem` to reset the
memory if not leave it alone
(cherry picked from commit 02609f1872)
fixes#25205fixes#14873
```nim
type
SysLockObj {.importc: "pthread_mutex_t", pure, final,
header: """#include <sys/types.h>
#include <pthread.h>""", byref.} = object
when defined(linux) and defined(amd64):
abi: array[40 div sizeof(clong), clong]
```
Before this PR, in refc, `resetLoc` generates field assignments for each
fields of `importc` object. But the field `abi` is not a genuine field,
which doesn't exits in the struct. We could use `zeroMem` to reset the
memory if not leave it alone
(cherry picked from commit 02609f1872)
POSIX signal has an identical definition to ISO C signal:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/signal.html
```c
void (*signal(int sig, void (*func)(int)))(int);
/* more readably restated by glibc as */
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
```
However, std/posix had omitted the function's return value; this fixes
that.
To prevent breaking every single line of code ever that touched this
binding (including mine...), I've also made it discardable.
Additionally, I have noticed that bsd_signal's type signature is wrong -
it should have been identical to signal. But bsd_signal was already
removed in POSIX 2008, and sigaction is the recommended, portable POSIX
signal interface. So I just deleted the bsd_signal binding.
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 483389d399)
TODO list, copied from the documentation:
- [x] compiler/platform.nim Add os/cpu properties.
- [x] lib/system.nim Add os/cpu to the documentation for system.hostOS
and system.hostCPU.
- [x] ~~compiler/options.nim Add special os/cpu property checks in
isDefined.~~ seems unnecessary; isn't dont for most CPUs
- [x] compiler/installer.ini Add os/cpu to Project.Platforms field.
- [x] lib/system/platforms.nim Add os/cpu.
- [x] ~~std/private/osseps.nim Add os specializations.~~
- [x] ~~lib/pure/distros.nim Add os, package handler.~~
- [x] ~~tools/niminst/makefile.nimf Add os/cpu compiler/linker flags.~~
already done in https://github.com/nim-lang/Nim/pull/20943
- [x] tools/niminst/buildsh.nimf Add os/cpu compiler/linker flags.
For csource:
- [x] have compiler/platform.nim updated
- [x] have compiler/installer.ini updated
- [x] have tools/niminst/buildsh.nimf updated
- [x] have tools/niminst/makefile.nimf updated
- [ ] be backported to the Nim version used by the csources
- [ ] the new csources must be pushed
- [ ] the new csources revision must be updated in
config/build_config.txt
Additionally:
- [x] check relation to https://github.com/nim-lang/Nim/pull/20943
Possible future work:
- Porting Nim to s390x-specific operating systems, notably z/OS
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit f4497c6158)
...introduced by me in #24792. Sorry.
This fix doesn't avoid copying the `restrictedBody` twice in the
generated code but has the benefit of working.
Proper fix needs a detection that can set a const bool for a module
once. `when nimvm` is restricted in use and is difficult to dance
around. Some details in: #12517, #12518, #13038
I might have copied the buggy solution from some discussion and it might
have worked at some point, but it's small excuse.
(cherry picked from commit 6938fce40c)
fixes#24760
I tried `incl` `tfHasAsgn` to nontrivial assignment, but that solution
seems to break too many things. Instead, in this PR, `passCopyToSink`
now checks nontrivial assignment
(cherry picked from commit e958f4a3cd)
Workaround for #24596.
I also took the liberty to disable it on all targets with GCC, since
their documentation claims that it is also enabled on -Os.
---------
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 3f48576113)
fixes#24998
Basically it retraces back to the situation before
https://github.com/nim-lang/Nim/pull/18366 and
https://github.com/nim-lang/Nim/pull/18362, i.e.
```nim
import fuzz/a
import fuzz/a
```
```nim
import fuzz/a
from buzz/a
```
```nim
import fuzz/a except nil
from fuzz/a import addInt
```
All of these cases are now flagged as invalid and triggers a
redefinition error, i.e., each module name importing is treated as
consistent as the symbol definition
kinda annoying for importing/exporting with `when conditions` though
ref https://github.com/nim-lang/Nim/issues/18762https://github.com/nim-lang/Nim/issues/20907
```nim
from std/strutils import toLower
when not defined(js):
from std/strutils import toUpper
```
(cherry picked from commit 87ee9c84cb)
Inside a signal handler, you cannot allocate memory because the signal
handler, being implemented with a C
[`signal`](https://en.cppreference.com/w/c/program/signal) call, can be
called _during_ a memory allocation - when that happens, the CTRL-C
handler causes a segfault and/or other inconsistent state.
Similarly, the call can happen from a non-nim thread or inside a C
library function call etc, most of which do not support reentrancy and
therefore cannot be called _from_ a signal handler.
The stack trace facility used in the default handler is unfortunately
beyond fixing without more significant refactoring since it uses
garbage-collected types in its API and implementation.
As an alternative to https://github.com/nim-lang/Nim/pull/25110, this PR
removes the most problematic signal handler, namely the one for SIGINT
(ctrl-c) - SIGINT is special because it's meant to cause a regular
shutdown of the application and crashes during SIGINT handling are both
confusing and, if turned into SIGSEGV, have downstream effects like core
dumps and OS crash reports.
The signal handlers for the various crash scenarios remain as-is - they
may too cause their own crashes but we're already going down in a bad
way, so the harm is more limited - in particular, crashing during a
crash handler corrupts `core`/crash dumps. Users wanting to keep their
core files pristine should continue to use `-d:noSignalHandler` - this
is usually the better option for production applications since they
carry more detail than the Nim stack trace that gets printed.
Finally, the example of a ctrl-c handler performs the same mistake of
calling `echo` which is not well-defined - replace it with an example
that is mostly correct (except maybe for the lack of `volatile` for the
`stop` variable).
(cherry picked from commit 41ce86b577)
Raising exceptions halfway through a memory allocation is undefined
behavior since exceptions themselves require multiple allocations and
the allocator functions are not reentrant.
It is of course also expensive performance-wise to introduce lots of
exception-raising code everywhere since it breaks many optimisations and
bloats the code.
Finally, performing pointer arithmetic with signed integers is incorrect
for example on on a 32-bit systems that allows up to 3gb of address
space for applications (large address extensions) and unnecessary
elsewhere - broadly, stuff inside the memory allocator is generated by
the compiler or controlled by the standard library meaning that
applications should not be forced to pay this price.
If we wanted to check for overflow, the right way would be in the
initial allocation location where both the size and count of objects is
known.
The code is updated to use the same arithmetic operator style as for
refc with unchecked operations rather than disabling overflow checking
wholesale in the allocator module - there are reasons for both, but
going with the existing flow seems like an easier place to start.
(cherry picked from commit 8b9972c8b6)
Because `prevFields` and `currentFields` have been already quoted by
`'`, no need to add another.
The error message was
```
The fields ''x'' and ''y'' cannot be initialized together, because they are from conflicting branches in the case object.
```
(cherry picked from commit cdb750c962)
fixes#24844
it may not be used in other places except in `genTraverseProc`,
we have to generate a `typedesc` for this case, not a weak `typedec`
(cherry picked from commit a77d1cc6c1)
Also added some documentation to the header.
See: https://forum.nim-lang.org/t/13311
> I did try using the flag, but couldn't get it to work. If I do
-d:nimIoSelector, the defined check passes, but the other code fails to
compile because there is no const named nimIoSelector. It seemed like a
bug to me, do you have a working number compiler invocation?
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit d60e0211bc)
`DWORD` is defined as `int32`, so `DWORD(...)` would not work as
expected. When writing to files larger than 2GB, exception occurs:
```
unhandled exception: value out of range: 4294967295 notin -2147483648 .. 2147483647 [RangeDefect]
```
This PR is a quick fix for this.
P.S. Why `DWORD` is defined as `int32`?
(cherry picked from commit 4f09675d8a)
fixes#25117
errors on `requiresInit` of `result` if it is used before
initialization. Otherwise
```nim
# prevent superfluous warnings about the same variable:
a.init.add s.id
```
It produces a warning, and this line prevents it from being recognized
by the `requiresInit` check in `trackProc`
(cherry picked from commit c8456eacd5)
fixes#24093
transforms
```nim
let a = new array[1000, byte]
block:
for _ in cast[typeof(a)](a)[]:
discard
```
into
```nim
let a = new array[1000, byte]
block:
let temp = cast[typeof(a)](a)
for _ in temp[]:
discard
```
So it keeps the same behavior with the manual version
(cherry picked from commit 08d74a1c27)
Follow up to https://github.com/nim-lang/Nim/pull/25126
It changed `formatSize` outputs from some inputs, so some of existing
test code related to it need to be updated.
Sorry, I didn't know `tests/destructor/tnewruntime_strutils.nim` has
tests calls `formatSize`.
(cherry picked from commit 8ea8755cc0)
`strutils.formatSize` returns correct strings from large values close to
`int64.high`.
Round down `bytes` when it is converted to float.
(cherry picked from commit 065c4b443b)
fixes#25066
Probably it is not worth implementing comparing pointers at compile
time. For a starter, we can improve the error message instead of letting
it crash
(cherry picked from commit e2a294504e)
## Description
Fixed an inconsistency in the Nim manual's example for the `*+`
operator.
Previously, the example on line 4065 of `doc/manual.md` used variables
`a`, `b`, and `c`:
```nim
assert `*+`(3, 4, 6) == `+`(`*`(a, b), c)
```
This did not match the preceding call which directly used literals `3`,
`4`, `6`.
Updated the example to:
```nim
assert `*+`(3, 4, 6) == `+`(`*`(3, 4), 6)
```
This change makes the example consistent with the function call and
immediately understandable to readers without requiring prior variable
definitions.
## Rationale
* Improves clarity by avoiding undefined variables in a code snippet.
* Matches the example usage in the preceding line.
* Helps beginners understand the operator's behavior without additional
context.
## Changes
* **Edited**: `doc/manual.md` line 4065 — replaced variables `a`, `b`,
`c` with literals `3`, `4`, `6`.
## Issue
Closes#25084
(cherry picked from commit c6352ce0ab)
- Added support for SOCKS5h (h for proxy-side DNS resolving) to
httpclient
- Deprecated `auth` arguments for `newProxy` constructors, for auth to
be embedded in the url.
Unfortunately `http://example.com` is not currently reachable from
github CI, so the tests fail there for a few days already, I'm not sure
what can be done here.
(cherry picked from commit 161b321796)
* Add a new section to doc/tut2.md explaining interfaces.
* Provide a code example demonstrating how to simulate interfaces using
objects of closures.
* The example shows a basic IntFieldInterface with getter and setter
procedures.
This PR was inspired by the discussion in
https://forum.nim-lang.org/t/13217
---------
Co-authored-by: Emre Şafak <esafak@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
(cherry picked from commit bb93b39b58)
fixes#7179
```nim
var f = 751.0
echo f.int8
```
In this case, `int8(float)` yields different numbers for different
optimization levels, since float to int conversions are undefined
behaviors. In this PR, it mitigates this problem by conversions to same
size integers before converting to the final type: i.e.
`int8(int64(float))`, which has UB problems but is better than before
(cherry picked from commit 08d51e5c88)
A function with an illegal parameter name like
```nim
proc myproc(type: int) =
echo type
```
would uninformatively fail like so:
```nim
tkeywordparam.nim(1, 13) Error: expected closing ')'
```
This commit makes it return the following error:
```nim
tkeywordparam.nim(1, 13) Error: 'type' is a keyword and cannot be used as a parameter name
```
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Emre Şafak <esafak@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
(cherry picked from commit 9c1e3bf8fb)
revert #24896
Partially reverting #24896 in #25024 broke CI. So better revert it
completely so the CI is green. I'll investigate the issue later.
(cherry picked from commit 08642ffe34)
Reworked closureiter transformation.
- Convolutedly nested finallies should cause no problems now.
- CurrentException state now follows nim runtime rules (pushes and pops
appropriately), and mimics normal code, which is somewhat buggy, see
#25031
- Previously state optimization (removing empty states or extra jumps)
missed some opportunities, I've reimplemented it to do everything
possible to optimize the states. At this point any extra states or jumps
should be considered a bug.
The resulting codegen (compiled binaries) is also slightly smaller.
**BUT:**
- I had to change C++ reraising logic, see expt.nim. Because with
closure iters `currentException` is not always in sync with C++'s notion
of current exception. From my tests and understanding of C++ runtime
there should not be any problems, but I'm only 99% sure :)
- I've reused `nfNoRewrite` flag in one specific case during the
transformation. This flag is also used in term-rewriting logic. Again,
99% sure, these 2 scenarios will never intersect.
(cherry picked from commit 36f8cefa85)
Docs are routinely compiled on a different OS so often don't reflect
reality of CT-conditionals.
I bet there's a few of other places like this in the stdlib.
(cherry picked from commit 6bdb069a66)
fixes#25014
`implicitConv` tries to instantiate the supertype to convert to,
previously the bindings of `m` was shared with the bindings of the
converter but now an isolated match `convMatch` holds the bindings, so
`convMatch` is now used in the call to `implicitConv` instead of `m` so
that its bindings are used when instantiating the supertype.
(cherry picked from commit 97a6f42b56)
fixes#25009
Introduced by #24176, when matching a set type to another, if the given
set is a constructor and the element types match worse than a generic
match (which includes the case with no match), the match is always set
to a convertible match, without checking that it is at least a
convertible match. This is fixed by checking this.
(cherry picked from commit 334848f3ae)
fixes#24996
uses the lineinfos of `dest` is `ri` is not available (e.g. `=destroy`
doesn't have a second parameter)
(cherry picked from commit c22bfe6bc0)
fixes#25000
A failed match on `nfDotField` tries to assert that the name of the dot
field is an identifier node. I am not exactly sure how but at some point
typed generics causes an `nfDotField` call to contain a symchoice for
the field name. The compiler does not use the fact that the field name
is an identifier, so the assert is loosened to allow any identifier-like
node kind. Could also investigate why the symchoice gets created, my
guess is that typed generics detects that the match fails but still
sends it through generic prechecking and doesn't remove the
`nfDotField`, which is harmless and it might cause more trouble to work
around it.
(cherry picked from commit 8e5ed5dbb7)
fixes#23713
`linkTo` normally sets the sym of the type as well as the type of the
sym, but this is not wanted for custom pragmas as it would look up the
definition of the generic param and not the definition of its value. I
don't see a practical use for this either.
(cherry picked from commit 7701b3c7e6)
fxies #24981
`m.g.graph.procGlobals` could change because the right side of `.global`
assignment (e.g. `let a {.global.} = g(T)`) may trigger injections for
unhandled procs
(cherry picked from commit ffb993d5bd)
follows up #24871
For subscript assignments, if an overload of `[]=`/`{}=` is not found,
the LHS checks for overloads of `[]`/`{}` as a fallback, similar to what
field setters do since #24871. This is accomplished by just compiling
the LHS if the assignment overloads fail. This has the side effect that
the error messages are different now, instead of displaying the
overloads of `[]=`/`{}=` that did not match, it will display the ones
for `[]`/`{}` instead. This could be fixed by checking for `efLValue`
when giving the error messages for `[]`/`{}` but this is not done here.
The code for `[]` subscripts is a little different because of the
`mArrGet`/`mArrPut` overloads that always match. If the `mArrPut`
overload matches without a builtin subscript behavior for the LHS then
it calls `semAsgn` again with `mode = noOverloadedSubscript`. Before
this meant "fail to compile" but now it means "try to compile the LHS as
normal", in both cases the overloads of `[]=` are not considered again.
(cherry picked from commit 8752392838)
fixes#24940fixes#17552
Collects `{.global.}` (i.e. if it was changed into a hook call: `=copy`,
`=sink`) in `injectDestructorCalls` and generates it in the init
sections in cgen
(cherry picked from commit 3c0446b082)
fixes#24947
When injectdestructors detects that a variable is a tuple unpacking temp
(i.e. it is an `skTemp`, is not a cursor, and has tuple type) it does
not generate a destructor for it and only generates sink/bit assignments
for its components. However the reason it does not generate a destructor
is that it expects it to be fully unpacked, this is true for unpackings
in for loops but not for tuple unpacking assignments which supports `_`
since #22537. Tuple unpacking definitions for `var`/`let`/`const` do not
generate `skTemp` and use the same symbol kind as the definition so they
did not have this problem.
To keep this compatible, the `_` parts of the tuple unpacking
assignments are now not ignored and unpacked into `let _ = ...`, which
generates its own destructor. Another option might be to use `skLet`
instead of `skTemp` but this might cause changes to behavior like
additional copies, I am not sure about this though.
(cherry picked from commit 71c5a4f72c)
todo: We can also give a deprecation message for `ltPtr`/`lePtr`
matching for cstring in `magicsAfterOverloadResolution`
follow up https://github.com/nim-lang/Nim/pull/24942
(cherry picked from commit ade500b2cb)
Using `echo` to print file contents to stdout automatically adds a
newline at the end of the file contents. When using nimpretty to auto
format files on save in some editors which replace the file contents
with the formatted ones this means that with every save/format operation
an additional newline is added to the end of the file. Using
`stdout.write` does not automatically add a newline at the end
preventing this issue.
Fixes#24950
(cherry picked from commit c1e6cf812f)
explaining why the result may not be so surprising. Clean-up of stray
whitespace and insert of missing "in" along for the ride.
It's just not always faster or slower than `Table`. The difference
depends upon many factors such as (at least!): A) how much (if anything
- for `int` keys it is nothing) hash-comparison before `==` comparison
saves B) how much resizing happens (which may even vary from run to run
if end users are allowed to provide scale guess input), C) how much
comparison happens at all (i.e., table density), D) how much space/size
matters - like how close to a specific deployment "available" cache size
the table is.
If we want, we could add a sentence suggesting performance fans also try
`Table`, but the kind of low-level nature of the explanation strikes me
as already along those lines.
(cherry picked from commit 091fb5057b)
refs #24929, partially reverts #23403
Instead of using `Table[ItemId, T]`, the old algorithm is brought back
into `TIdTable[T]` to prevent a performance regression. The inheritance
removal from #23403 still holds, only `ItemId`s are stored.
(cherry picked from commit 82553384d1)
In `semExprWithType`: `if result.typ.kind in {tyVar, tyLent}: result =
newDeref(result)` derefed `var`/`lent`. Since it is not done for `sink`,
we need to skip `tySink` in the corresponding procs
(cherry picked from commit f56568d851)
Fixes#24895
- Remove all bio handling
- Remove all `sendPendingSslData` which only seems to make things work
by chance
- Wrap the client socket on `acceptAddr` (std/net does this)
- Do the SSL handshake on accept (std/net does this)
The only concern is if addWrite/addRead works well on Windows.
(cherry picked from commit 8518cf079f)
On windows, `HANDLE` type values are converted to `syncio.FileHandle` in
`lib/std/syncio.nim`, `lib/pure/memfiles.nim` and `lib/pure/osproc.nim`.
`HANDLE` type is `void *` on Windows and its size is larger then `cint`.
https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
This PR change `syncio.FileHandle` type so that converting `HANDLE` type
to `syncio.FileHandle` doesn't lose bits.
We can keep `FileHandle` unchanged and change some of parameter/return
type from `FileHandle` to an type same size to `HANDLE`, but it is
breaking change.
(cherry picked from commit eea4ce0e2c)
fixes#24898
A type is only overwritten if it is definitely a forward type, partial
object (symbol marked `sfForward`) or a magic type. Maybe worse for
performance but should be more correct. Another option might be to
provide a different value for `prev` for the `preserveSym` case but then
we cannot easily ignore only nominal type nodes.
(cherry picked from commit d966ee3fc3)
fixes#5631, fixes#8938, fixes#18855, fixes#19271, fixes#23885,
fixes#24877
`isTupleRecursive`, previously only called to give an error for illegal
recursions for:
* tuple fields
* types declared in type sections
* explicitly instantiated generic types
did not check for recursions in proc types. It now does, meaning proc
types now need a nominal type layer to recurse over themselves. It is
renamed to `isRecursiveStructuralType` to better reflect what it does,
it is different from a recursive type that cannot exist due to a lack of
pointer indirection which is possible for nominal types.
It is now also called to check the param/return types of procs, similar
to how tuple field types are checked. Pointer indirection checks are not
needed since procs are pointers.
I wondered if this would lead to a slowdown in the compiler but since it
only skips structural types it shouldn't take too many iterations, not
to mention only proc types are newly considered and aren't that common.
But maybe something in the implementation could be inefficient, like the
cycle detector using an IntSet.
Note: The name `isRecursiveStructuralType` is not exactly correct
because it still checks for `distinct` types. If it didn't, then the
compiler would accept this:
```nim
type
A = distinct B
B = ref A
```
But this breaks when attempting to write `var x: A`. However this is not
the case for:
```nim
type
A = object
x: B
B = ref A
```
So a better description would be "types that are structural on the
backend".
A future step to deal with #14015 and #23224 might be to check the
arguments of `tyGenericInst` as well but I don't know if this makes
perfect sense.
(cherry picked from commit 7f0e07492f)
fixes#24887 (really just this [1 line
commit](632c7b3397)
would have been enough to fix the issue but it would ignore the general
problem)
When a type definition is encountered where the symbol already has a
type (not a forward type), the type is left alone (not reset to
`tyForward`) and the RHS is handled differently: The RHS is still
semchecked, but the type of the symbol is not updated, and nominal type
nodes are ignored entirely (specifically if they are the same kind as
the symbol's existing type but this restriction is not really needed).
If the existing type of the symbol is an enum and and the RHS has a
nominal enum type node, the enum fields of the existing type are added
to scope rather than creating a new type from the RHS and adding its
symbols instead.
The goal is to prevent any incompatible nominal types from being
generated during resem as in #24887. But it also restricts what macros
can do if they generate type section AST, for example if we have:
```nim
type Foo = int
```
and a macro modifies the type section while keeping the symbol node for
`Foo` like:
```nim
type Foo = float
```
Then the type of `Foo` will still remain `int`, while it previously
became `float`. While we could maybe allow this and make it so only
nominal types cannot be changed, it gets even more complex when
considering generic params and whether or not they get updated. So to
keep it as simple as possible the rule is that the symbol type does not
change, but maybe this behavior was useful for macros.
Only nominal type nodes are ignored for semchecking on the RHS, so that
cases like this do not cause a regression:
```nim
template foo(): untyped =
proc bar() {.inject.} = discard
int
type Foo = foo()
bar() # normally works
```
However this specific code exposed a problem with forward type handling:
---
In specific cases, when the type section is undergoing the final pass,
if the type fits some overly general criteria (it is not an object,
enum, alias or a sink type and its node is not a nominal type node), the
entire RHS is semchecked for a 2nd time as a standalone type (with `nil`
prev) and *maybe* reassigned to the new semchecked type, depending on
its type kind. (for some reason including nominal types when we excluded
them before?) This causes a redefinition error if the RHS defines a
symbol.
This code goes all the way back to the first commit and I could not find
the reason why it was there, but removing it showed a failure in
`thard_tyforward`: If a generic forward type is invoked, it is left as
an unresolved `tyGenericInvocation` on the first run. Semchecking it
again at the end turns it into a `tyGenericInst`. So my understanding is
that it exists to handle these loose forward types, but it is way too
general and there is a similar mechanism `c.skipTypes` which is supposed
to do the same thing but doesn't.
So this is no longer done, and `c.skipTypes` is revamped (and renamed):
It is now a list of types and the nodes that are supposed to evaluate to
them, such that types needing to be updated later due to containing
forward types are added to it along with their nodes. When finishing the
type section, these types are reassigned to the semchecked value of
their nodes so that the forward types in them are fully resolved. The
"reassigning" here works due to updating the data inside the type
pointer directly, and is how forward types work by themselves normally
(`tyForward` types are modified in place as `s.typ`).
For example, as mentioned before, generic invocations of forward types
are first created as `tyGenericInvocation` and need to become
`tyGenericInst` later. So they are now added to this list along with
their node. Object types with forward types as their base types also
need to be updated later to check that the base type is correct/inherit
fields from it: For this the entire object type and its node are added
to the list. Similarly, any case where whether a component type is
`tyGenericInst` or `tyGenericInvocation` matters also needs to cascade
this (`set` does presumably to check the instantiated type).
This is not complete: Generic invocations with forward types only check
that their base type is a forward type, but not any of their arguments,
which causes #16754 and #24133. The generated invocations also need to
cascade properly: `Foo[Bar[ForwardType]]` for example would see that
`Bar[ForwardType]` is a generic invocation and stay as a generic
invocation itself, but it might not queue itself to be updated later.
Even if it did, only the entire type `Foo[Bar[ForwardType]]` needs to be
queued, updating `Bar[ForwardType]` by itself would be redundant or it
would not change anything at all. But these can be done later.
(cherry picked from commit 525d64fe88)
refs https://github.com/nim-lang/RFCs/issues/559
Parses as an `nkIdentDefs` with an `nkEmpty` name. Pragma is allowed,
can remove this if necessary.
Fine to close and postpone for later
(cherry picked from commit 032da90ed1)
closes#24875
Refc gives `0 (invalid data!)`, but since enum `$` procs on arc are
generated during enum declarations we might not have access to string
concatenation and integer `$`, so it generates a static string. Just
chose an empty string for this.
(cherry picked from commit 5aaba213d4)
follows up #24855
Before #24855, the test would work because the indentation of the `;`
token would be passed to `semiStmtList` and so its indentation of `-1`
would be used. Now the `;` token is skipped and the indentation of the
first `discard` is used which is > -1. However the second discard has an
indentation of -1 because it's on the same line: this fails the
`sameInd(p) or realInd(p)` check since -1 is never >= the indent of the
first discard.
For compatibility with the parser up to this point this indent check is
entirely removed, meaning the indent is ignored. Because the `;` is
basically never on a separate line, this was already the case for
basically every use. `semiStmtList` is wrapped in a `withInd` anyway
which resets the indent after it's done, since the entire statement list
is wrapped in a `()`. To disallow dedents, the above check could be
fixed to use `sameOrNoInd` instead of `sameInd`, which is done in the
commented version of this check.
(cherry picked from commit 3d14381473)
fixes#24863, refs #23787 and #24316
Working off the minimized example, my understanding of the issue is: `n`
captures `r` as `:envP.r1` where `:envP` is the environment of `b`, then
`proc () = n()` does the lambda lifting of `n` again (which isn't done
if the `proc ()` is marked `{.closure.}`, hence the workaround) which
then captures the `:envP` as another field inside the `:envP`, so it
generates `:envP.:envP_2.r1` but the `.:envP_2` field is `nil`, so it
causes a segfault.
The problem is that the capture of `r` in `n` is done inside
`detectCapturedVars` for the surrounding closure iterator: inner procs
are not special cased and traversed as regular nodes, so it thinks it's
inside the iterator and generates a field access of `:envP` freely. The
lambda lifting version of `detectCapturedVars` ignores inner procs and
works off of symbol uses (anonymous iterator and lambda declarations
pretend their symbol is used).
As a naive solution, closure iterators now also ignore inner proc
declarations same as `lambdalifting.detectCapturedVars`, but unlike it
they also don't do anything for the inner proc symbols. Lambdalifting
seems to properly handle the lifted variables but in the worst case we
can also make sure `closureiters.detectCapturedVars` traverses inner
procs by marking every local of the closure iter used in them as needing
lifting (but not doing the lifting). This does not seem necessary for
now so it's not done (was done and reverted in [this
commit](9bb39a9259)),
but regressions are still possible
(cherry picked from commit c06bb6cc03)
refs https://forum.nim-lang.org/t/12785, refs #4711
The code was already there that when `propertyWriteAccess` returns `nil`
(i.e. cannot find a setter), `semAsgn` turns the [LHS into a call and
semchecks
it](1ef9a656d2/compiler/semexprs.nim (L1941-L1948)),
meaning if a setter cannot be found a getter will be assigned to
instead. However `propertyWriteAccess` never returned nil, because
`semOverloadedCallAnalyseEffects` was not called with `efNoUndeclared`
and so produced an error directly. So `efNoUndeclared` is passed to this
call so this code works as intended.
This fixes the issue described in #4711 which was closed because
subscripts do not have the same behavior implemented. However we can
implement this for subscripts as well (I have an implementation ready),
it just changes the error message from the failed overloads of `[]=` to
the failed overloads of `[]` for the LHS, which might be misleading but
is consistent with the error messages for any other assignment. I can do
this in this PR or another one.
(cherry picked from commit 4d9e5e8b6d)
split from #24204, closes#7674
The `{.size.}` pragma no longer restricts the given size to 1, 2, 4 or 8
if it is used for an imported type. This is not tested very thoroughly
but there's no obvious reason to disallow it.
(cherry picked from commit 1ef9a656d2)
fixes#4554, fixes#10900, fixes#13843, fixes#19471, fixes#19517
Instead of matching generic converters to their arguments using the full
call match bindings, a new match is created for them (from which the
bindings are used to instantiate the converter return type). Then when
instantiating generic converters, they are matched to their argument
again to get their bindings again instead of using the call bindings.
This prevents generic converters which match more than once from
interfering with each other's bindings.
(cherry picked from commit 334f96c05a)
Implements #24569
Adds `--stdinfile` flag for specifying the file to use in place of
`stdinfile.nim` in error messages. Will enable easier integration of
tooling with nim check
(cherry picked from commit 0cba752c8a)
To protect against crashes when this stops being experimental, in most
places handled the exact same as normal symchoices (not encountered in
typed ast)
(cherry picked from commit 4d075dc301)
fixes#24484, fixes#24672
When an array, set or tuple constructor has an element that resolves to
`tyFromExpr`, the type of the entire literal is now set to `tyFromExpr`
and the subsequent elements are not matched to any type.
The remaining expressions are still typed (a version of the PR before
this called `semGenericStmt` on them instead), however elements with int
literal types have their types set to `nil`, since generic instantiation
removes int literal types and the int literal type is required for
implicitly converting the int literal element to the set type. Tuples
should not really need this but it is done for them anyway in case it
messes up some type inference
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 897126a711)
Combining two small PRs in one here. The test case explains what was
wrong with the concepts and for naitivesockets, it's typical to adjust
`ai_flags` so I opened that up.
(cherry picked from commit d4098e6ca0)
Previously it would try to parse the semicolon as its own statement and
produce an `nkEmpty` node
Also more than 1 semicolon in an expression list i.e. `(a;; b)` gives an
"expression expected" error in `semiStmtList` when multiple semicolons
are allowed in normal statements, this could be fixed by changing the
`if tok.kind == tokSemicolon` check to a `while` but it does not match
the grammar so not done here.
(cherry picked from commit 918f972369)
`=copy` should be treated like `=` instead of `shallowCopy`, i.e.,
`nkFastAsgn` by default. `mAsgn` is treated similar in sempass2 too
(cherry picked from commit 51166ab382)
ref https://github.com/nim-lang/Nim/issues/24764
To keep destructors injected consistently, we need to transform `mAsgn`
properly into `nkSinkAsgn` and `nkAsgn`. This PR is the first step
towards overhauling hook injections.
In this PR, hooks (except mAsgn) are treated consistently whether it is
resolved in matching or instantiated by sempass2. It also fixes a
spelling `=wasMoved` to its normalized version, which caused no
replacing generic hook calls with lifted hook calls.
(cherry picked from commit 40a1ec21d7)
fixes#24847
Object constructors call `fillObjectFields` when a field inside the
constructor does not have a location, however when the field is from a
base type this does not process it. Now `fillObjectFields` also calls
itself for the base type to fix this but not sure if this is a good
solution as `fillObjectFields` is used in other places too.
(cherry picked from commit a625fab098)
implements https://github.com/nim-lang/RFCs/issues/557
It inserts defect handing into a bare except branch
```nim
try:
raiseAssert "test"
except:
echo "nope"
```
=>
```nim
try:
raiseAssert "test"
except:
# New behaviov, now well-defined: **never** catches the assert, regardless of panic mode
raiseDefect()
echo "nope"
```
In this way, `except` still catches foreign exceptions, but panics on
`Defect`. Probably when Nim has `except {.foreign.}`, we can extend
`raiseDefect` to foreign exceptions as well. That's supposed to be a
small use case anyway.
`--legacy:noPanicOnExcept` is provided for a transition period.
(cherry picked from commit 26b86c8f4d)
fixes#24837
I really wanted to name the variable just `stream` and leave `defer:
...` and `result =...` out, but the compiler says the variable is
redefined, so this is the form.
(cherry picked from commit 2ed45eb848)
fixes#24806
Blocks don't merge symbols that are used before destruction to the
parent scope, which causes `wasMoved; destroy` to elide incorrectly
(cherry picked from commit 73aeac81d1)
fixes#24801
Because distinct `seq` types match `proc `=destroy`*[T](x: var T)
{.inline, magic: "Destroy".}`. But the Nim compiler generates lifted seq
types for corresponding distinct types. So we skip the address for
distinct types.
Related to https://github.com/nim-lang/Nim/pull/22207 I had a hard time
finding the other place where generic destructors get replaced by
attachedDestructors
(cherry picked from commit 4352fa2ef0)
```nim
proc foo =
var x = "1234"
var y = x
when nimvm:
discard
else:
var s = x
doAssert s == "1234"
doAssert y == "1234"
static: foo()
foo()
```
`dfa` chooses the `nimvm` branch, `x` is misread as a last read and
`wasMoved`.
`injectDestructor` is used for codegen and is not used for vmgen. It's
reasonable to choose the codegen path instead of the `nimvm` path so the
code works for codegen. Though the problem is often hidden by
`cursorinference` or `optimizer`.
found in https://github.com/nim-lang/Nim/pull/24831
(cherry picked from commit 3617d2e077)
This change adds `withValue` templates for the `Table` type that are
able to operate on immutable table values -- the existing implementation
requires a `var`.
This is needed for situations where performance is sensitive. There are
two goals with my implementation:
1. Don't create a copy of the value in the table. That's why I need the
`cursor` pragma. Otherwise, it would copy the value
2. Don't double calculate the hash. That's kind of intrinsic with this
implementation. But the only way to achieve this without this PR is to
first check `if key in table` then to read `table[key]`
I brought this up in the discord and a few folks tried to come up with
options that were as fast as this, but nothing quite matched the
performance here. Thread starts here:
https://discord.com/channels/371759389889003530/371759389889003532/1355206546966974584
(cherry picked from commit 0f5732bc8c)
Script wasn't working on my machine with GDB 16.2
Main issues
- `gdb.types` wasn't imported, leading to import error on initial load
- dollar function didn't work with the new mangling scheme
Fixes them, also updates the test script to work with some new mangling
changes.
Test evidence

(cherry picked from commit e0a4876981)
- Allows using with `--experimental:strictFuncs`
- `{.cast(noSideEffect).}:` inside the proc was required to mutate
`s.len`, same as used in `newSeqImpl`.
- Removed now unnecessary `noSideEffect` casts in `system.nim`
-
Closes#24811
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit ecdcffed4b)
- `system.substr` now uses `copymem` when available, introducing a small
template for nimvm detection (#12517#12518)
- Docs are updated to clarify behaviour on out-of-bounds input
- Runnable examples cover more edge cases and do not repeat between
overloads
- Docs now explain the difference between overloads
What bothers me is that the `substr*(a: openArray[char]): string =`
which was added by @beef331 is practically an implementation of #14810,
which is just a conversion from `openArray` to `string` but somehow it
ended up being a `substr` overload, even though its behaviour is totally
different, _the "substringing" is performed by a previous step_
(conversion to openArray) and the bounds are not checked. I'm not sure
it's that great for overloads to differ in subtle ways so much.
What are the cases that `substr` covers now, that prohibit renaming it
to `toString` (or something like that)?
(cherry picked from commit b82d7e8ba1)
Multiple replacements based on character sets in a single pass. Useful
for string sanitation. Follows existing `multiReplace` semantics.
Note: initially copied the substring version logic with a `while` and a
named block break, but Godbolt showed it had produced slightly larger
assembly using higher registers than the final version.
- [x] Tests
- [x] changelog.md
(cherry picked from commit 909f3b8b79)
Follow up https://github.com/nim-lang/Nim/pull/19512
ref https://github.com/nim-lang/Nim/issues/24794
Otherwise, `/Users/blue/Desktop/Nim/lib/system/mm/malloc.nim(4, 1)
Error: redefinition of 'allocImpl'; previous declaration here:
/Users/blue/Desktop/Nim/lib/system/memalloc.nim(51, 8)`
In `proc allocImpl*(size: Natural): pointer {.noconv, rtl, tags: [],
benign, raises: [].}`, `rtl` means it is an `importc` function instead
of a proc forward decl.
(cherry picked from commit d15705e05b)
closes#24780
This proc `genStmt` is only called to run the VM in `vm.evalStmt`,
otherwise it's not used in vmgen. Now it acts the same as `proc
gen(PCtx, PNode)`, used by `discard` statements, which just calls
`freeTemp` on the dest if it was set rather than erroring.
(cherry picked from commit fcba14707a)
Async SSL socket SIGSEGV's sometimes when calling socket.close() while
send/recv. The issue was found here
https://github.com/nitely/nim-hyperx/pull/59.
Possibly related: #24024
This can occur when closing the socket while sending or receiving,
because `socket.sslHandle` is freed. The sigsegv can also occur on calls
that require `socket.bioIn` or `socket.bioOut` because those use
`socket.sslHandle` internally. This PR checks sslHandle is set before
doing any operation that requires it.
(cherry picked from commit 9ace1f97ac)
fixes#24773
`c.inheritancePenalty` is supposed to be used for the entire match, but
in these places the inheritance penalty of a single argument overrides
the entire match penalty. The `+ ord(c.inheritancePenalty < 0)` is
copied from other places that use the same idiom, the intent is that the
existing penalty changes from -1 to 0 first to mark that it participates
in inheritance before adding the inheritance depth.
---------
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
(cherry picked from commit fb93295344)
Otherwise, `sink T` is kept as it is. This PR treats sink types as its
base types for the arguments. So the concept would match both cases
Required by https://github.com/nim-lang/Nim/pull/24724
(cherry picked from commit 9ebfa7973a)
fixes#24772
The old implementation was said to copied from Windows SDK,
but you can find the newer SDK's definition is updated and the sign is
reversed compared to the old.
Also, `__builtin_nanf("")` is used if available,
which is more efficient than previous (In x86_64 gcc, latter produces
32B code but former just 8B).
(cherry picked from commit 4f32624641)
fixes#24770
e.g. `seq[(ObjectWithDestructors, string)]`/ For refc, a seq with
elements that have destructors will have `hasAsgn` flags. The flag is
the criteria whether a seq is thought as `containsGarbageCollectedRef`.
i.e. whether to `registerTraverseProc` for the type.
The culprit seems to be that `searchTypeForAux` doesn't consider the
element type of sequence, even it contains a string that should belong
to `GarbageCollectedRef`.
With this PR:
It now generates
```
nimRegisterThreadLocalMarker(TM__mSF73dT1lSI7DG58StKHLQ_5);
```
in refc
(cherry picked from commit dfa482e292)
refs #24766
Detect when we track a call to a forward declaration without explicit
`raises` effects, then when the `raises` check fails for the proc, give
a hint that this forward declaration was tracked as potentially raising
any exception.
(cherry picked from commit 82891e6850)
motivating example:
```nim
iterator p(a: openArray[char]): int =
if a.len != 0:
if a[0] != '/':
discard
for t in p(""): discard
```
The compiler wants to evaluate `a[0]` at compile time even though it is
protected by the if statement above it. Similarly expressions like
`a.len != 0 and a[0] == '/'` have problems. It seems like the logic in
semfold needs to be more aware of branches to positively identify when
it is okay to fail compilation in these scenarios. It's a bit tough
though because it may be the case that non-constant expressions in
branching logic can properly protect some constant expressions.
(cherry picked from commit 850f327713)
fixes#24755, refs #24710
Instead of using the node from `indexTypesMatch` which inserts a hidden
conv node, just change the type of the node back to the old type
directly
(cherry picked from commit 38ad336c69)
fixes#24751
`typeof` leaves the object constructor as a call node for some reason,
in this case it tries to access the first child of the type node but the
object has no fields so the type field is empty. Alternatively the
optimizer can stop looking into `typeof`
(cherry picked from commit e2e7790779)
### Issue
When using `tcc` as backend to compile a trivial program
```
nim c --cc:tcc --skipCfg a.nim
```
, errors reported:
```
tcc: error: undefined symbol 'fabs'
```
### Solution
`fabs` belongs to libm. With these two options added, one can compile
with an additional clib option:
```
nim c --cc:tcc --skipCfg --clib:m a.nim
```
(cherry picked from commit dfd2987118)
Without this fix, trying to use `scanTuple` in a generic proc imported
from a different module fails to compile (`undeclared identifier:
'scanf'`):
```nim
# module.nim
import std/strscans
proc scan*[T](s: string): (bool, string) =
s.scanTuple("$+")
```
```nim
# main.nim
import ./module
echo scan[int]("foo")
```
Workaround is to `export scanf` in `module.nim` or `import std/strscans`
in `main.nim`.
(cherry picked from commit f8294ce06e)
Yet another one of these. Multiple changes piled up in this one. I've
only minimally cleaned it for now (debug code is still here etc). Just
want to start putting this up so I might get feedback. I know this is a
lot and you all are busy with bigger things. As per my last PR, this
might just contain changes that are not ready.
### concept instantiation uniqueness
It has already been said that concepts like `ArrayLike[int]` is not
unique for each matching type of that concept. Likewise the compiler
needs to instantiate a new proc for each unique *bound* type not each
unique invocation of `ArrayLike`
### generic parameter bindings
Couple of things here. The code in sigmatch has to give it's bindings to
the code in concepts, else the information is lost in that step. The
code that prepares the generic variables bound in concepts was also
changed slightly. Net effect is that it works better.
I did choose to use the `LayedIdTable` instead of the `seq`s in
`concepts.nim`. This was mostly to avoid confusing myself. It also
avoids some unnecessary movings around. I wouldn't doubt this is
slightly less performant, but not much in the grand scheme of things and
I would prefer to keep things as easy to understand as possible for as
long as possible because this stuff can get confusing.
### various fixes in the matching logic
Certain forms of modifiers like `var` and generic types like
`tyGenericInst` and `tyGenericInvocation` have logic adjustments based
on my testing and usage
### signature matching method adjustment
This is the weird one, like my last PR. I thought a lot about the
feedback from my last attempt and this is what I came up with. Perhaps
unfortunately I am preoccupied with a slight grey area. consider the
follwing:
```nim
type
C1 = concept
proc p[T](s: Self; x: T)
C2[T] = concept
proc p(s: Self; x: T)
```
It would be temping to say that these are the same, but I don't think
they are. `C2` makes each invocation distinct, and this has important
implications in the type system. eg `C2[int]` is not the same type as
`C2[string]` and this means that signatures are meant to accept a type
that only matches `p` for a single type per unique binding. For `C1` all
are the same and the binding `p` accepts multiple types. There are
multiple variations of this type classes, `tyAnything` and the like.
The make things more complicated, an implementation might match:
```nim
type
A = object
C3 = concept
proc p(s: Self; x: A)
```
if the implementation defines:
```nim
proc p(x: Impl; y: object)
```
while a concept that fits `C2` may be satisfied by something like:
```nim
proc p(x: Impl; y: int)
proc spring[T](x: C2[T])
```
it just depends. None of this is really a problem, it just seems to
provoke some more logic in `concepts.nim` that makes all of this (appear
to?) work. The logic checks for both kinds of matches with a couple of
caveats. The fist is that some unbind-able arrangements may be matched
during overload resolution. I don't think this is avoidable and I
actually think this is a good way to get a failed compilation. So, first
note imo is that failing during binding is preferred to forcing the
programming to write annoying stub procs and putting insane gymnastics
in the compiler. Second thing is: I think this logic is way to accepting
for some parts of overload resolutions. Particularly in `checkGeneric`
when disambiguation is happening. Things get hard to understand for me
here. ~~I made it so the implicit bindings to not count during
disambiguation~~. I still need to test this more, but the thought is
that it would help curb excessive ambiguity errors.
Again, I'm sorry for this being so many changes. It's probably
inconvenient.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit dfab30734b)
fixes#24743, refs #24718
We cannot do this in general for any expression with generic type
because the `typeof` logic is called for things like `type Foo` in:
```nim
type Foo[T] = object
proc init(_: type Foo) = discard
```
We also cannot use `containsUnresolvedType` to work around this specific
case because the base type of `static[auto]` is not unresolved, it is a
typeclass that isn't lifted to a parameter. The behavior of generating
`tyFromExpr` is also consistent with pre-2.0, so we do this in this
special case of `static`.
(cherry picked from commit 569d02e212)
fixes#24736
The VM can produce integer nodes with no types as set elements, which
are later reannotated in `semmacrosanity.annotateType`. However the case
of ranges was not handled properly. Not sure why this is a regression,
probably unrelated but will have to see the bisect result to make sure.
Note. Originally tried to fix this in `opcInclRange`, generated for and
only for range expressions in set constructors, this seems to add the
range node directly to the set node without checking if it has overlap
with the existing elements by calling `nimsets` so an expression like
`{cctNone, cctNone..cctHeader}` can produce `{0, 0..5}`. Doesn't seem to
cause problems but `opcIncl` for single elements does check for overlap.
Something else to note is that integer nodes produced by `nimsets` have
proper types, so another option instead of relying on semmacrosanity to
fix this would be to make `opcIncl` and `opcInclRange` call `nimsets` to
add to the set node, but this might lose performance.
(cherry picked from commit e39d152b89)
fixes#24705
```nim
proc xxx(v: static int) =
echo v
xxx(10)
xxx(20)
```
They are mangled as `_ZN14titaniummangle7xxx_s10E` and
`_ZN14titaniummangle7xxx_s20E` with `--debugger:native`. Static
parameters are prefixed with `_s` to distinguish simple cases like
`xxx(10, 15)` and `xxx(101, 5)` if `xxx` supports two `static[int]`
parameters
(cherry picked from commit c452275e29)
fixes#24698
The same aim as #24224 but for tuple constructors. The difference here
is that the type of a tuple constructor is always going to be valid
unlike array constructors which can have `seq` etc types, so we can just
generate a conversion again. If the conversion fails, it is ignored
similar to #24611, this is to protect against modified typed nodes in
macros.
Also #24611 was only adapted to `semTupleFieldsConstr` and not
`semTuplePositionsConstr`, this is now fixed.
(cherry picked from commit 49dfc3a0d4)
fixes#24715
In generic typechecking, unresolved static param symbols (i.e.
`skGenericParam`) have [the static type
itself](1f8da3835f/compiler/semexprs.nim (L1483-L1485))
as their type when used in an expression. This is not the case when the
static param is resolved (the type is wrapped in static when necessary),
but semchecking of types and generic typechecking expects the type of
the value to be wrapped in `static` (at least `array[N, int]` breaks).
So for now, to solve the issue, `typeof` just skips static types.
(cherry picked from commit 514a25c9a2)
fixes#24725
`lacksMTypeField` doesn't take the base types into consideration. And
for ` {.inheritable, pure.}`, it shouldn't generate a `m_type` field.
(cherry picked from commit e449813c61)
Both cases are now valid. Though, it could be problematic to mix two
cases together as built-in types have non var T destructors
(cherry picked from commit 93fb219f10)
fixes#24664
```nim
proc main() =
for i in 0..1:
var s = "12345"
s.add s
echo s
main()
```
In the given example, `add` contains two steps: `prepareAdd` and
`appendString`. In the first step, a new buffer is created in order to
store the final doubled string. But it doesn't copy the null terminator,
neither zeromem the left unused spaces. It causes a problem because
`appendString` will copy itself which doesn't end with `\0` properly so
contaminated memory is copied instead.
```
var s = 12345\0
prepareAdd:
var s = 12345xxxxx\0
appendString:
var s = 1234512345x
```
(cherry picked from commit 1f07fdd2dc)
Applies #24144 to the equivalent matches of generic types, and adds the
behavior to matches of generic invocations to generic invocations. Not
encountered in many cases so it's hard to come up with tests but an
example is the test code in #24688, the match to the generic body never
sets the inheritance penalty leaving it at -1, but the match to the
generic invocation sets it to 0 which matches worse, when it should set
it to -1 because the object does not participate in inheritance.
(cherry picked from commit ebeef1067f)
ref https://github.com/nim-lang/Nim/pull/24686
With this PR
```nim
import std/streams
proc foo() =
var name = newStringStream("2r2")
raise newException(ValueError, "sh")
try:
foo()
except:
discard
echo 123
```
this example no longer leaks
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 510ac84518)
fixes#8758, fixes#10828, fixes#12172, fixes#21610, fixes#23803,
fixes#24633, fixes#24634, succeeds #24085
We simply track the symbol ID of every traversed `var`/`let` definition
in `vmgen`, then these symbols are always considered evaluable in the
current `vmgen` context. The set of symbols is reset before every
generation, but both tests worked properly without doing this including
the nested `const`, so maybe it's already done in some way I'm not
seeing.
(cherry picked from commit a5cc33c1d3)
fixes#24673
The problem is that there is no way to distinguish `cint`, `cint`, etc
ctypes with Nim types. So `when T is cint | clong | clonglong:` is true
for types derived from `int`, `int32` and `int64`. In this PR, it fixes
the branch to avoid erros for `Natural`
(cherry picked from commit b211ada273)
This pr adds support for running `nimpretty` on stdin as described in
#24622.
I tested `:%!nimpretty -` and `:%!nimpretty --stdin` in neovim and both
seems to work without issues.
(cherry picked from commit 1a7bc6d878)
ref https://en.cppreference.com/w/cpp/error/exception/what
> Pointer to a null-terminated string with explanatory information. The
pointer is guaranteed to be valid at least until the exception object
from which it is obtained is destroyed, or until a non-const member
function on the exception object is called.
The pointer is only valid before `CStdException as e` is destroyed
Old examples are broken on macOS arm64
```
/Users/blue/Desktop/nimony/test4.nim(38) test4
/Users/blue/Desktop/nimony/test4.nim(26) fn
/Users/blue/.choosenim/toolchains/nim-#devel/lib/std/assertions.nim(41) failedAssertImpl
/Users/blue/.choosenim/toolchains/nim-#devel/lib/std/assertions.nim(36) raiseAssert
/Users/blue/.choosenim/toolchains/nim-#devel/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: /Users/blue/Desktop/nimony/test4.nim(26, 3) `$b == "foo2"` [AssertionDefect]
```
(cherry picked from commit e6f6c369ff)
fixes#24644
Another option is to include the symbol names and owners in the type
listing as in #24645 but this is a bit verbose.
(cherry picked from commit 0861dabfa7)
With some inputs larger than `BiggestUInt.high`, `parseBiggestUInt` proc
in `parseutils.nim` fails to detect overflow and returns random value.
This is because `rawParseUInt` try to detects overflow with `if prev >
res:` but it doesn't detects the overflow from multiplication.
It is possible that `x *= 10` causes overflow and resulting value is
larger than original value.
Here is example values larger than `BiggestUInt.high` but
`parseBiggestUInt` returns without detecting overflow:
```
22751622367522324480000000
41404969074137497600000000
20701551093035827200000000000000000
22546225502460313600000000000000000
204963831854661632000000000000000000
```
Following code search for values larger than `BiggestUInt.high` and
`parseBiggestUInt` cannot detect overflow:
```nim
import std/[strutils]
const
# Increase this to extend search range
NBits = 34'u
NBitsMax1 = 1'u shl NBits
NBitsMax = NBitsMax1 - 1'u
# Increase this when there are too many results and want to see only larger result.
MinMultiply10 = 14
var nfound = 0
for i in (NBitsMax div 10'u + 1'u) .. NBitsMax:
var
x = i
n10 = 0
for j in 0 ..< NBits:
let px = x
x = (x * 10'u) and NBitsMax
if x < px:
break
inc n10
if n10 >= MinMultiply10:
echo "i = ", i
echo "uint: ", (i shl (64'u - NBits)), '0'.repeat n10
inc nfound
if nfound > 15:
break
echo "found: ", nfound
```
(cherry picked from commit 95b1dda1db)
Essentially this PR removes the `{.error.}` pragmas littered around in
the OS module and submodules which prevents them from being imported if
the target OS is not supported. This made it impossible to use certain
supported features of the OS module in macros from a supported host OS.
Instead of the `{.error.}` pragmas the `oscommon` module now has a
constant `supportedSystem` which is false in the cases where the
`{.error.}` pragmas where generated. All procedures which can't be run
by macros is also not declared when `supportedSystem` is false.
It would be possible to create dummy versions of the omitted functions
with an `{.error.}` pragma that would trigger upon their use, but this
is currently not done.
This properly fixes#19414
(cherry picked from commit 1f9cac1f5c)
fixes#24631
[Object
constructors](793baf34ff/compiler/semobjconstr.nim (L462)),
[casts](793baf34ff/compiler/semexprs.nim (L494))
and [type
conversions](793baf34ff/compiler/semexprs.nim (L419))
copy their type nodes verbatim instead of producing semchecked type
nodes. This causes a crash in transf when an untyped expression in the
type node has `nil` type. To deal with this, don't try to transform the
type node in these expressions at all. I couldn't reproduce the problem
with type conversion nodes though so those are unchanged in transf.
(cherry picked from commit 6d59680217)
fixes#24626
`createTypeboundOps` in sempass2 is called when generating destructors
for types including for explicit destructor calls, however it blocks
destructors from getting generated in a `nodestroy` proc. This causes
issues when a destructor is explicitly called in a `nodestroy` proc. To
fix this, allow destructors to get generated only for explicit
destructor calls in nodestroy procs.
(cherry picked from commit 793baf34ff)
fixes#24609
A tuple may have an incompatible expected type if there is a converter
match to it. So the compiler should not error when trying to match the
individual elements in the constructor to the elements of the expected
tuple type, this will be checked when the tuple is entirely constructed
anyway.
(cherry picked from commit 8d0e853e0a)
This pull request adds the `cumproded` function along with its in-place
equivalent, `cumprod`, to the math library. These functions provide
functionality similar to `cumsum` and `cumsummed`, allowing users to
calculate the cumulative sum of elements.
The `cumprod` function computes the cumulative product of elements
in-place, while `cumproded` additionally returns the prod seq.
(cherry picked from commit 4aff12408c)
- `/` is now a hotkey to jump to the search
- Search results now are in line with the page (previously on small
screens it would be off centre)
- Jumping to a search result inside the page or via TOC will now hide
the search results (previously the results got in the way)
Example site here: https://tranquil-scone-c159b6.netlify.app/main.html
(cherry picked from commit 86d6f71f5a)
This makes await point to the caller line instead of asyncmacro. It also
reworks the "Async traceback:" section of the traceback. Follow up PR
#21091 (issue #19931) so it works if there is asynchronous work done.
(cherry picked from commit 2f127bf99f)
fixes#23114
As in https://github.com/nim-lang/Nim/pull/22074, expressions in
bracketed emit are strictly typechecked, this PR applies the same check
for symbols in asm statements in order to keep them consistent.
(cherry picked from commit 3c4246dd24)
This fixes one error in https://github.com/nim-lang/Nim/issues/24544 .
I tested this on Raspberry Pi Pico (arm) and Raspberry Pi 3(arm64).
It is not tested on i386, riscv32 and riscv64 CPU.
(cherry picked from commit fc806710cb)
fixes#24559
The strformat macros have the problem that they don't capture symbols,
so don't use them in the generic `fromJson` proc here. Also `fromJson`
refers to `jsonTo` before it is declared which doesn't capture it, so
it's now forward declared.
(cherry picked from commit 5c71fbab30)
Fixes two line infos to make the error's clearer inside editors
- 'field is not accessible' would point to the whole object construction
instead of just the field inside the construction
- 'field initialized twice' would point to the colon instead of the
field
(cherry picked from commit 6bc52737b3)
fixes#24552
Could also implement `{.used.}` for imports but this wouldn't be
backwards compatible. The same problem as #24552 also exists for
`{.hint[XDeclaredButNotUsed].}` but this isn't as much of a problem
since `{.used.}`/`{.push used.}` exist.
(cherry picked from commit 986ca7dcd4)
Was debugging with `--expandMacro` and noticed that private fields
weren't exported.
Passes extra flags to the renderer to make them be shown
(cherry picked from commit f80ce139d5)
follow up #24537
Because `nimble` is a bundled repo so it is bundled in the tarballs
i.e.
82421fd705/.github/workflows/nightlies.yml (L264)
has bundled `dist/nimble`, but it only copies the data without `.git`.
So in this PR, we ignore bundled nimble repo.
(cherry picked from commit 70b3232d3a)
fixes#20908
This PR unifies the treatment of unknown warnings and hints, which now
gives an `warnUnknownNotes` instead of an error.
(cherry picked from commit 81d8c0fc17)
Like quit, this function never returns.
Also, "code" was marked as "int", even though POSIX _exit takes a C int.
(cherry picked from commit f485973459)
fixes#22101
The old implementation generates
`auto T = value;` for the cpp backend which causes problems for goto
exceptions. This PR puts the declaration of `T` to the cpsLocals parts
and makes it compatible with goto exceptions.
(cherry picked from commit f7a461a30c)
fixes#22153
It's a problem for refc because you cannot index a nil string: i.e.
`[""]` is `{((NimStringDesc*) NIM_NIL)}` which cannot be indexed
(cherry picked from commit 9bb7e53e7f)
With this example
```nim
import std/strformat
echo fmt"{invalid, code}"
```
We get the error message
```
stack trace: (most recent call last)
/home/jake/.choosenim/toolchains/nim-hashdevel/lib/pure/strformat.nim(750, 16) fmt
/home/jake/.choosenim/toolchains/nim-hashdevel/lib/pure/strformat.nim(714, 16) strformatImpl
/home/jake/Documents/projects/Nim/temp.nim(3, 9) template/generic instantiation of `fmt` from here
/home/jake/.choosenim/toolchains/nim-hashdevel/lib/pure/strformat.nim(714, 16) Error: could not parse `invalid, code` in `{invalid, code}`.
(1, 8) Error: invalid indentation
```
After PR it now shortens it to just appear in user code
```
/home/jake/Documents/projects/Nim/lib/pure/strformat.nim(750, 16) fmt
/home/jake/Documents/projects/Nim/lib/pure/strformat.nim(714, 16) strformatImpl
/home/jake/Documents/projects/Nim/temp.nim(3, 9) Error: could not parse `invalid, code` in `{invalid, code}`.
(1, 8) Error: invalid indentation
```
(cherry picked from commit da9f7f671b)
Refs #24158
Fixes the line info of the module symbol (cases like `import as` and
grouped imports had wrong line info). Since that symbol's line info is
now used for the warnings, there isn't a separate line info stored for
`unusedImports`
Examples of fixed cases
```nim
import strutils as test #[
^ before
^ after ]#
# This case was fixed by #24158, but only for unused imports
import std/[strutils, strutils] #[
^ before
^ after ]#
from strutils import split #[
^ before
^ after ]#
```
(cherry picked from commit 69e0cdb6c0)
fixes#24526, follows up #23101
The `shallowCopy` calls do not keep the original node's children, they
just make a new seq with the same length, so the `Ident "*"` node from
the original postfix nodes was not carried over, making it `nil` and
causing the segfault.
(cherry picked from commit b529f69518)
refs #24503
Infinite recursions currently are not tracked separately from infinite
loops, because they also increase the loop counter. However the max
infinite loop count is very high by default (10 million) and does not
reliably catch infinite recursions before consuming a lot of memory. So
to protect against infinite recursions, we separately track call depth,
and add a separate option for the maximum call depth, much lower than
the maximum iteration count by default (2000, the same as
`nimCallDepthLimit`).
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 6f4106bf5d)
`curTimeout` is calculated incorrectly. So this PR fixes it.
This PR also replaces `now()` with `getMonoTime()`.
(cherry picked from commit bbf6a62c90)
fixes#24492
Kind of a goofy way of doing this, but we count how many derefs were
used for the first parameter before calling `builtinFieldAccess`, then
count after, and if there are more now than before, we remove the added
derefs. I thought maybe getting rid of #18298 would simplify it but
maybe this would still be the best way.
For better encapsulation we could make `dotTransformation` take an
`nOrig` param instead but this would be less efficient since it would
need a copy, though `semAsgn` already makes one.
(cherry picked from commit 2529f33760)
issue 1 - statics in the type:
This probably only handles simple cases. It's probably too accepting
only comparing the base, but that should only affect candidate selection
I think.
issue 2 - `tyArray` of length 3:
This is just a work around since I couldn't get the fix right in
previous PR
issue 3 - shadowing:
The part in `concepts.nim` that iterates candidates does not consider
imported idents if at least once module level ident matches. It does not
have to match in any other way then name.
EDIT: 2 more
issue 4 - composite typeclasses:
when declared in both the concept and the `proc` can cause problems
issue 5 - recursion:
simple recursion and scenarios where more than one concepts recurse
together (only tested two)
(cherry picked from commit e479151473)
fixes#24472
Excluding variables which are initialized in the nimvm branch so that
they won't interfere the other branch
(cherry picked from commit e7f48cdd5c)
When parsing `a = 1` with `langPython`, Eof is reported unexpectedly.
Fix: allow other languages to fallback to "Identifier" when it is not a
keyword.
This patch is useful as this is a highlighter. `Eof` as annoying.
(cherry picked from commit 6112c51e78)
fixes#24449
The standalone `seq` type is a `tyBuiltInTypeClass` with a single child
of kind `tySequence`, which itself has no children. This is also the
case for most other `tyBuiltInTypeClass` kinds. However this can cause a
crash in sigmatch when calling `isEmptyContainer` on this child type,
which expects the sequence type to have children. This check was added
in #5557 to prevent empty collections like `@[]` from matching their
respective typeclass, but it's not useful when matching against another
typeclass (which is done here to resolve an ambiguity). So to avoid the
crash, this empty container check is disabled when matching against
another typeclass.
(cherry picked from commit 96043bdbb7)
I think this might not be a comprehensive solution to dealing with
`tyGenericBody` but we take a step forward
#24451
(cherry picked from commit 08c2a1741d)
closes#22369, closes#23197, closes#24385, refs #21328
According to #21328 the standard library on Unix should be installed in
`/usr/lib/nim/lib`, however the installer was not updated for this
change, hence the problem as described in
https://github.com/nim-lang/Nim/issues/23197#issuecomment-2031386896.
Have not tested if this fixes the problem but the comment heavily
implies it does. The problem is also in 2.0 so it could be backported
but I can't say for sure that it works and doesn't break anything.
(cherry picked from commit 33e455c986)
fixes#24450
The new concepts were previously not included in
[containsGenericType][1] which prevents them from being instantiated.
Here they are included by being added to `tyTypeClasses` though this
doesn't have to be done, they can also be added manually to
`containsGenericTypeIter`, but this might be too specific.
[1]:
a2031ec6cf/compiler/types.nim (L1507-L1517)
(cherry picked from commit e28d2f42e9)
closes#24372, refs #20091
This was added in #20091 for some reason but doesn't actually work and
only makes error messages more obscure. So for now, it's disabled.
Can also be backported to 2.0 if necessary.
(cherry picked from commit a610f23060)
follows up #24425, fixes#18861, fixes#22445
Since #24425 generic object and distinct types now accurately link back
to their generic instantiations. To work around this issue previously,
type matching checked if generic objects/distinct types were
*structurally* equal, which caused false positives with types that
didn't use generic parameters in their structures. This structural check
is now removed, in cases where generic objects/distinct types require a
nontrivial equality check, the generic parameters of the `typeInst`
fields are checked for equality instead.
The check is copied from `tyGenericInst`, but the check in
`tyGenericInst` is not always sufficient as this type can be skipped or
unreachable in the case of `ref object`s.
(cherry picked from commit a2031ec6cf)
fixes#22479, fixes#24374, depends on #24429 and #24430
When instantiating generic types which directly have nominal types
(object, distinct, ref/ptr object but not enums[^1]) as their values,
the nominal type is now copied (in the case of ref objects, its child as
well) so that it receives a fresh ID and `typeInst` field. Previously
this only happened if it contained any generic types in its structure,
as is the case for all other types.
This solves #22479 and #24374 by virtue of the IDs being unique, which
is what destructors check for. Technically types containing generic
param fields work for the same reason. There is also the benefit that
the `typeInst` field is correct. However issues like #22445 aren't
solved because the compiler still uses structural object equality checks
for inheritance etc. which could be removed in a later PR.
Also fixes a pre-existing issue where destructors bound to object types
with generic fields would not error when attempting to define a user
destructor after the fact, but the error message doesn't show where the
implicit destructor was created now since it was only created for
another instance. To do this, a type flag is used that marks the generic
type symbol when a generic instance has a destructor created. Reusing
`tfCheckedForDestructor` for this doesn't work.
Maybe there is a nicer design that isn't an overreliance on the ID
mechanism, but the shortcomings of `tyGenericInst` are too ingrained in
the compiler to use for this. I thought about maybe adding something
like `tyNominalGenericInst`, but it's really much easier if the nominal
type itself directly contains the information of its generic parameters,
or at least its "symbol", which the design is heading towards.
[^1]: See [this
test](21420d8b09/lib/std/enumutils.nim (L102))
in enumutils. The field symbols `b0`/`b1` always have the uninstantiated
type `B` because enum fields don't expect to be generic, so no generic
instance of `B` matches its own symbols. Wouldn't expect anyone to use
generic enums but maybe someone does.
(cherry picked from commit 05c74d6844)
fixes#17571
Objects in the VM are represented as object constructor nodes that
contain every single field, including ones in different case branches.
This is so that every field has a unique invariant index in the object
constructor that can be written to and read from. However when
converting this node back into semantic code, fields from inactive case
branches can remain in the constructor which causes bad codegen,
generating assignments to fields from other case branches.
To fix this, fields from inactive branches are now detected in
`semmacrosanity.annotateType` (called in `fixupTypeAfterEval`) and
marked to prevent the codegen of their assignments. In #24441 these
fields were excluded from the resulting node, but this causes issues
when the node is directly supposed to go back into the VM, for example
as `const` values. I don't know if this is the only case where this
happens, so I wasn't sure about how to keep that implementation working.
(cherry picked from commit 75b512bc6a)
fixes#16413
`semIterator` checks if the original iterator passed to it has no body,
but it should check the processed node created by `semProcAux`.
(cherry picked from commit e239968b80)
fixes#24402
```nim
iterator myPairsInline*[T](twoDarray: seq[seq[T]]): (int, seq[T]) {.inline.} =
for indexValuePair in twoDarray.pairs:
yield indexValuePair
proc innerTestTotalMem() =
var my2dArray: seq[seq[int32]] = @[]
# fill with some data...
for i in 0'i32..100:
var z = @[i, i+1]
my2dArray.add z
for oneDindex, innerArray in myPairsInline(my2dArray):
discard
innerTestTotalMem()
```
In `for oneDindex, innerArray in myPairsInline(my2dArray)`, `oneDindex`
and `innerArray` becomes `cursors` because they satisfy the criterion of
`isSimpleIteratorVar`. On the one hand, it is not correct to have them
point to the temporary generated by tuple unpacking, which left the
memory of the temporary uncleaned up. On the other hand, we don't need
to generate a temporary for a symbol node when unpacking the tuple.
(cherry picked from commit 21420d8b09)
split from #24425
Matching `tyGenericBody` performs a match on the last child of the
generic body, in this case the uninstantied `tyObject` type. If the
object contains no generic fields, this ends up being the same type as
all instantiated ones, but if it does, a new type is created. This fails
the `sameObjectTypes` check that subtype matching for object types uses.
To fix this, also consider that the pattern type could be the generic
uninstantiated object type of the matched type in subtype matching.
(cherry picked from commit 511ab72342)
split from #24425
The added test did not work previously. The result of `getTypeImpl` is
the uninstantiated AST of the original type symbol, and the macro
attempts to use this type for the result. To fix the issue, the provided
`typedesc` argument is used instead.
(cherry picked from commit 45e21ce8f1)
fixes#17958
In `transf`, conversions in subscript expressions are skipped (with
`skipConv`'s rules). This is because array indexing can produce
conversions to the range type that is the array's index type, which
causes a `RangeDefect` rather than an `IndexDefect` (and also
`--rangeChecks` and `--indexChecks` are both considered). However this
causes problems when explicit conversions are used, between types of
different bitsizes, because those also get skipped.
To fix this, we only skip the conversion if:
* it's a hidden (implicit) conversion
* it's a range check conversion (produces `nkChckRange`)
* the subscript is on an array type and the result type of the
conversion has the same bounds as the array index type
And `skipConv` rules also still apply (int/float classification).
Another idea would be to prevent the implicit conversion to the array
index type from being generated. But there is no good way to do this:
matching to the base type instead prevents types like `uint32` from
implicitly converting (i.e. it can convert to `range[0..3]` but not
`int`), and analyzing whether this is an array bound check is easier in
`transf`, since `sigmatch` just produces a type conversion.
The rules for skipping the conversion could also receive some other
tweaks: We could add a rule that changing bitsizes also doesn't skip the
conversion, but this breaks the `uint32` case. We could simplify it to
only removing implicit skips to specifically fix#17958, but this is
wrong in general.
We could also add something like `nkChckIndex` that generates index
errors instead but this is weird when it doesn't have access to the
collection type and it might be overkill.
(cherry picked from commit 76c5f16ac5)
fixes#14067, fixes#15004, fixes#19019
Anonymous procs are [added to
scope](8091d76306/compiler/semstmts.nim (L2466))
with the name `:anonymous`. This means that if they have the same
signature in a scope, they can consider each other as redefinitions. To
prevent this, mark their symbols as `sfGenSym` so they do not get added
to scope or cause any name conflicts. The commented out `and not isAnon`
check wouldn't work because `isAnon` would not be true if the proc is
being resemmed, in which case the name field in the proc AST would have
the symbol of the anonymous proc rather than being empty.
There is a separate problem of default values in generic/normal procs
not opening new scopes which is partially responsible for #19019.
(cherry picked from commit 3e47725c08)
fixes#24415
Since #23978 (which is in 2.0), all generic types that alias to another
type now insert a `tyAlias` layer in their value. However the
`skipGenericAlias` etc code which `sigmatch` uses is not updated for
this, so `tyAlias` is now skipped in these.
The relevant code in sigmatch is:
67ad1ae159/compiler/sigmatch.nim (L1668-L1673)
This behavior is also suspicious IMO, not skipping a structural
`tyGenericInst` alias can be useful for code like #10220, but this is
currently arbitrarily decided based on "depth" and whether the alias is
to another `tyGenericInst` type or not. Maybe in the future we could
enforce the use of a nominal type.
(cherry picked from commit 45b8434c7d)
fixes issue described in https://forum.nim-lang.org/t/12579
In #24065 explicit generic parameter matching was made to fail matches
on arguments with unresolved types in generic contexts (the sigmatch
diff, following #24010), similar to what is done for regular calls since
#22029. However unlike regular calls, a failed match in a generic
context for a standalone explicit generic instantiation did not convert
the expression into one with `tyFromExpr` type, which means it would
error immediately given any unresolved parameter. This is now done to
fix the issue.
For explicit generic instantiations on single non-overloaded symbols, a
successful match is still instantiated. For multiple overloads (i.e.
symchoice), if any of the overloads fail the match, the entire
expression is considered untyped and any instantiations are not used, so
as to not void overloads that would match later. This means even
symchoices without unresolved arguments aren't instantiated, which may
be too restrictive, but it could also be too lenient and we might need
to make symchoice instantiations always untyped. The behavior for
symchoice is not sound anyway given it causes #9997 so this is something
to consider for a redesign.
Diff follows #24276.
(cherry picked from commit 67ad1ae159)
Flaky not just due to recent ubuntu 24/GCC 14 upgrades, windows fails as
well, assuming the issue is with badssl or it's just not worth testing
here.
(cherry picked from commit 5f056f87b2)
This commit fixes/adds tests for and fixes several issues with `JOIN`
operator parsing:
- For OUTER joins, LEFT | RIGHT | FULL specifier is not optional
```nim
doAssertRaises(SqlParseError): discard parseSql("""
SELECT id FROM a
OUTER JOIN b
ON a.id = b.id
""")
```
- For NATURAL JOIN and CROSS JOIN, ON and USING clauses are forbidden
```nim
doAssertRaises(SqlParseError): discard parseSql("""
SELECT id FROM a
CROSS JOIN b
ON a.id = b.id
""")
```
- JOIN should parse as part of FROM, not after WHERE
```nim
doAssertRaises(SqlParseError): discard parseSql("""
SELECT id FROM a
WHERE a.id IS NOT NULL
INNER JOIN b
ON a.id = b.id
""")
```
- LEFT JOIN should parse
```nim
doAssert $parseSql("""
SELECT id FROM a
LEFT JOIN b
ON a.id = b.id
""") == "select id from a left join b on a.id = b.id;"
```
- NATURAL JOIN should parse
```nim
doAssert $parseSql("""
SELECT id FROM a
NATURAL JOIN b
""") == "select id from a natural join b;"
```
- USING should parse
```nim
doAssert $parseSql("""
SELECT id FROM a
JOIN b
USING (id)
""") == "select id from a join b using (id );"
```
- Multiple JOINs should parse
```nim
doAssert $parseSql("""
SELECT id FROM a
JOIN b
ON a.id = b.id
LEFT JOIN c
USING (id)
""") == "select id from a join b on a.id = b.id left join c using (id );"
```
(cherry picked from commit 46bb47a444)
fixes#24378
```nim
type Win = typeof(`body`)
doAssert not supportsCopyMem((int, Win))
```
`semAfterMacroCall` doesn't skip the children aliases types in the tuple
typedesc construction while the normal program seem to skip the aliases
types somewhere
`(int, Win)` is kept as `(int, alias string)` instead of expected `(int,
string)`
(cherry picked from commit 5e56f0a356)
refs #23625, refs #24289
Encountered in #24360 but could not reproduce minimally: overloading on
static parameters can work with the normal compile commands but crash
`nim check`. Static overloading relies on `tryConstExpr` which recovers
from things like `globalError` and fails softly, in this case this can
happen when a variable etc. is not available to evaluate in the VM. But
with `nim check`, the compiler does not throw an exception in this case,
and instead tries to keep generating the entire expression in the VM,
which can cause crashes.
To fix this, when the compiler has no error outputs even on `nim check`,
we raise a global error so that the VM code generation stops early. This
fixes both `tryConstExpr` and speeds up `nim check`, because no error
outputs means we don't need cascading errors.
(cherry picked from commit efd603eb28)
Links for succ/pred/inc/dec were incorrect since they link to a symbol
with `int` as their second type.
Uses local referencing instead so that it links to the correct symbol.
Doesn't change the other links since they worked and doing the same
local referencing for `high`/`low` would've make them link to the group
of procs instead of the specific ones for ordinals
(cherry picked from commit 79ce3fe6b7)
pre-existing issues:
```nim
block:
type
FooObj = object
data: int
Foo = ref ref FooObj
proc delete(self: Foo) =
echo self.data
var s: Foo
new(s, delete)
```
it crashed with arc/orc in 1.6.x and 2.x.x
```nim
block:
type
Foo = ref int
proc delete(self: Foo) =
echo self[]
var s: Foo
new(s, delete)
```
The simple fix is to add a type restriction for the type `T` for arc/orc
versions
```nim
proc new*[T: object](a: var ref T, finalizer: proc (x: T) {.nimcall.})
```
(cherry picked from commit 2af602a5c8)
fixes#13417, fixes#19703
When passing an expression to an `openarray` iterator parameter: If the
expression is a statement list (considered "complex"), it's assigned in
a non-deep-copying way to a temporary variable first, then this variable
is used as a parameter. If it's not a statement list, i.e. a call or a
symbol, the parameter is substituted directly with the given expression.
In the case of calls, this results in the call potentially being
executed more than once, or can cause redefined variables in the
codegen.
To fix this, calls are also considered as "complex" assignments to
openarrays, as long as the return type of the call is not `openarray` as
the generated assignment in that case has issues/is unimplemented
(caused a segfault [here in
datamancer](47ba4d81bf/src/datamancer/dataframe.nim (L1580))).
As for why creating a temporary isn't the default only with exceptions
for things like `nkSym`, the "non-deep-copying" way of assignment
apparently still causes arrays to be copied according to a comment in
the code. I'm not sure to what extent this is true: if it still happens
on ARC/ORC, if it happens for every array length, or if we can fix it by
passing arrays by reference. Otherwise, a more general way to assign to
openarrays might be needed, but I'm not sure if the compiler can easily
do this.
(cherry picked from commit d303c289fa)
fixes#23952
It reorders `type Foo = enum A, B = -1` to `type Foo = enum B = -1, A`
so that `firstOrd` etc. continue to work.
(cherry picked from commit 294b1566e7)
closes https://github.com/nim-lang/RFCs/issues/380, fixes#4773, fixes
#14729, fixes#16755, fixes#18150, fixes#22984, refs #11167 (only some
comments fixed), refs #12620 (needs tiny workaround)
The compiler gains a concept of root "nominal" types (i.e. objects,
enums, distincts, direct `Foo = ref object`s, generic versions of all of
these). Exported top-level routines in the same module as the nominal
types that their parameter types derive from (i.e. with
`var`/`sink`/`typedesc`/generic constraints) are considered attached to
the respective type, as the RFC states. This happens for every argument
regardless of placement.
When a call is overloaded and overload matching starts, for all
arguments in the call that already have a type, we add any operation
with the same name in the scope of the root nominal type of each
argument (if it exists) to the overload match. This also happens as
arguments gradually get typed after every overload match. This restricts
the considered overloads to ones attached to the given arguments, as
well as preventing `untyped` arguments from being forcefully typed due
to unrelated overloads. There are some caveats:
* If no overloads with a name are in scope, type bound ops are not
triggered, i.e. if `foo` is not declared, `foo(x)` will not consider a
type bound op for `x`.
* If overloads in scope do not have enough parameters up to the argument
which needs its type bound op considered, then type bound ops are also
not added. For example, if only `foo()` is in scope, `foo(x)` will not
consider a type bound op for `x`.
In the cases of "generic interfaces" like `hash`, `$`, `items` etc. this
is not really a problem since any code using it will have at least one
typed overload imported. For arbitrary versions of these though, as in
the test case for #12620, a workaround is to declare a temporary
"template" overload that never matches:
```nim
# neither have to be exported, just needed for any use of `foo`:
type Placeholder = object
proc foo(_: Placeholder) = discard
```
I don't know what a "proper" version of this could be, maybe something
to do with the new concepts.
Possible directions:
A limitation with the proposal is that parameters like `a: ref Foo` are
not attached to any type, even if `Foo` is nominal. Fixing this for just
`ptr`/`ref` would be a special case, parameters like `seq[Foo]` would
still not be attached to `Foo`. We could also skip any *structural* type
but this could produce more than one nominal type, i.e. `(Foo, Bar)`
(not that this is hard to implement, it just might be unexpected).
Converters do not use type bound ops, they still need to be in scope to
implicitly convert. But maybe they could also participate in the nominal
type consideration: if `Generic[T] = distinct T` has a converter to `T`,
both `Generic` and `T` can be considered as nominal roots.
The other restriction in the proposal, being in the same scope as the
nominal type, could maybe be worked around by explicitly attaching to
the type, i.e.: `proc foo(x: T) {.attach: T.}`, similar to class
extensions in newer OOP languages. The given type `T` needs to be
obtainable from the type of the given argument `x` however, i.e.
something like `proc foo(x: ref T) {.attach: T.}` doesn't work to fix
the `ref` issue since the compiler never obtains `T` from a given `ref
T` argument. Edit: Since the module is queried now, this is likely not
possible.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 2864830941)
fixes#24236
Locally tested to generate a 100 KB file for TCC. Empty flexible array
size is standard in C99 but maybe some compilers still don't support it.
At the very least an array size of 1000000 should be rare.
(cherry picked from commit dd3a4b2aba)
fixes#24338
When unrolling each iteration of a `fields` iterator, the compiler only
opens a new scope for semchecking, but doesn't generate a node that
signals to the codegen that a new scope should be created. This causes
issues for reused template instantiations that reuse variable symbols
between each iteration, which causes the codegen to generate multiple
declarations for them in the same scope (regardless of `inject` or
`gensym`). To fix this, we wrap the unrolled iterations in an `if true:
body` node, which both opens a new scope and doesn't interfere with
`break`.
(cherry picked from commit ca5df9ab25)
This fixes several cases of the Nim binding of nfds_t being inconsistent
with the target platform signedness and/or size.
Additionally, it fixes poll's third argument (timeout) being set to Nim
"int" when it should have been "cint".
The former is the same issue that #23045 had attempted to fix, but
failed because it only considered Linux. (Also, it was only applied to
version 2.0, so the two branches now have incompatible versions of the
same bug.)
Notes:
* SVR4's original "unsigned long" definition is cloned by Linux and
Haiku. Nim got this right for Haiku and Linux-amd64, but it was wrong on
non-amd64 Linux.
* Zephyr does not have nfds_t, but simply uses (signed) "int". This was
already correctly reflected by Nim.
* OpenBSD poll.h uses "unsigned int", and other BSD derivatives follow
suit. This being the most commonly copied definition, the fallback case
now returns cuint. (This also seems to be correct for the OS X headers I
could find on the web.)
* This changes Nintendo Switch nfds_t to cuint from culong. It is
purportedly a FreeBSD derivative, so I *think* this is correct, but I
can't tell because I don't have access to the Nintendo Switch headers.
I have also moved the platform-specific Tnfds to posix.nim so that we
can reuse the fallback logic on all platforms. (e.g. specifying the size
in posix_linux_amd64 only to then use when defined(linux) in posix_other
seems redundant.)
(cherry picked from commit 67442471ae)
refs #6978, refs #6752, refs #21613, refs #24234
The `jsNoInt64`, `whenHasBigInt64`, `whenJsNoBigInt64` templates are
replaced with bool constants to use with `when`. Weird that I didn't do
this in the first place.
The `whenJsNoBigInt64` template was also slightly misleading. The first
branch was compiled for both no bigint64 on JS as well as on C/C++. It
seems only `trandom` depended on this by mistake.
The workaround for #6752 added in #6978 to `times` is also removed with
`--jsbigint64:on`, but #24233 was also encountered with this, so this PR
depends on #24234.
(cherry picked from commit 041098e882)
Running `ctags` on files with quoted symbols (e.g. `$`) would list \`
instead of the full ident. Issue was the result getting reassigned at
the end to a \` instead of appending
(cherry picked from commit 93c24fe1c5)
closes https://github.com/nim-lang/RFCs/issues/554
Adds a symmetric difference operation to the language bitset type. This
maps to a simple `xor` operation on the backend and thus is likely
faster than the current alternatives, namely `(a - b) + (b - a)` or `a +
b - a * b`. The compiler VM implementation of bitsets already
implemented this via `symdiffSets` but it was never used.
The standalone binary operation is added to `setutils`, named
`symmetricDifference` in line with [hash
sets](https://nim-lang.org/docs/sets.html#symmetricDifference%2CHashSet%5BA%5D%2CHashSet%5BA%5D).
An operator version `-+-` and an in-place version like `toggle` as
described in the RFC are also added, implemented as trivial sugar.
(cherry picked from commit ae9287c4f3)
refs #8064, refs #24010
Error messages for standalone explicit generic instantiations are
revamped. Failing standalone explicit generic instantiations now only
error after overloading has finished and resolved to the default `[]`
magic (this means `[]` can now be overloaded for procs but this isn't
necessarily intentional, in #24010 it was documented that it isn't
possible). The error messages for failed instantiations are also no
longer a simple `cannot instantiate: foo` message, instead they now give
the same type mismatch error message as overloads with mismatching
explicit generic parameters.
This is now possible due to the changes in #24010 that delegate all
explicit generic proc instantiations to overload resolution. Old code
that worked around this is now removed. `maybeInstantiateGeneric` could
maybe also be removed in favor of just `explicitGenericSym`, the `result
== n` case is due to `explicitGenericInstError` which is only for niche
cases.
Also, to cause "ambiguous identifier" error messages when the explicit
instantiation is a symchoice and the expression context doesn't allow
symchoices, we semcheck the sym/symchoice created by
`explicitGenericSym` with the given expression flags.
#8064 isn't entirely fixed because the error message is still misleading
for the original case which does `values[1]`, as a consequence of
#12664.
(cherry picked from commit 0a058a6b8f)
The first commit reverts the revert of #23787.
The second fixes lambdalifting in convolutedly nested
closures/closureiters. This is considered to be the reason of #24094,
though I can't tell for sure, as I was not able to reproduce #24094 for
complicated but irrelevant reasons. Therefore I ask @jmgomez, @metagn or
anyone who could reproduce it to try it again with this PR.
I would suggest this PR to not be squashed if possible, as the history
is already messy enough.
Some theory behind the lambdalifting fix:
- A closureiter that captures anything outside its body will always have
`:up` in its env. This property is now used as a trigger to lift any
proc that captures such a closureiter.
- Instantiating a closureiter involves filling out its `:up`, which was
previously done incorrectly. The fixed algorithm is to use "current" env
if it is the owner of the iter declaration, or traverse through `:up`s
of env param until the common ancestor is found.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 5fa96ef270)
It seems exportcpp was implemented in v1.0 but there is no documentation
about it excepts changelog.
`noinline` is used in many procedures in Nim code but there is also no
documentation about it.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit b8f6088ac0)
fixes#24305, refs #23807
Since #23014 `nkHiddenAddr` is produced to fast assign array elements in
iterators. However the array access inside this `nkHiddenAddr` can get
folded at compile time, generating invalid code. In #23807, compile time
folding of regular `addr` expressions was changed to be prevented in
`transf` but `nkHiddenAddr` was not updated alongside it.
The method for preventing folding in `addr` in #23807 was also faulty,
it should only trigger on the immediate child node of the address rather
than all nodes nested inside it. This caused a regression as outlined in
[this
comment](https://github.com/nim-lang/Nim/pull/24322#issuecomment-2419560182).
To fix both issues, `addr` and `nkHiddenAddr` now both shallowly prevent
constant folding for their immediate children.
(cherry picked from commit 52cf7dfde0)
fixes#24319
`byRefLoc` (`mapType`) requires the Loc `a` to have the right type.
Without `lfEnforceDeref`, it produces the wrong type for `deref (var
array)`, which may come from `mitems`.
(cherry picked from commit 0347536ff2)
fixes#18896fixes#20886
```nim
type
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
# import C's FILE* type; Nim will treat it as a new pointer type
```
This is an excerpt from the Nim manual. In the old Nim versions, it
produces a void pointer type instead of the `FILE*` type that should
have been generated. Because these C types tend to be opaque and adapt
to changes on different platforms. It might affect the portability of
Nim on various OS, i.e. `csource_v2` cannot build on the apline platform
because of `Time` relies on Nim types instead of the `time_t` type.
ref https://github.com/nim-lang/Nim/pull/18851
(cherry picked from commit 8be82c36c9)
fixes#24258
It uses conditionals to guard against ill formed AST to produce better
error messages, rather than crashing
(cherry picked from commit 8b39b2df7d)
fixes#24296fixes#24295
Templates use `expectedType` for type inference. It's justified that
when templates don't have an actual return type, i.e., `untyped` etc.
When the return type of templates is specified, we should not infer the
type
```nim
template g(): string = ""
let c: cstring = g()
```
In this example, it is not reasonable to annotate the templates
expression with the `cstring` type before the `fitNode` check with its
specified return type.
(cherry picked from commit 80e6b35721)
I couldn't understand why there is "x" declaration. Comparison make it
easier to understand to people not familiar to enums.
(cherry picked from commit 1dbf614858)
follows up #24279
`discard finishTest` was wrong if the test still had a `retries` option:
it would just ignore the result of the test. This is an unlikely mistake
but we safeguard against it by splitting `finishTest` into two, one that
completely ignores the retries option and `finishTestRetryable` which
has to be checked for a retry. This also makes the code look slightly
better.
(cherry picked from commit 2f7586c066)
Testament now retries a test by a specified amount if it fails in any
way other than an invalid spec. This is to deal with the flaky GC tests
on Windows CI that fail in many different ways, from the linker randomly
erroring, segfaults, etc.
Unfortunately I couldn't do this cleanly in testament's current code.
The proc `addResult`, which is the "final" proc called in a test run's
lifetime, is now wrapped in a proc `finishTest` that returns a bool
`true` if the test failed and has to be retried. This result is
propagated up from `cmpMsgs` and `compilerOutputTests` until it reaches
`testSpecHelper`, which handles these results by recursing if the test
has to be retried. Since calling `testSpecHelper` means "run this test
with one given configuration", this means every single matrix
option/target etc. receive an equal amount of retries each.
The result of `finishTest` is ignored in cases where it's known that it
won't be retried due to passing, being skipped, having an invalid spec
etc. It's also ignored in `testNimblePackages` because it's not
necessary for those specific tests yet and similar retry behavior is
already implemented for part of it.
This was a last resort for the flaky GC tests but they've been a problem
for years at this point, they give us more work to do and turn off
contributors. Ideally GC tests failing should mark as "needs review" in
the CI rather than "failed" but I don't know if Github supports
something like this.
(cherry picked from commit 720d0aee5c)
fixes#24288, refs #23625
Since #23625 "cannot evaluate" errors during VM code generation are
"soft" errors with `nim check`, i.e. the code generation isn't halted
(except for the current proc which `return`s which can cause wrong
codegen) and the expression is still attempted to be evaluated. Now,
these errors signal to the VM that the current generated VM code cannot
be evaluated, and so instead of evaluating, an error node is returned.
This keeps the benefit of the "soft" errors without potentially crashing
the compiler on improperly generated VM code. Although maybe the
compiler might not be able to handle the generated error node in some
cases.
This fixes the chame example in #24288 but this is not tested in CI.
Presumably it or the compiler was doing something like `compiles()` on
code that can't run in the VM.
I would accept nicer ways of tracking non-evaluability than
`c.cannotEval = true` but I tried to keep it as harmless as possible.
(cherry picked from commit def1fea43a)
fixes#24021
The field checking for case object branches at some point generates a
negated set `contains` check for the object discriminator. For enum
types, this tries to generate a complement set and convert to a
`contains` check in that instead. It obtains this type from the type of
the element node in the `contains` check.
`buildProperFieldCheck` creates the element node by changing a field
access expression like `foo.z` into `foo.kind`. In order to do this, it
copies the node `foo.z` and sets the field name in the node to the
symbol `kind`. But when copying the node, the type of the original
`foo.z` is retained. This means that the complement is performed on the
type of the accessed field rather than the type of the discriminator,
which causes problems when the accessed field is also an enum.
To fix this, we properly set the type of the copied node to the type of
the kind field. An alternative is just to make a new node instead.
A lot of text for a single line change, I know, but this part of the
codebase could use more explanation.
(cherry picked from commit 1bebc236bd)
fixes#24087, refs https://forum.nim-lang.org/t/341, refs #14222, refs
#14221
The Nim compiler calls `cl` for linking as well as compilation. This
means that options to the linker have to be passed after a `/link`
argument. But the Nim compiler doesn't include this option normally,
because users may still want to pass non-linker options to `cl` at link
time.
To deal with this, a workaround is used: every single library link
option adds `/link` before it. The linker simply ignores extraneous
`/link` arguments and gives a warning instead, since it's an
unrecognized option to the linker. This is really hacky but otherwise we
need to separate linker arguments into arguments passed either to the
compiler or to the linker at link time, and this behavior wouldn't be
meaningful outside of MSVC.
I can't really test this manually but I did test that the linker ignores
`/link`. I also can't really do more than this, I don't really use MSVC
so I wouldn't know how to navigate it, or how people use it. Ideally
someone who knows more about/uses MSVC can give their input or take
over.
(cherry picked from commit 449106a5a4)
fixes#24269, refs #20095
Instead of checking the package of the *used sym* to determine whether a
stylecheck should trigger, we check the package of the lineinfo instead.
Before #20095 this checked for the current compilation context module
instead which caused issues with generic procs, but the lineinfo should
more closely match the AST.
I figured this might cause issues with includes etc but the foreign
package test specifically tests for an include and passes, so maybe the
package determining logic accounts for this already. This still might
not be the correct logic, I'm not too familiar with the package handling
in the compiler.
Package PRs, both merged:
- json_rpc: https://github.com/status-im/nim-json-rpc/pull/226
- json_serialization:
https://github.com/status-im/nim-json-serialization/pull/99
(cherry picked from commit aaf6c408c6)
As said in the warning after #21659, a set of ints defaults to
`set[range[0..65535]]` which is very large. So in osproc, a `case`
statement is used instead of an int set to check for an int being one of
2 values.
Also tested all of CI with the warning from #21659 as an error, this
seems to be the only remaining case in CI.
(cherry picked from commit 706985997e)
fixes#24274
The code in the `if` branch replaces the current destination `d` with a
new one. But the location `d` can be an assignment location, in which
case the provided expression isn't generated. To fix this, don't trigger
this code for when the location already exists. An alternative would be
to call `putIntoDest` in this case as is done below.
(cherry picked from commit 9c85f4fd07)
This adds several new Status packages to the CIs:
- confutils
- eth
- metrics
- nat_traversal
- toml_serialization
Other packages mentioned in https://github.com/nim-lang/Nim/issues/24266
are currently not ready to test with `devel` for various reasons.
----
This also enables `criterion`, and removes other packages that had been
in the `allowFailure` category — even without them we have plenty of
packages (145) that we test, there's no point in spending CI time on
them just to see them fail every time.
If/when the authors of those packages make them work with Nim devel, we
can re-introduce them then.
(cherry picked from commit 274762638f)
I have added a new overload of `^` for float exponents.
Is two overloads for `float32` and `float64` better than just one
overload with `SomeFloat` type ?
I guess this would not work with `SomeFloat`, as `pow` is not defined
for `float`.
Another remark. Maybe we should catch exponents with 0.5 and call `sqrt`
instead ?
---------
Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
Co-authored-by: metagn <metagngn@gmail.com>
(cherry picked from commit e9a4d096ab)
fixes#24091, refs #24092
Any instantiations resolving to a generic body type now gives an error.
Due to #24092, this does not error in cases like matching against `type
M` in generics because generic body type symbols are just not
instantiated. But this prevents parameters with type `type M` from being
used, although there doesn't seem to be any code which does this. Just
in case such code exists, we still allow `typedesc` types resolving to
generic body types.
(cherry picked from commit 2f904535d0)
fixes#23587
As explained in the issue, `getOrDefault` has a parameter named
`default` that can be a proc after generic instantiation. But the
parameter having a proc type [overrides all other
overloads](f73e03b132/compiler/semexprs.nim (L1203))
including the magic `system.default` overload and causes a compile error
if the proc doesn't match the normal use of `default`. To fix this, the
`result = default(B)` initializer call is removed because it's not
needed, `result` is always set in `getOrDefaultImpl` when a default
value is provided.
This is still a suspicious behavior of the compiler but `tables` working
has a higher priority.
(cherry picked from commit 67ea754b7f)
fixes#18649, refs #24183
Same as in #24183 for templates, we now process pragma nodes in generics
so that macro symbols are captured and the pragma arguments are checked,
but ignoring language pragma keywords.
A difference is that we cannot process call nodes as is, we have to
process their children individually so that the early untyped
macro/template instantiation in generics does not kick in.
(cherry picked from commit d72b848d17)
fixes#24233
Integer literals with type `int` can match `int64` with a generic match.
Normally this would generate an conversion via `isFromIntLit`, but when
it matches with a generic match (`isGeneric`) the node is left alone and
continues to have type `int` (related to #4858, but separate; since
`isFromIntLit > isGeneric` it doesn't propagate). This did not cause
problems on the C backend up to this point because either the compiler
generated a cast when generating the C code or it was implicitly casted
in the C code itself. On the JS backend however, we need to generate
`int64` and `int` values differently, so we copy the integer literal and
give it the matched type now instead.
This is somewhat risky even if CI passes but it's required to make the
times module work without [this
workaround](7dfadb8b4e/lib/pure/times.nim (L219-L238))
on `--jsbigint64:on` (the default).
CI exposed an issue: When matching an int literal to a generic parameter
in a generic instantiation, the literal is only treated like a value if
it has `int literal` type, but if it has the type `int`, it gets
transformed into literally the type `int` (#12664, #13906), which breaks
the tests t14193 and t12938. To deal with this, we don't give it the
type `int` if we are in a generic instantiation and preserve the `int
literal` type.
(cherry picked from commit c73eedfe6e)
fixes#24186
When encountering pragma nodes in templates, if it's a language pragma,
we don't process the name, and only any values if they exist. If it's
not a language pragma, we process the full node. Previously only the
values of colon expressions were processed.
To make this simpler, `whichPragma` is patched to consider bracketed
hint/warning etc pragmas like `{.hint[HintName]: off.}` as being a
pragma of kind `wHint` rather than an invalid pragma which would have to
be checked separately. From looking at the uses of `whichPragma` this
doesn't seem like it would cause problems.
Generics have [the same
problem](a27542195c/compiler/semgnrc.nim (L619))
(causing #18649), but to make it work we need to make sure the
templates/macros don't get evaluated or get evaluated correctly (i.e.
passing the proc node as the final argument), either with #23094 or by
completely disabling template/macro evaluation when processing the
pragma node, which would also cover `{.pragma.}` templates.
(cherry picked from commit 911cef1621)
fixes#24228, refs #22022
As described in
https://github.com/nim-lang/Nim/issues/24228#issuecomment-2392462221,
instantiating generic routines inside `typeof` causes all code inside to
be treated as being in a typeof context, and thus preventing compile
time proc folding, causing issues when code is generated for the
instantiated routine. Now, instantiated generic procs are treated as
never being inside a `typeof` context.
This is probably an arbitrary special case and more issues with the
`typeof` behavior from #22022 are likely. Ideally this behavior would be
removed but it's necessary to accomodate the current [proc `declval` in
the package `stew`](https://github.com/status-im/nim-stew/pull/190), at
least without changes to `compileTime` that would either break other
code (making it not eagerly fold by default) or still require a change
in stew (adding an option to disable the eager folding).
Alternatively we could also make the eager folding opt-in only for
generic compileTime procs so that #22022 breaks nothing whatsoever, but
a universal solution would be better. Edit: Done in #24230 via
experimental switch
(cherry picked from commit ea9811a4d2)
split from #24198
This is a required refactor for the only good solution I've been able to
think of for #4858 etc. Explanation:
---
`sigmatch` currently [disables
bindings](d6a71a1067/compiler/sigmatch.nim (L1956))
(except for binding to other generic parameters) when matching against
constraints of generic parameters. This is so when the constraint is a
general metatype like `seq`, the type matching will not treat all
following uses of `seq` as the type matched against that generic
parameter.
However to solve #4858 etc we need to bind `or` types with a conversion
match to the type they are supposed to be converted to (i.e. matching
`int literal(123)` against `int8 | int16` should bind `int8`[^1], not
`int`). The generic parameter constraint binding needs some way to keep
track of this so that matching `int literal(123)` against `T: int8 |
int16` also binds `T` to `int8`[^1].
The only good way to do this IMO is to generate a new "binding context"
when matching against constraints, then binding the generic param to
what the constraint was bound to in that context (in #24198 this is
restricted to just `or` types & concrete types with convertible matches,
it doesn't work in general).
---
`semtypinst` already does something similar for bindings of generic
invocations using `LayeredIdTable`, so `LayeredIdTable` is now split
into its own module and used in `sigmatch` for type bindings as well,
rather than a single-layer `TypeMapping`. Other modules which act on
`sigmatch`'s binding map are also updated to use this type instead.
The type is also made into an `object` type rather than a `ref object`
to reduce the pointer indirection when embedding it inside
`TCandidate`/`TReplTypeVars`, but only on arc/orc since there are some
weird aliasing bugs on refc/markAndSweep that cause a segfault when
setting a layer to its previous layer. If we want we can also just
remove the conditional compilation altogether and always use `ref
object` at the cost of some performance.
[^1]: `int8` binding here and not `int16` might seem weird, since they
match equally well. But we need to resolve the ambiguity here, in #24012
I tested disallowing ambiguities like this and it broke many packages
that tries to match int literals to things like `int16 | uint16` or
`int8 | int16`. Instead of making these packages stop working I think
it's better we resolve the ambiguity with a rule like "the earliest `or`
branch with the best match, matches". This is the rule used in #24198.
(cherry picked from commit cad8726907)
Followup to #24154, packages aren't ready for macos 14 (M1/ARM CPU) yet
and it seems to be preview on azure, so upgrade to macos 13 for now.
Macos 12 gives a warning:
```
You are using macOS 12.
We (and Apple) do not provide support for this old version.
It is expected behaviour that some formulae will fail to build in this old version.
It is expected behaviour that Homebrew will be buggy and slow.
Do not create any issues about this on Homebrew's GitHub repositories.
Do not create any issues even if you think this message is unrelated.
Any opened issues will be immediately closed without response.
Do not ask for help from Homebrew or its maintainers on social media.
You may ask for help in Homebrew's discussions but are unlikely to receive a response.
Try to figure out the problem yourself and submit a fix as a pull request.
We will review it but may or may not accept it.
```
(cherry picked from commit 4a63186cda)
Hello, I am the original developer credited in this file.
I no longer wish to be credited for the it so I've updated it to say
"Nim Contributors".
This is a quick edit from the GitHub Web UI so let me know if I need to
make any changes to get this merged.
Thank you.
---------
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit f420a5a273)
fixes#18396, fixes#20142
Set types with base types matching less than a generic match (so
subrange matches, conversion matches, int conversion matches) are now
considered mismatching, as their representation is different on the
backends (except VM and JS), causing codegen issues. An exception is
granted for set literal types, which now implicitly convert each element
to the matched base type, so things like `s == {'a', 'b'}` are still
possible where `s` is `set[range['a'..'z']]`. Also every conversion
match in this case is unified under the normal "conversion" match, so a
literal doesn't match one set type better than the other, unless it's
equal.
However `{'a', 'b'} == s` or `{'a', 'b'} - s` etc is now not possible.
when it used to work in the VM. So this is somewhat breaking, and needs
a changelog entry.
(cherry picked from commit 7dfadb8b4e)
Previously, the compiler never differentiated between `untyped`/`typed`
argument default values and other types, it considered any parameter
with a type as typed and called `semExprWithType`, which both
typechecked it and disallowed `void` expressions. Now, we perform no
typechecking at all on `untyped` template param default values, and call
`semExpr` instead for `typed` params, which allows expressions with
`void` type.
(cherry picked from commit 4eed341ba5)
fixes#23010, split from #24195
When resemming bracket nodes, the compiler currently unconditionally
makes a new node with an array type based on the node. However the VM
can generate bracket nodes with `seq` types, which this erases. To fix
this, if a bracket node already has a type, we still resem the bracket
node, but don't construct a new type for it, instead using the type of
the original node.
A version of this was rejected that didn't resem the node at all if it
was typed, but I can't find it. The difference with this one is that the
individual elements are still resemmed.
This should fix the break caused by #24184 so we could redo it after
this PR but it might still have issues, not to mention the related
pre-existing issues like #22793, #12559 etc.
(cherry picked from commit d98ef312f0)
yet performed for ordinary slices outside of a `parallel` section.
Strict definitions and `out` parameters
=======================================
With `experimental: "strictDefs"` *every* local variable must be initialized explicitly before it can be used:
```nim
{.experimental: "strictDefs".}
proc test =
var s: seq[string]
s.add "abc" # invalid!
```
Needs to be written as:
```nim
{.experimental: "strictDefs".}
proc test =
var s: seq[string] = @[]
s.add "abc" # valid!
```
A control flow analysis is performed in order to prove that a variable has been written to
before it is used. Thus the following is valid:
```nim
{.experimental: "strictDefs".}
proc test(cond: bool) =
var s: seq[string]
if cond:
s = @["y"]
else:
s = @[]
s.add "abc" # valid!
```
In this example every path does set `s` to a value before it is used.
```nim
{.experimental: "strictDefs".}
proc test(cond: bool) =
let s: seq[string]
if cond:
s = @["y"]
else:
s = @[]
```
With `experimental: "strictDefs"`, `let` statements are allowed to not have an initial value, but every path should set `s` to a value before it is used.
`out` parameters
----------------
An `out` parameter is like a `var` parameter but it must be written to before it can be used:
```nim
proc myopen(f: out File; name: string): bool =
f = default(File)
result = open(f, name)
```
While it is usually the better style to use the return type in order to return results API and ABI
considerations might make this infeasible. Like for `var T` Nim maps `out T` to a hidden pointer.
For example POSIX's `stat` routine can be wrapped as:
```nim
proc stat*(a1: cstring, a2: out Stat): cint {.importc, header: "<sys/stat.h>".}
```
When the implementation of a routine with output parameters is analysed, the compiler
checks that every path before the (implicit or explicit) return does set every output
parameter:
```nim
proc p(x: out int; y: out string; cond: bool) =
x = 4
if cond:
y = "abc"
# error: not every path initializes 'y'
```
Out parameters and exception handling
-------------------------------------
The analysis should take exceptions into account (but currently does not):
```nim
proc p(x: out int; y: out string; cond: bool) =
x = canRaise(45)
y = "abc" # <-- error: not every path initializes 'y'
```
Once the implementation takes exceptions into account it is easy enough to
use `outParam = default(typeof(outParam))` in the beginning of the proc body.
Out parameters and inheritance
------------------------------
It is not valid to pass an lvalue of a supertype to an `out T` parameter:
```nim
type
Superclass = object of RootObj
a: int
Subclass = object of Superclass
s: string
proc init(x: out Superclass) =
x = Superclass(a: 8)
var v: Subclass
init v
use v.s # the 's' field was never initialized!
```
However, in the future this could be allowed and provide a better way to write object
constructors that take inheritance into account.
**Note**: The implementation of "strict definitions" and "out parameters" is experimental but the concept
is solid and it is expected that eventually this mode becomes the default in later versions.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.