From 0e2b34ce3571188cfe234067c80fcfa89e220d43 Mon Sep 17 00:00:00 2001 From: metagn Date: Thu, 22 Aug 2024 08:20:20 +0300 Subject: [PATCH] fix subscript magic giving unresolved generic param type (#23988) 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. (cherry picked from commit 04da0a6028a4a0d469a10567a35655646f4957c2) --- compiler/semcall.nim | 3 ++- tests/overload/m19737.nim | 10 ++++++++++ tests/overload/t19737.nim | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/overload/m19737.nim create mode 100644 tests/overload/t19737.nim diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 13506becdd..0cc30132e8 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -662,7 +662,8 @@ proc semResolvedCall(c: PContext, x: TCandidate, instGenericConvertersSons(c, result, x) markConvertersUsed(c, result) result[0] = newSymNode(finalCallee, getCallLineInfo(result[0])) - result.typ = finalCallee.typ[0] + if finalCallee.magic notin {mArrGet, mArrPut}: + result.typ = finalCallee.typ[0] updateDefaultParams(result) proc canDeref(n: PNode): bool {.inline.} = diff --git a/tests/overload/m19737.nim b/tests/overload/m19737.nim new file mode 100644 index 0000000000..7f7ac98e2a --- /dev/null +++ b/tests/overload/m19737.nim @@ -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)) diff --git a/tests/overload/t19737.nim b/tests/overload/t19737.nim new file mode 100644 index 0000000000..b33ba9d8bd --- /dev/null +++ b/tests/overload/t19737.nim @@ -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)