Skip to content

Commit

Permalink
fix subscript magic giving unresolved generic param type (#23988)
Browse files Browse the repository at this point in the history
fixes #19737

As in the diff, `semResolvedCall` sets the return type of a call to a
proc to the type of the call. But in the case of the [subscript
magic](https://nim-lang.org/docs/system.html#%5B%5D%2CT%2CI), this type
is the first generic param which is also supposed to be the type of the
first argument, but this is invalid, the correct type is the element
type eventually given by `semSubscript`. Some lines above also [prevent
the subscript magics from instantiating their
params](https://github.com/nim-lang/Nim/blob/dda638c1ba985a77eac3c7518138992521884172/compiler/semcall.nim#L699)
so this type ends up being an unresolved generic param.

Since the type of the node is not `nil`, `prepareOperand` doesn't try to
type it again, and this unresolved generic param type ends up being the
final type of the node. To prevent this, we just never set the type of
the node if we encountered a subscript magic.

Maybe we could also rename the generic parameters of the subscript
magics to stuff like `DummyT`, `DummyI` if we want this to be easier to
debug in the future.
  • Loading branch information
metagn authored Aug 22, 2024
1 parent ac0179c commit 04da0a6
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
3 changes: 2 additions & 1 deletion compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,8 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
result = x.call
instGenericConvertersSons(c, result, x)
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
result.typ = finalCallee.typ.returnType
if finalCallee.magic notin {mArrGet, mArrPut}:
result.typ = finalCallee.typ.returnType
updateDefaultParams(result)

proc canDeref(n: PNode): bool {.inline.} =
Expand Down
10 changes: 10 additions & 0 deletions tests/overload/m19737.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type
UInt128* = object
lo, hi: uint64

func `<`*(x, y: UInt128): bool =
(x.hi < y.hi) or ((x.hi == y.hi) and (x.lo < y.lo))

when not defined(works):
func `>`*(x, y: UInt128): bool =
(x.hi > y.hi) or ((x.hi == y.hi) and (x.lo > y.lo))
15 changes: 15 additions & 0 deletions tests/overload/t19737.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# issue #19737

import ./m19737

var m: seq[uint64]

proc foo(x: bool) = discard

proc test[T: uint64|uint32](s: var seq[T]) =
var tmp = newSeq[T](1)
s = newSeq[T](1)

foo s[0] > tmp[0]

test(m)

0 comments on commit 04da0a6

Please sign in to comment.