mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 06:18:51 +00:00
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:
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user