Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix sym of created generic instantiation type #22642

Merged
merged 5 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,18 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
# One step is enough, because the recursive nature of
# handleGenericInvocation will handle the alias-to-alias-to-alias case
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias

let origSym = newbody.sym
if origSym != nil and sfFromGeneric notin origSym.flags:
# same as `replaceTypeVarsS` but directly set the type without recursion:
newbody.sym = copySym(origSym, cl.c.idgen)
incl(newbody.sym.flags, sfFromGeneric)
newbody.sym.owner = origSym.owner
newbody.sym.typ = newbody
# unfortunately calling `replaceTypeVarsN` causes recursion, so this AST
# is the original generic body AST
newbody.sym.ast = copyTree(origSym.ast)

rawAddSon(result, newbody)
checkPartialConstructedType(cl.c.config, cl.info, newbody)
if not cl.allowMetaTypes:
Expand Down
12 changes: 10 additions & 2 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -505,18 +505,26 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
if r.kind == tyObject and ptrs <= 1: result = r
else: result = nil

proc getObjectSym(t: PType): PSym =
if tfFromGeneric in t.flags and t.typeInst.kind == tyGenericInst:
var dummy: SkippedPtr
result = t.typeInst[0].skipToObject(dummy).sym
else:
result = t.sym

proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType): bool =
assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
var askip = skippedNone
var fskip = skippedNone
var t = a.skipToObject(askip)
let r = f.skipToObject(fskip)
if r == nil: return false
let rSym = getObjectSym(r)
var depth = 0
var last = a
# XXX sameObjectType can return false here. Need to investigate
# why that is but sameObjectType does way too much work here anyway.
while t != nil and r.sym != t.sym and askip == fskip:
while t != nil and rSym != getObjectSym(t) and askip == fskip:
t = t[0]
if t == nil: break
last = t
Expand Down Expand Up @@ -1602,7 +1610,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# crossing path with metatypes/aliases, so we need to separate them
# by checking sym.id
let genericSubtype = isGenericSubtype(c, x, f, depth, f)
if not (genericSubtype and aobj.sym.id != fobj.sym.id) and aOrig.kind != tyGenericBody:
if not (genericSubtype and getObjectSym(aobj).id != getObjectSym(fobj).id) and aOrig.kind != tyGenericBody:
depth = -1

if depth >= 0:
Expand Down
6 changes: 2 additions & 4 deletions compiler/suggest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,8 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} =
for module in c.friendModules:
if fmoduleId == module.id: return true
if f.kind == skField:
var symObj = f.owner
if symObj.typ.skipTypes({tyGenericBody, tyGenericInst, tyGenericInvocation, tyAlias}).kind in {tyRef, tyPtr}:
symObj = symObj.typ.toObjectFromRefPtrGeneric.sym
assert symObj != nil
var symObj = f.owner.typ.toObjectFromRefPtrGeneric.sym
assert symObj != nil
for scope in allScopes(c.currentScope):
for sym in scope.allowPrivateAccess:
if symObj.id == sym.id: return true
Expand Down
39 changes: 35 additions & 4 deletions tests/generics/timpl_ast.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
discard """
action: compile
"""

import std/macros
import std/assertions

Expand Down Expand Up @@ -47,3 +43,38 @@ block: # issues #9899, ##14708
macro parse(s: static string) =
result = parseStmt(s)
parse("type " & implRepr(Option))

block: # issue #22639
type
Spectrum[N: static int] = object
data: array[N, float]
AngleInterpolator = object
data: seq[Spectrum[60]]
proc initInterpolator(num: int): AngleInterpolator =
result = AngleInterpolator()
for i in 0 ..< num:
result.data.add Spectrum[60]()
macro genCompatibleTuple(t: typed): untyped =
let typ = t.getType[1].getTypeImpl[2]
result = nnkTupleTy.newTree()
for i, ch in typ: # is `nnkObjectTy`
result.add nnkIdentDefs.newTree(ident(ch[0].strVal), # ch is `nnkIdentDefs`
ch[1],
newEmptyNode())
proc fullSize[T: object | tuple](x: T): int =
var tmp: genCompatibleTuple(T)
result = 0
for field, val in fieldPairs(x):
result += sizeof(val)
doAssert result == sizeof(tmp)

let reflectivity = initInterpolator(1)
for el in reflectivity.data:
doAssert fullSize(el) == sizeof(el)
doAssert fullSize(reflectivity.data[0]) == sizeof(reflectivity.data[0])
doAssert genCompatibleTuple(Spectrum[60]) is tuple[data: array[60, float]]
doAssert genCompatibleTuple(Spectrum[120]) is tuple[data: array[120, float]]
type Foo[T] = object
data: T
doAssert genCompatibleTuple(Foo[int]) is tuple[data: int]
doAssert genCompatibleTuple(Foo[float]) is tuple[data: float]