generate tyFromExpr for typeof static param with generic base type (#24745)

fixes #24743, refs #24718

We cannot do this in general for any expression with generic type
because the `typeof` logic is called for things like `type Foo` in:

```nim
type Foo[T] = object

proc init(_: type Foo) = discard
```

We also cannot use `containsUnresolvedType` to work around this specific
case because the base type of `static[auto]` is not unresolved, it is a
typeclass that isn't lifted to a parameter. The behavior of generating
`tyFromExpr` is also consistent with pre-2.0, so we do this in this
special case of `static`.
This commit is contained in:
metagn
2025-03-05 15:47:56 +03:00
committed by GitHub
parent e39d152b89
commit 569d02e212
3 changed files with 45 additions and 13 deletions

View File

@@ -55,7 +55,15 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
result.add typExpr
if typExpr.typ.kind == tyFromExpr:
typExpr.typ.flags.incl tfNonConstExpr
result.typ() = makeTypeDesc(c, typExpr.typ.skipTypes({tyStatic}))
var t = typExpr.typ
if t.kind == tyStatic:
let base = t.skipTypes({tyStatic})
if c.inGenericContext > 0 and base.containsGenericType:
t = makeTypeFromExpr(c, copyTree(typExpr))
t.flags.incl tfNonConstExpr
else:
t = base
result.typ() = makeTypeDesc(c, t)
type
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn

View File

@@ -1933,11 +1933,17 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
defer: dec c.inTypeofContext # compiles can raise an exception
let ex = semExprWithType(c, n, {efInTypeof})
closeScope(c)
let t = ex.typ.skipTypes({tyStatic})
fixupTypeOf(c, prev, t)
result = t
result = ex.typ
if result.kind == tyFromExpr:
result.flags.incl tfNonConstExpr
elif result.kind == tyStatic:
let base = result.skipTypes({tyStatic})
if c.inGenericContext > 0 and base.containsGenericType:
result = makeTypeFromExpr(c, copyTree(ex))
result.flags.incl tfNonConstExpr
else:
result = base
fixupTypeOf(c, prev, result)
proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
openScope(c)
@@ -1952,11 +1958,17 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
defer: dec c.inTypeofContext # compiles can raise an exception
let ex = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
closeScope(c)
let t = ex.typ.skipTypes({tyStatic})
fixupTypeOf(c, prev, t)
result = t
result = ex.typ
if result.kind == tyFromExpr:
result.flags.incl tfNonConstExpr
elif result.kind == tyStatic:
let base = result.skipTypes({tyStatic})
if c.inGenericContext > 0 and base.containsGenericType:
result = makeTypeFromExpr(c, copyTree(ex))
result.flags.incl tfNonConstExpr
else:
result = base
fixupTypeOf(c, prev, result)
proc semTypeIdent(c: PContext, n: PNode): PSym =
if n.kind == nkSym:

View File

@@ -1,9 +1,21 @@
# issue #24715
block: # issue #24715
type H[c: static[float64]] = object
value: typeof(c)
type H[c: static[float64]] = object
value: typeof(c)
proc u[T: H](_: typedesc[T]) =
discard default(T)
proc u[T: H](_: typedesc[T]) =
discard default(T)
u(H[1'f64])
u(H[1'f64])
block: # issue #24743
type
K[w: static[auto]] = typeof(w)
V = object
a: K[0]
GenericV[w: static[auto]] = object
a: typeof(w)
var x: GenericV[0]
doAssert x.a is int
var y: GenericV["abc"]
doAssert y.a is string