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.
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.
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`
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.
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.
updated version of #22193
After #22029 and the followups #23983 and #24005 which fixed issues with
it, `tyFromExpr` no longer match any proc params in generic type bodies
but delay all non-matching calls until the type is instantiated.
Previously the mechanism `fauxMatch` was used to pretend that any
failing match against `tyFromExpr` actually matched, but prevented the
instantiation of the type until later.
Since this mechanism is not needed anymore for `tyFromExpr`, it is now
only used for `tyError` to prevent cascading errors and changed to a
bool field for simplicity. A change in `semtypes` was also needed to
prevent calling `fitNode` on default param values resolving to type
`tyFromExpr` in generic procs for params with non-generic types, as this
would try to coerce the expression into a concrete type when it can't be
instantiated yet.
The aliases `tyProxy` and `tyUnknown` for `tyError` and `tyFromExpr` are
also removed for uniformity.
fixes#22850
The `is` operator checks the type of the left hand side, and if it's
generic or if it's a `typedesc` type with no base type, it leaves it to
be evaluated later. But `typedesc` types with no base type precisely
describe the default typeclass `type`/`typeclass`, so this condition is
removed. Maybe at some point this represented an unresolved generic
type?
This fixes an oversight with a change that I made a while ago.
Basically, these two snippets should both compile. Currently the
`varargs` version will fail.
```nim
template s(d: typed)=discard
proc something()=discard
proc something(x:int)=discard
s(something)
```
```nim
template s(d: varargs[typed])=discard
proc something()=discard
proc something(x:int)=discard
s(something)
```
Potentially unrelated, but this works currently for some reason:
```nim
template s(a: varargs[typed])=discard
proc something()=discard
proc something(x:int)=discard
s:
something
```
also, this works:
```nim
template s(b:untyped, a: varargs[typed])=discard
proc something()=discard
proc something(x:int)=discard
s (g: int):
something
```
but this doesn't, and the error message is not what I would expect:
```nim
template s(b:untyped, a: varargs[typed])=discard
proc something()=discard
proc something(x:int)=discard
s (g: int), something
```
So far as I can tell, none of these issues persist for me after the code
changes in this PR.
fixes#23200, fixes#18866#21065 made it so `auto` proc return types remained as `tyAnything` and
not turned to `tyUntyped`. This had the side effect that anything
previously bound to `tyAnything` in the proc type match was then bound
to the proc return type, which is wrong since we don't know the proc
return type even if we know the expected parameter types (`tyUntyped`
also [does not care about its previous bindings in
`typeRel`](ab4278d217/compiler/sigmatch.nim (L1059-L1061))
maybe for this reason).
Now we mark `tyAnything` return types for routines as `tfRetType` [as
done for other meta return
types](18b5fb256d/compiler/semtypes.nim (L1451)),
and ignore bindings to `tyAnything` + `tfRetType` types in `semtypinst`.
On top of this, we reset the type relation in `paramTypesMatch` only
after creating the instantiation (instead of trusting
`isInferred`/`isInferredConvertible` before creating the instantiation),
using the same mechanism that `isBothMetaConvertible` uses.
This fixes the issues as well as making the disabled t15386_2 test
introduced in #21065 work. As seen in the changes for the other tests,
the error messages give an obscure `proc (a: GenericParam): auto` now,
but it does give the correct error that the overload doesn't match
instead of matching the overload pre-emptively and expecting a specific
return type.
tsugar had to be changed due to #16906, which is the problem where
`void` is not inferred in the case where `result` was never touched.
* test case haul for old generic/template/macro issues
closes#12582, closes#19552, closes#2465, closes#4596, closes#15246,
closes#12683, closes#7889, closes#4547, closes#12415, closes#2002,
closes#1771, closes#5121
The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.
* fix template gensym test
* round out tuple unpacking assignment, support underscores
fixes#18710
* fix test messages
* use discard instead of continue
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* Allows for arbitrary ordering of inheritance in type section #6259
* prevents ilegal recursion
* fixes ilegal recursion. Test passes with a better message
* Apply suggestions from code review
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
* clean up some test categories
* mention exact slice issue
* magics into system
* move trangechecks into overflow
* move tmemory to system
* try fix CI
* try fix CI
* final CI fix
* remove deprecated pragma syntax from 0.20.0
closes#4651, closes#16653 with a cheap fix for now due to
how early `tfFinal` is set
* remove type pragma between name and generics
* undo removal, try removing bind expression (0.8.14)
* fix test, unremove bind expr
* remove again
* Update changelog.md
Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
* dependencies @ HEAD & weave test dependencies
* try fix package ci
Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
* micro implementation of rfc 149
refs https://github.com/nim-lang/RFCs/issues/149
* number/array/seq literals, more statements
* try fix number literal alias issue
* renew expectedType with if/case/try branch types
* fix (nerf) index type handling and float typed int
* use typeAllowed
* tweaks + const test (tested locally) [skip ci]
* fill out more of the checklist
* more literals, change @ order, type conversions
Not copying the full call tree before the typedesc call check
in `semIndirectOp` is also a small performance improvement.
* disable self-conversion warning
* revert type conversions (maybe separate op later)
* deal with CI for now (seems unrelated), try enums
* workaround CI different way
* proper fix
* again
* see sizes
* lol
* overload selection, simplify int literal -> float
* range, new @ solution, try use fitNode for nil
* use new magic
* try fix ranges, new magic, deal with #20193
* add documentation, support templates
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Instead of rejecting type expressions based on node kind,
evaluate the expression as a type.
This is already the behavior for call results, and it has its own error
for non-types, which is the same error you would normally get
with 2 words swapped.
* deprecate unsafeAddr; extend addr
addr is now available for all addressable locations, unsafeAddr is deprecated and become an alias for addr
* follow @Vindaar's advice
* change the signature of addr
* unsafeAddr => addr (stdlib)
* Update changelog.md
* unsafeAddr => addr (tests)
* Revert "unsafeAddr => addr (stdlib)"
This reverts commit ab83c99c50.
* doc changes; thanks to @konsumlamm
Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
* fix failing test toSeq in manual which now works
* changelog
* reject proc fn(a: iterable)
* add iterable to spec
* remove MCS/UFCS limitation that now works
* fix#14127 from int to int casting
* add test for #14127
* use template for test, also test uint2int
* move to tests/types/t14127_cast_number.nim targets:c cpp js