Skip to content

Commit

Permalink
fix calls to implicitly generic params in generic contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Oct 5, 2024
1 parent 7dfadb8 commit 07fc303
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 1 deletion.
3 changes: 3 additions & 0 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,9 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =

var lhsType = n[1].typ
if lhsType.kind != tyTypeDesc:
if c.inGenericContext > 0 and lhsType.containsUnresolvedType:
# `x is T` where `x` is unresolved, cannot evaluate yet
return
if liftLhs:
n[1] = makeTypeSymNode(c, lhsType, n[1].info)
lhsType = n[1].typ
Expand Down
6 changes: 6 additions & 0 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
case a.kind
of tyOr:
# XXX: deal with the current dual meaning of tyGenericParam
if c.c.inGenericContext > 0 and not c.isNoCall:
# a has unresolved type, don't match call in generic context
return isNone
c.typedescMatched = true
# seq[int|string] vs seq[number]
# both int and string must match against number
Expand Down Expand Up @@ -1339,6 +1342,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if f.kind == tyAnything: return isGeneric
else: return isNone
of tyUserTypeClass, tyUserTypeClassInst:
if c.c.inGenericContext > 0 and not c.isNoCall:
# a has unresolved type, don't match call in generic context
return isNone
if c.c.matchedConcept != nil and c.c.matchedConcept.depth <= 4:
# consider this: 'var g: Node' *within* a concept where 'Node'
# is a concept too (tgraph)
Expand Down
3 changes: 2 additions & 1 deletion compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,8 @@ proc containsGenericType*(t: PType): bool =
result = iterOverType(t, containsGenericTypeIter, nil)

proc containsUnresolvedTypeIter(t: PType, closure: RootRef): bool =
if tfUnresolved in t.flags: return true
if {tfUnresolved, tfGenericTypeParam, tfImplicitTypeParam} * t.flags != {}:
return true
case t.kind
of tyStatic:
return t.n == nil
Expand Down
36 changes: 36 additions & 0 deletions tests/proc/tgenericdefaultparam.nim
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,39 @@ block: # issue #24121
proc baz[T: FooBar](x: T, y = foo(x)): string = y
doAssert baz(Foo(123)) == "b"
doAssert baz(Bar(123)) == "c"

block: # using `or` type
template val(x: int): string = "int"
template val(x: string): string = "string"
proc foo(x: int | string, y = val(x)): string =
y

doAssert foo(123) == "int"
doAssert foo("abc") == "string"

block: # using concept type
type Foo = concept x
x is int | string
template val(x: int): string = "int"
template val(x: string): string = "string"
proc foo(x: Foo, y = val(x)): string =
y

doAssert foo(123) == "int"
doAssert foo("abc") == "string"

block: # using `or` type with direct `is`
proc foo(x: int | string, y = when x is int: "int" else: "string"): string =
y

doAssert foo(123) == "int"
doAssert foo("abc") == "string"

block: # using concept type with direct `is`
type Foo = concept x
x is int | string
proc foo(x: Foo, y = when x is int: "int" else: "string"): string =
y

doAssert foo(123) == "int"
doAssert foo("abc") == "string"

0 comments on commit 07fc303

Please sign in to comment.