fixes #3770; templates with untyped parameters resolve private fields wrongly in generics (#21554)

* fixes #3770; templates with untyped parameters resolve private fields wrongly

* add a test case for #3770

* rename to `nfSkipFieldChecking`
This commit is contained in:
ringabout
2023-03-21 22:22:07 +08:00
committed by GitHub
parent f7e3af0c2d
commit c814c4d993
8 changed files with 48 additions and 11 deletions

View File

@@ -510,7 +510,7 @@ type
nfLastRead # this node is a last read
nfFirstWrite # this node is a first write
nfHasComment # node has a comment
nfUseDefaultField # node has a default value (object constructor)
nfSkipFieldChecking # node skips field visable checking
TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 46)
@@ -1081,7 +1081,7 @@ const
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
nfFromTemplate, nfDefaultRefsParam,
nfExecuteOnReload, nfLastRead,
nfFirstWrite, nfUseDefaultField}
nfFirstWrite, nfSkipFieldChecking}
namePos* = 0
patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2

View File

@@ -572,7 +572,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
let asgnExpr = defaultNodeField(c, recNode, recNode.typ)
if asgnExpr != nil:
hasDefault = true
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
return
@@ -582,7 +582,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)),
newNodeIT(nkType, recNode.info, asgnType)
)
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
asgnExpr.typ = recType
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
else:
@@ -604,7 +604,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
defaultValue.typ = discriminator.typ
selectedBranch = recNode.pickCaseBranchIndex defaultValue
defaultValue.flags.incl nfUseDefaultField
defaultValue.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1])
of nkSym:
@@ -616,7 +616,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
let asgnExpr = defaultNodeField(c, recNode, recType)
if asgnExpr != nil:
asgnExpr.typ = recType
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
else:
doAssert false

View File

@@ -78,14 +78,18 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
if macroToExpandSym(s):
onUse(n.info, s)
result = semTemplateExpr(c, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, {}, ctx)
discard c.friendModules.pop()
else:
result = symChoice(c, n, s, scOpen)
of skMacro:
if macroToExpandSym(s):
onUse(n.info, s)
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, {}, ctx)
discard c.friendModules.pop()
else:
result = symChoice(c, n, s, scOpen)
of skGenericParam:
@@ -245,7 +249,9 @@ proc semGenericStmt(c: PContext, n: PNode,
if macroToExpand(s) and sc.safeLen <= 1:
onUse(fn.info, s)
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, flags, ctx)
discard c.friendModules.pop()
else:
n[0] = sc
result = n
@@ -254,7 +260,9 @@ proc semGenericStmt(c: PContext, n: PNode,
if macroToExpand(s) and sc.safeLen <= 1:
onUse(fn.info, s)
result = semTemplateExpr(c, n, s, {efNoSemCheck})
c.friendModules.add(s.owner.getModule)
result = semGenericStmt(c, result, flags, ctx)
discard c.friendModules.pop()
else:
n[0] = sc
result = n
@@ -493,6 +501,20 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkExprColonExpr, nkExprEqExpr:
checkMinSonsLen(n, 2, c.config)
result[1] = semGenericStmt(c, n[1], flags, ctx)
of nkObjConstr:
for i in 0..<n.len:
result[i] = semGenericStmt(c, n[i], flags, ctx)
if result[0].kind == nkSym:
let fmoduleId = getModule(result[0].sym).id
var isVisable = false
for module in c.friendModules:
if module.id == fmoduleId:
isVisable = true
break
if isVisable:
for i in 1..<result.len:
if result[i].kind == nkExprColonExpr:
result[i][1].flags.incl nfSkipFieldChecking
else:
for i in 0..<n.len:
result[i] = semGenericStmt(c, n[i], flags, ctx)

View File

@@ -76,7 +76,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
let assignment = locateFieldInInitExpr(c, field, initExpr)
if assignment != nil:
if nfSem in assignment.flags: return assignment[1]
if nfUseDefaultField in assignment[1].flags:
if nfSkipFieldChecking in assignment[1].flags:
discard
elif not fieldVisible(c, field):
localError(c.config, initExpr.info,
@@ -178,7 +178,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
newSymNode(getSysMagic(c.graph, constrCtx.initExpr.info, "zeroDefault", mZeroDefault)),
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
)
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.flags.incl nfSkipFieldChecking
asgnExpr.typ = recTyp
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)

View File

@@ -519,7 +519,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
let fSym = newSymNode(field)
if hasDefaultField:
fSym.sym.ast = a[^1]
fSym.sym.ast.flags.incl nfUseDefaultField
fSym.sym.ast.flags.incl nfSkipFieldChecking
result.n.add fSym
addSonSkipIntLit(result, typ, c.idgen)
styleCheckDef(c, a[j].info, field)
@@ -868,7 +868,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
let fSym = newSymNode(f)
if hasDefaultField:
fSym.sym.ast = n[^1]
fSym.sym.ast.flags.incl nfUseDefaultField
fSym.sym.ast.flags.incl nfSkipFieldChecking
if a.kind == nkEmpty: father.add fSym
else: a.add fSym
styleCheckDef(c, f)

View File

@@ -1829,7 +1829,7 @@ proc getNullValueAux(t: PType; obj: PNode, result: PNode; conf: ConfigRef; currP
let field = newNodeI(nkExprColonExpr, result.info)
field.add(obj)
let value = getNullValue(obj.sym.typ, result.info, conf)
value.flags.incl nfUseDefaultField
value.flags.incl nfSkipFieldChecking
field.add(value)
result.add field
doAssert obj.sym.position == currPosition

6
tests/generics/m3770.nim Normal file
View File

@@ -0,0 +1,6 @@
type
Noice* = object
hidden: int
template jjj*: Noice =
Noice(hidden: 15)

9
tests/generics/t3770.nim Normal file
View File

@@ -0,0 +1,9 @@
# bug #3770
import m3770
doAssert $jjj() == "(hidden: 15)" # works
proc someGeneric(_: type) =
doAssert $jjj() == "(hidden: 15)" # fails: "Error: the field 'hidden' is not accessible."
someGeneric(int)