adds modifierMode parameter to typeof (#25815)

This PR adds 3 modes to `typeof` to specify how to handle type modifiers
`var`, `sink` and `lent`.

- typeOfModCompatible
Remove or keep type modifiers in the same way as old typeof. That means
keep `sink` but remove `var` and `lent`.
- typeOfModRemoveModifier
  Remove type modifiers.
- typeOfModKeepModifier
  Keep type modifiers.

Related to https://github.com/nim-lang/Nim/pull/25779
https://github.com/nim-lang/Nim/issues/25786

(cherry picked from commit 48621c217f)
This commit is contained in:
Tomohiro
2026-06-10 03:55:30 +09:00
committed by narimiran
parent 848188512c
commit db595b397c
6 changed files with 161 additions and 22 deletions

View File

@@ -106,7 +106,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExprCheck(c, n, flags)
if result.typ == nil:
if result.typ == nil and efInTypeof in flags:
result.typ = c.voidType
elif result.typ == nil:
localError(c.config, n.info, errExprXHasNoType %
renderTree(result, {renderNoComments}))
result.typ() = errorType(c)

View File

@@ -43,17 +43,8 @@ proc semAddr(c: PContext; n: PNode): PNode =
result.typ() = makePtrType(c, x.typ.skipTypes({tySink}))
proc semTypeOf(c: PContext; n: PNode): PNode =
var m = BiggestInt 1 # typeOfIter
if n.len == 3:
let mode = semConstExpr(c, n[2])
if mode.kind != nkIntLit:
localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time")
else:
m = mode.intVal
let typExpr = semTypeOfImpl(c, n)
result = newNodeI(nkTypeOfExpr, n.info)
inc c.inTypeofContext
defer: dec c.inTypeofContext # compiles can raise an exception
let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
result.add typExpr
if typExpr.typ.kind == tyFromExpr:
typExpr.typ.flags.incl tfNonConstExpr

View File

@@ -1949,6 +1949,57 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
result.rawAddSon(base)
result.flags.incl tfHasStatic
proc semTypeOfImpl(c: PContext; n: PNode): PNode =
var m = BiggestInt 1 # typeOfIter
var modifierMode = BiggestInt 0 # CompatibleTypeModifiers
type
TypeOfParams = enum
topMode
topModifier
if n.len in 3 .. 4:
for i in 2 ..< n.len:
var argKind = topMode
var arg: PNode = nil
if n[i].kind == nkExprEqExpr and n[i][0].kind == nkIdent:
# named param
case n[i][0].ident.s
of "mode": argKind = topMode
of "modifierMode": argKind = topModifier
else:
localError(c.config, n.info, "typeof: got unknown parameter name")
arg = n[i][1]
else:
if i == 2:
argKind = topMode
else:
argKind = topModifier
arg = n[i]
case argKind
of topMode:
let mode = semConstExpr(c, arg)
if mode.kind != nkIntLit:
localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time")
else:
m = mode.intVal
of topModifier:
let modMode = semConstExpr(c, arg)
if modMode.kind != nkIntLit:
localError(c.config, n.info, "typeof: cannot evaluate 'modifierMode' parameter at compile-time")
else:
modifierMode = modMode.intVal
inc c.inTypeofContext
defer: dec c.inTypeofContext # compiles can raise an exception
var typExpr = semExprNoDeref(c, n[1], if m == 1: {efInTypeof} else: {})
if modifierMode == 0:
# CompatibleTypeModifiers
typExpr.typ = typExpr.typ.skipTypes({tyVar, tyLent})
elif modifierMode == 1:
# RemoveTypeModifiers
typExpr.typ = typExpr.typ.skipTypes({tyVar, tyLent, tySink})
result = typExpr
proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
openScope(c)
inc c.inTypeofContext
@@ -1969,16 +2020,7 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
openScope(c)
var m = BiggestInt 1 # typeOfIter
if n.len == 3:
let mode = semConstExpr(c, n[2])
if mode.kind != nkIntLit:
localError(c.config, n.info, "typeof: cannot evaluate 'mode' parameter at compile-time")
else:
m = mode.intVal
inc c.inTypeofContext
defer: dec c.inTypeofContext # compiles can raise an exception
let ex = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
let ex = semTypeOfImpl(c, n)
closeScope(c)
result = ex.typ
if result.kind == tyFromExpr: