block ambiguous type conversion dotcalls in generics (#22375)

fixes #22373
This commit is contained in:
metagn
2023-08-09 07:12:14 +03:00
committed by GitHub
parent d136af0122
commit 3aaef9e4cf
5 changed files with 57 additions and 0 deletions

View File

@@ -168,6 +168,17 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
elif s.isMixedIn:
result = newDot(result, symChoice(c, n, s, scForceOpen))
else:
if s.kind == skType and candidates.len > 1:
var ambig = false
let s2 = searchInScopes(c, ident, ambig)
if ambig:
# this is a type conversion like a.T where T is ambiguous with
# other types or routines
# in regular code, this never considers a type conversion and
# skips to routine overloading
# so symchoices are used which behave similarly with type symbols
result = newDot(result, symChoice(c, n, s, scForceOpen))
return
let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
result = newDot(result, syms)

View File

@@ -0,0 +1,7 @@
# module a for t22373
# original:
type LightClientHeader* = object
# simplified:
type TypeOrTemplate* = object

View File

@@ -0,0 +1,18 @@
# module b for t22373
import m22373a
# original:
type
LightClientDataFork* {.pure.} = enum
None = 0,
Altair = 1
template LightClientHeader*(kind: static LightClientDataFork): auto =
when kind == LightClientDataFork.Altair:
typedesc[m22373a.LightClientHeader]
else:
static: raiseAssert "Unreachable"
# simplified:
template TypeOrTemplate*(num: int): untyped =
typedesc[m22373a.TypeOrTemplate]

16
tests/generics/t22373.nim Normal file
View File

@@ -0,0 +1,16 @@
# issue #22373
import m22373a
import m22373b
# original:
template lazy_header(name: untyped): untyped {.dirty.} =
var `name _ ptr`: ptr[data_fork.LightClientHeader] # this data_fork.Foo part seems required to reproduce
proc createLightClientUpdates(data_fork: static LightClientDataFork) =
lazy_header(attested_header)
createLightClientUpdates(LightClientDataFork.Altair)
# simplified:
proc generic[T](abc: T) =
var x: abc.TypeOrTemplate
generic(123)

View File

@@ -46,6 +46,11 @@ block tdotlookup:
x.set("hello", "world")
result = x
doAssert abc(5) == 10
block: # ensure normal call is consistent with dot call
proc T(x: int): float = x.float
proc foo[T](x: int) =
doAssert typeof(T(x)) is typeof(x.T)
foo[uint](123)
block tmodule_same_as_proc:
# bug #1965