From b5f2eafed1438e612b7f269e95422a52893f7a5d Mon Sep 17 00:00:00 2001 From: metagn Date: Tue, 17 Sep 2024 07:22:45 +0300 Subject: [PATCH] don't match arguments with typeclass type in generics (#24123) fixes #24121 Proc arguments can have typeclass type like `Foo | Bar` that `sigmatch` handles specially before matching them to the param type, because they wouldn't match otherwise. Not exactly sure why this existed but matching any typeclass or unresolved type in generic contexts now fails the match so typing the call is delayed until instantiation. Also it turns out default values with `tyFromExpr` type depending on other parameters was never tested, this also needs a patch to make the `tyFromExpr` type `tfNonConstExpr` so it doesn't try to evaluate the other parameter at compile time. --- compiler/seminst.nim | 2 ++ compiler/sigmatch.nim | 5 +++++ tests/proc/tgenericdefaultparam.nim | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index ff15925730..1bc6d31a2a 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -254,6 +254,8 @@ proc instantiateProcType(c: PContext, pt: TypeMapping, let needsStaticSkipping = resulti.kind == tyFromExpr let needsTypeDescSkipping = resulti.kind == tyTypeDesc and tfUnresolved in resulti.flags + if resulti.kind == tyFromExpr: + resulti.flags.incl tfNonConstExpr result[i] = replaceTypeVarsT(cl, resulti) if needsStaticSkipping: result[i] = result[i].skipTypes({tyStatic}) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 17d2e7a4db..a48e79b7c6 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1279,6 +1279,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, if prev == nil: body else: return typeRel(c, prev, a, flags) + if c.c.inGenericContext > 0 and not c.isNoCall and + (tfUnresolved in a.flags or a.kind in tyTypeClasses): + # cheap check for unresolved arg, not nested + return isNone + case a.kind of tyOr: # XXX: deal with the current dual meaning of tyGenericParam diff --git a/tests/proc/tgenericdefaultparam.nim b/tests/proc/tgenericdefaultparam.nim index 2d0f850c25..7bce591ce5 100644 --- a/tests/proc/tgenericdefaultparam.nim +++ b/tests/proc/tgenericdefaultparam.nim @@ -78,3 +78,21 @@ block: # issue #13270 g A() # This should fail because there is no f(a: B) overload available doAssert not compiles(g B()) + +block: # issue #24121 + type + Foo = distinct int + Bar = distinct int + FooBar = Foo | Bar + + proc foo[T: distinct](x: T): string = "a" + proc foo(x: Foo): string = "b" + proc foo(x: Bar): string = "c" + + proc bar(x: FooBar, y = foo(x)): string = y + doAssert bar(Foo(123)) == "b" + doAssert bar(Bar(123)) == "c" + + proc baz[T: FooBar](x: T, y = foo(x)): string = y + doAssert baz(Foo(123)) == "b" + doAssert baz(Bar(123)) == "c"