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>
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.
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)
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.
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.
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.
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)
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.
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.
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.
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.
fixes#24434
In https://github.com/nim-lang/Nim/pull/24432
```nim
let ex = "NIM_EXTERNC N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N" %
[(i.ord - '0'.ord).rope, extract(el)]
```
```nim
procs.addDeclWithVisibility(ExternC):
procs.addProcHeader(ccNimCall, "nimLoadProcs" & $(i.ord - '0'.ord), "void", cProcParams())
```
extern "C" makes a function-name in C++ have C linkage; it should be
effaced with C compiler
Follows up #24423, needed more refactoring than I expected, sorry for
ugly diff.
With this pretty much all of the raw C code generating parts of the
codegen are abstracted into the cbuilder API (to my knowledge at least).
The current design of NIFC does not implement everything the codegen
generates, such things have mostly not been adapted, they are the
following along with how I'm guessing they could be implemented:
* C++ specific codegen: Maybe a dialect of NIFC for generating C++?
* `codegenDecl` pragma: Could be passed as a pragma to NIFC
* C macros, currently only used for line info IIRC i.e. `nimln_(123)`:
Just inline them when generating NIFC
* Other C defines & `#line`: Maybe as NIFC directives or line infos?
* There is also [this
`#ifndef`](21420d8b09/compiler/cgen.nim (L2249))
when generating headers but NIFC shouldn't need it
* `alignof`/`offsetof`: Is in `cbuilder` but not implemented in NIFC,
should be easy
For now we can disable C++ and the `codegenDecl` pragma when generating
NIFC but since cbuilder is mostly designed to generate NIFC as a flag
when booting the compiler, this hinders the ability to run the CI
against NIFC. Maybe we could also make cbuilder able to generate both C
and NIFC at runtime, this would be a large refactor but wouldn't be too
difficult.
Other missing abstractions before being able to generate NIFC are:
* Primitive types and symbols i.e. `int`, `void*`, `NI`, `NIM_NULL` are
currently still constant string literals, `NU8`, `NU16` etc are also
sometimes generated like `"NU" & $bits`.
* NIFC identifiers, i.e. adding `.c` to imported symbols and properly
mangling generated ones. Not sure how difficult this is going to be.