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.
This commit is contained in:
metagn
2024-09-17 07:22:45 +03:00
committed by GitHub
parent fe55dcb2be
commit b5f2eafed1
3 changed files with 25 additions and 0 deletions

View File

@@ -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})

View File

@@ -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

View File

@@ -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"