`cbuilder` is now split into `cbuilderbase`, `cbuilderexprs`,
`cbuilderdecls`, with all the struct builder code up to this point going
in `cbuilderdecls`.
Variable builders are added, with local, global and constant variables
implemented, but not threadvars.
A builder for struct (braced) initializers is added. The field names
have to be passed to build each field (so they can be used in `oconstr`
in nifc), but they're not used in the output code if a flag
`orderCompliant` is enabled, which means the initializer list is
generated in order of the built fields. The version which uses the names
on C is not implemented (C99 designated initializers), so this flag has
to be enabled for now.
The struct builders now generate the struct as an inline expression if a
name isn't provided rather than a statement. This means we can now use
`addSimpleStruct` etc for the type of fields, but we can't replace
`addFieldWithStructType` because of `#pragma pack(pop)`.
Doc comments are added to every usable proc but may still not be
sufficient.
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.
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.
```
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>
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.
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.
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.
`addSimpleStruct` is just so the compiler doesn't use so much extra
computation on analyzing the `typ` parameter for `addStruct`, which
doesn't change anything for `seq` types. We could probably still get
away with using `addStruct` instead, or making `addStruct` accept `nil`
as the `typ` argument but this would be even more computation.
There were a lot of hidden issues with `addStruct` being a template &
template argument substitution, so most of the behavior is moved into
`startStruct`/`finishStruct` procs.
This is turning out to be a lot of code for just a couple of changed
lines, we might have to split `cbuilder` into multiple modules.
fixes#24008
The old logic didn't check the contents of the output executables, when
it switched release->debug->release, it picked up the Json files used in
the first release building, the content of which didn't change. So it
mistook the executables which are built by the second debug building as
the functioning one.
`changeDetectedViaJsonBuildInstructions` needs a way to distinguish the
executables generated by different buildings.
refs #24207
The `-d:nimUseCAtomics` flag added in #24207 is now inverted and made
into `-d:nimUseCppAtomics`, which means C++ atomics are only enabled
with the define. This flag is now also documented and tested.
fixes#24203
`semTypeNode` is called twice for RHS'es of type sections,
[here](b0e6d28782/compiler/semstmts.nim (L1612))
and
[here](b0e6d28782/compiler/semstmts.nim (L1646)).
Each time `prev` is `s.typ`, but the assertion expects `prev == nil`
which is false since `s.typ` is not nil the second time. To fix this,
the `prev == nil` part of the assertion is removed.
The reason this only happens for types like `seq[int]`, `(int, int)` etc
is because they don't have syms: `semTypeIdent` attempts to directly
[replace the typedesc param
itself](b0e6d28782/compiler/semtypes.nim (L1916))
with the sym of the base type of the resolved typedesc type if it
exists, which means `semTypeNode` doesn't receive the typedesc param sym
to perform the assert.
refs https://github.com/nim-lang/Nim/pull/24200#issuecomment-2382501282
Workaround for C++ Atomic[T] issues that doesn't require a compiler
change. Not tested or documented in case it's not meant to be officially
supported, locally tested `tatomics` and #24159 to work with it though,
can add these as tests if required.
fixes#22523
There were 2 problems with the code in `sameType` for
`dcEqIgnoreDistinct`:
1. The code that skipped `{tyDistinct, tyGenericInst}` only ran if the
given types had different kinds. This is fixed by always performing this
skip.
2. The code block below that checks if `tyGenericInst`s have different
values still ran for `dcEqIgnoreDistinct` since it checks if the given
types are generic insts, not the skipped types (and also only the 1st
given type). This is fixed by only invoking this block for `dcEq`;
`dcEqOrDistinctOf` (which is unused) also skips the first given type.
Arguably there is another issue here that `skipGenericAlias` only ever
skips 1 type.
These combined fix the issue (`T` is `GenericInst(V, 1, distinct int)`
and `D[0]` is `GenericInst(D, 0, distinct int)`).
#24037 shouldn't be a dependency but the diff follows it.
Sorry I don't have a test case or issue for this. `injectdestructors` is
supposed to add a final bool argument to `=copy` and `=dup` to mark
cyclic types, as generated by `liftdestructors`. Hence this flag is
added after every call to `genCopy`, but `genCopy` can generate a
`=sink` call when passed the flag `IsExplicitSink` by `nkSinkAsgn`. This
creates a codegen error, saying the sink received an extra argument.
This is fixed by not adding the argument on the flag `IsExplicitSink`.
This is a followup to #20585 which is on the 2.0 branch, hence this is
marked backport.
based on #24127
Needs some tweaks to replace the other `struct` type generations, e.g.
seqs, maybe by exposing `BaseTypeKind` as a parameter. C++ and
codegenDecl etc seem like they are going to need attention.
Also `Builder` should really be `distinct string` that one has to call
`extract` on, but for this to be optimal in the current codegen, we
would need something like:
```nim
template buildInto(s: var string, builderName: untyped, body) =
template `builderName`: untyped = Builder(s)
body
buildInto(result, builder):
builder.add ...
```
but this could be a separate PR since it might not work with the
compiler. The possibly-not-optimal alternative is to do:
```nim
template build(builderName: untyped, body): string =
var `builderName` = Builder("")
body
extract(`builderName`)
result = build(builder):
builder.add ...
```
where the compiler maybe copies the built string but shouldn't.
---------
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
fixes#19010
`getType` for proc types generated an `nkProcTy` for iterator types
instead of `nkIteratorTy`, and didn't generate a calling convention
pragma unless it was in the proc AST. Iterator types now generate
`nkIteratorTy`, and a calling convention pragma is added if the calling
convention isn't `closure` or was explicitly provided.
fixes#11422, refs #8336/#8333, refs #20130
The compiler generates conversion nodes *after* evaluating the branches
of case statements as constants, the reasoning is that case branches
accept constants of different types, like arrays or sets. But this means
that conversion nodes that need to be evaluated like converter calls
don't get evaluated as a constant for codegen. #8336 fixed this by
re-evaluating the node if an `nkHiddenCallConv` was created, and in
#20130 this logic also had to be added for `nkHiddenStdConv` for
cstrings. This logic was only for single case elements, it has now been
added to range elements as well to fix#11422. Additionally, all
conversion nodes are now evaluated for simplicity, but maybe this won't
pass CI.
fixes#19866 given #23997
When searching for a module-qualified symbol, `qualifiedLookUp` tries to
obtain the raw identifier from the RHS of the dot field. However it only
does this when the RHS is either an `nkIdent` or an `nkAccQuoted` node,
not when the node is a resolved symbol or a symchoice, such as in
templates and generics when the module symbol can't be resolved yet.
Since the LHS is a module symbol when the compiler checks for this, any
resolved symbol information doesn't matter, since it has to be a member
of the module. So we now obtain the identifier from these nodes as well
as the unresolved identifier nodes.
The test is a bit niche and possibly not officially supported, but this
is likely a more general problem and I just couldn't think of another
test that would be more "proper". It's better than the error message
`'a' has no type` at least.
fixes#24179
The original fix made it so calls to `skError`/`skUnknown` (in this case
`->`, for some reason `sugar` couldn't be imported) returned an error
node, however this breaks tsug_accquote for some reason I don't
understand (it even parses as `tsug_accquote.discard`) so I've just
added a guard based on the stacktrace.
fixes#19277, refs #24169, refs #18124
When pragmas are pushed to a routine, if the routine symbol AST isn't
nil by the time the pushed pragmas are being processed, the pragmas are
implicitly added to the symbol AST. However this is done without
restriction on the pragma, if the pushed pragma isn't supposed to apply
to the routine, it's still added to the routine. This is why the symbol
AST for templates wasn't set before the pushed pragma processing in
#18124. Now, the pragmas added to the AST are restricted to ones that
apply to the given routine. This means we can set the template symbol
AST earlier so that the pragmas get added to the template AST.
fixes#24164, regression from #20091
The expression `nil` as the default value of template parameter `x:
untyped` is typechecked with expected type `untyped` since #20091. The
expected type is checked if it matches the `nil` literal with a match
better than a subtype match, and the type is set to it if it does.
However `untyped` matches with a generic match which is better, so the
`nil` literal has type `untyped`. This breaks type matching for the
literal. So if the expected type is `untyped` or `typed`, it is now
ignored and the `nil` literal just has the `nil` type.
When importing from subdirectories, the line info used in `UnusedImport`
warning would be the `/` node and not the actual module node. More
obvious with grouped imports where all unused imports would show the
same column

Fix is to just use the last child node for infixes when getting the line
info
Added in #24119, the test checks if every string produced is equal, but
the value of the strings depend on the `now()` timestamp of when they
were produced. 30 of them are produced in a for loop in sequence with
each other, but the first one is set after the data is marshalled into
and unmarshalled from a file. This means the timestamp strings can
differ depending on the execution time and causes this test to be flaky.
Instead we just make 2 strings from the same data and check if they
equal each other.
fixes#24150, refs #22022
An exception is raised in the `semExprWithType` call, which means `dec
c.inTypeofContext` is never called, but `compiles` allows compilation to
continue. This means `c.inTypeofContext` is left perpetually nonzero,
which prevents `compileTime` evaluation for the rest of the program.
To fix this, `defer:` is used for the `dec c.inTypeofContext` call, as
is done for
[`instCounter`](d51d88700b/compiler/seminst.nim (L374))
in other parts of the compiler.
Since the module allows for a handler to be added multiple times, for
the sake of consistency, `removeHandler` only removes the first found
instance of the handler in the `handlers` seq. So for n calls of
`addHandler` using the same handler, n calls of `removeHandler` are
required.
fixes#23757
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This fixes a logic error in #23870
The inheritance penalty should be -1 if there is no inheritance
relationship. Not sure how to write a test case for this one honestly.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>