From 96043bdbb7c777841b98aa7786eba0d6dba814da Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 23 Nov 2024 16:20:15 +0300 Subject: [PATCH] fix crash with tyBuiltInTypeClass matching itself (#24462) fixes #24449 The standalone `seq` type is a `tyBuiltInTypeClass` with a single child of kind `tySequence`, which itself has no children. This is also the case for most other `tyBuiltInTypeClass` kinds. However this can cause a crash in sigmatch when calling `isEmptyContainer` on this child type, which expects the sequence type to have children. This check was added in #5557 to prevent empty collections like `@[]` from matching their respective typeclass, but it's not useful when matching against another typeclass (which is done here to resolve an ambiguity). So to avoid the crash, this empty container check is disabled when matching against another typeclass. --- compiler/sigmatch.nim | 5 ++++- tests/overload/tvartypeclass.nim | 25 +++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 848cc684d6..14661ffcf8 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1878,9 +1878,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, let target = f.genericHead let targetKind = target.kind var effectiveArgType = reduceToBase(a) + # the skipped child of tyBuiltInTypeClass can be structured differently, + # newConstraint constructs them with no children + let typeClassArg = effectiveArgType.kind == tyBuiltInTypeClass effectiveArgType = effectiveArgType.skipTypes({tyBuiltInTypeClass}) if targetKind == effectiveArgType.kind: - if effectiveArgType.isEmptyContainer: + if not typeClassArg and effectiveArgType.isEmptyContainer: return isNone if targetKind == tyProc: if target.flags * {tfIterator} != effectiveArgType.flags * {tfIterator}: diff --git a/tests/overload/tvartypeclass.nim b/tests/overload/tvartypeclass.nim index 04f3f5a910..c47e2102cf 100644 --- a/tests/overload/tvartypeclass.nim +++ b/tests/overload/tvartypeclass.nim @@ -1,11 +1,16 @@ -# issue #13302 +block: # issue #13302 + proc foo(x: object): int = x.i*2 + proc foo(x: var object) = x.i*=2 + type Foo = object + i: int + let x = Foo(i: 3) + var y = Foo(i: 4) + doAssert foo(x) == 6 + foo(y) + doAssert y.i == 8 -proc foo(x: object): int = x.i*2 -proc foo(x: var object) = x.i*=2 -type Foo = object - i: int -let x = Foo(i: 3) -var y = Foo(i: 4) -doAssert foo(x) == 6 -foo(y) -doAssert y.i == 8 +block: # issue #24449 + proc p(x: var seq)= discard + proc p(x: seq)= discard + var s : seq[int] + p(s)