Commit Graph

6700 Commits

Author SHA1 Message Date
Jake Leahy
0cba752c8a Allow specifiying path to use for stdin error messages (#24595)
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
2025-04-12 08:40:25 +02:00
metagn
97d819a251 add bit type overloads of $ and repr (#24865)
fixes #24864
2025-04-12 08:37:36 +02:00
ringabout
42df731a2d fixes #24764; cross-module sink analysis broken (#24862)
fixes  #24764

It now consumes the `conv(x)` arg for the explicit sinking. So the
explicit sinking is kept as it is.

Follows up https://github.com/nim-lang/Nim/pull/20585

Related issues: https://github.com/nim-lang/Nim/issues/20572

Probably the same needs to be applied to explicit `copy` to prevent a
copy turning into a sink
2025-04-12 06:47:57 +02:00
metagn
f58cd51fc4 ignore typeof in closure iterators (#24861)
fixes #24859
2025-04-11 23:50:13 +03:00
metagn
897126a711 fix array/set/tuple literals with generic expression elements (#24497)
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>
2025-04-11 18:38:35 +02:00
Ryan McConnell
d4098e6ca0 new-style concept bugfix (#24858)
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.
2025-04-11 06:54:52 +02:00
metagn
918f972369 skip semicolon in stmtlist expr parsing (#24855)
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.
2025-04-11 03:29:20 +02:00
ringabout
29a2e25d1e fixes #24850; macro-generated if/else and when/else statements have m… (#24852)
…ismatched indentation with repr

fixes #24850
2025-04-08 23:54:31 +08:00
metagn
a625fab098 make fillObjectFields recur over base type (#24854)
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.
2025-04-08 17:00:58 +03:00
ringabout
26b86c8f4d Makes except: panics on Defect (#24821)
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.
2025-04-03 16:09:58 +02:00
ringabout
73aeac81d1 fixes #24806; don't elide wasMoved when syms are used in blocks (#24831)
fixes #24806

Blocks don't merge symbols that are used before destruction to the
parent scope, which causes `wasMoved; destroy` to elide incorrectly
2025-04-03 12:54:00 +02:00
metagn
5bcd9a329a fix infinite recursion with pushed user pragmas (#24839)
fixes #24838
2025-04-03 12:53:42 +02:00
ringabout
4352fa2ef0 fixes #24801; Invalid C codegen generated when destroying distinct seq types (#24835)
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
2025-04-02 18:46:29 +02:00
ringabout
3617d2e077 fixes lastRead uses the when nimvm branch (#24834)
```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
2025-04-02 09:29:15 +02:00
ringabout
f9c8775783 conv needs to be picky about aliases and introduces a temp for addr conv (#24818)
ref https://github.com/nim-lang/Nim/pull/24817
ref https://github.com/nim-lang/Nim/pull/24815
ref https://github.com/status-im/nim-eth/pull/784


```nim
{.emit:"""
void foo(unsigned long long* x)
{
}
""".}


proc foo(x: var culonglong) {.importc: "foo", nodecl.}

proc main(x: var uint64) =
  # var s: culonglong = u # TODO:
  var m = uint64(12)
  # var s = culonglong(m)
  foo(culonglong m)

var u = uint64(12)
main(u)
```
Notes that this code gives incompatible errors in 2.0.0, 2.2.0 and the
devel branch. With this PR, `conv` is kept, but it seems to go back to
https://github.com/nim-lang/Nim/pull/24807
2025-04-01 09:37:54 +02:00
Jake Leahy
e0a4876981 Fix nim-gdb.py script (#24824)
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

![image](https://github.com/user-attachments/assets/450b020f-1665-4ed2-9073-d02537150914)
2025-03-29 13:28:28 +01:00
ringabout
58b1f28177 fixes implicitConv discarding flags (#24817)
follow up https://github.com/nim-lang/Nim/pull/24809
ref https://github.com/nim-lang/Nim/pull/24815
2025-03-28 12:52:45 +01:00
ringabout
73112d64a3 fixes #24793; Revert "remove special treatments of sinking const sequences (#24812)
fixes #24793

There doesn't seem to have a better solution
2025-03-26 23:49:00 +08:00
ringabout
ddd83f8d8a fixes #24800; Invalid C code generation with a method, case object in refc (#24809)
fixes #24800

This PR avoids a conversion from `sink T` to `T`

I will add a test case
2025-03-25 20:42:40 +01:00
Zoom
909f3b8b79 [feature] stdlib: strutils.multiReplace for character sets (#24805)
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
2025-03-25 07:40:01 +01:00
metagn
fcba14707a disable "dest register is set" for vm statements (#24797)
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.
2025-03-23 06:59:06 +03:00
Ryan McConnell
2b699bca53 new-style concepts - small bugfix (#24778) 2025-03-15 15:05:14 +01:00
metagn
fb93295344 fix compound inheritance penalty (#24775)
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>
2025-03-12 17:31:33 +01:00
ringabout
9ebfa7973a fixes generic types sink T cannot be inferred for passed arguments (#24761)
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
2025-03-12 17:31:19 +01:00
metagn
82891e6850 give hint for forward declarations with unknown raises effects (#24767)
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.
2025-03-11 14:24:45 +01:00
Ryan McConnell
850f327713 folding const expressions with branching logic (#24689)
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.
2025-03-11 10:01:32 +01:00
metagn
38ad336c69 fix tuple nodes from VM inserting hidden conv to keep old type (#24756)
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
2025-03-11 10:00:37 +01:00
ringabout
a7711d452d fixes #24754; {.gcsafe.} block breaks move analysis (#24757)
fixes #24754
2025-03-11 09:59:55 +01:00
metagn
e2e7790779 fix canRaise for non-proc calls (#24752)
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`
2025-03-11 09:59:21 +01:00
ringabout
e2d4791229 fixes move for getPotentialWrites (#24753)
`move` would modify parameters as well
2025-03-11 09:57:48 +01:00
Laylie
f8294ce06e Fix scanTuple undeclared identifier 'scanf' (#24759)
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`.
2025-03-10 22:47:03 +08:00
Ryan McConnell
dfab30734b new-style concepts adjusments (#24697)
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>
2025-03-07 18:14:00 +01:00
metagn
569d02e212 generate tyFromExpr for typeof static param with generic base type (#24745)
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`.
2025-03-05 13:47:56 +01:00
metagn
e39d152b89 handle ranges in annotateType for set constructors (#24737)
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.
2025-02-28 17:23:19 +03:00
ringabout
7e8a650729 sink tuples by values (#24731)
A reduced case
```nim
type AnObject = tuple
  a: string
  b: int
  c: int

proc mutate(a: sink AnObject) =
  `=wasMoved`(a)
  echo 1

# echo "Value is: ", obj.value
proc bar =
  mutate(("1.2", 0, 0))

bar()
```
2025-02-27 18:33:35 +01:00
ringabout
7ecb35115b fixes #24339; underscores used with fields and fieldPairs (#24341)
fixes #24339
2025-02-27 16:48:15 +01:00
ringabout
b421d0f8ee fixes #19728; setLen slow when shrinking seq due to zero-filling of released area (#24683)
fixes #19728

don't zero-filling memory for "trivial types" without destructor in
refc. I tested locally with internal apis.
2025-02-27 16:45:58 +01:00
ringabout
c452275e29 fixes #24705; encode static parameters into function names for debugging (#24707)
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
2025-02-27 16:45:04 +01:00
metagn
a18dcca744 don't try to infer array range to unresolved range (#24709)
fixes #24708
2025-02-26 22:21:03 +01:00
metagn
49dfc3a0d4 convert tuple constructors from VM back to original types (#24710)
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.
2025-02-26 22:20:41 +01:00
ringabout
a7a8e364ea fixes #12340; enable refc with move analyzer (#23782)
fixes https://github.com/nim-lang/Nim/issues/12340
2025-02-25 20:20:24 +01:00
metagn
514a25c9a2 always skip static types for result of typeof (#24718)
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.
2025-02-25 17:09:04 +01:00
ringabout
e449813c61 fixes #24725; Invalid =sink generated for pure inheritable object (#24726)
fixes #24725

`lacksMTypeField` doesn't take the base types into consideration. And
for ` {.inheritable, pure.}`, it shouldn't generate a `m_type` field.
2025-02-25 17:08:22 +01:00
metagn
1f8da3835f keep param pragmas in typed proc AST (#24711)
fixes #24702
2025-02-22 21:22:30 +01:00
ringabout
1af88a2d20 always mangle local variables (#24681)
ref #24677
2025-02-19 23:03:58 +01:00
ringabout
1f07fdd2dc fixes #24664; always sets the \0 terminator in appendString (#24703)
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
```
2025-02-19 23:01:56 +01:00
ringabout
510ac84518 implements quirky for functions (#24700)
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>
2025-02-18 17:24:41 +01:00
metagn
a5cc33c1d3 track introduced locals in vmgen for eval check (#24674)
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.
2025-02-14 20:54:17 +01:00
ringabout
b211ada273 fixes #24673; divmod errors for ranges (#24679)
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`
2025-02-14 20:52:43 +01:00
ringabout
e6f6c369ff fixes bugs on the Nim manual (#24669)
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]
```
2025-02-06 23:19:53 +01:00