Skip to content

Commit

Permalink
fix #15326 (#15341)
Browse files Browse the repository at this point in the history
  • Loading branch information
cooldome authored Sep 16, 2020
1 parent 913ffbb commit d938c64
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 59 deletions.
126 changes: 67 additions & 59 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2055,72 +2055,80 @@ proc semGenericConstraints(c: PContext, x: PType): PType =
result = newTypeWithSons(c, tyGenericParam, @[x])

proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =

template addSym(result: PNode, s: PSym): untyped =
if father != nil: addSonSkipIntLit(father, s.typ)
if sfGenSym notin s.flags: addDecl(c, s)
result.add newSymNode(s)

result = copyNode(n)
if n.kind != nkGenericParams:
illFormedAst(n, c.config)
return
for i in 0..<n.len:
var a = n[i]
if a.kind != nkIdentDefs: illFormedAst(n, c.config)
var def = a[^1]
let constraint = a[^2]
var typ: PType
var a = n[i]
case a.kind
of nkSym: result.addSym(a.sym)
of nkIdentDefs:
var def = a[^1]
let constraint = a[^2]
var typ: PType

if constraint.kind != nkEmpty:
typ = semTypeNode(c, constraint, nil)
if typ.kind != tyStatic or typ.len == 0:
if typ.kind == tyTypeDesc:
if typ[0].kind == tyNone:
typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
incl typ.flags, tfCheckedForDestructor
else:
typ = semGenericConstraints(c, typ)

if constraint.kind != nkEmpty:
typ = semTypeNode(c, constraint, nil)
if typ.kind != tyStatic or typ.len == 0:
if typ.kind == tyTypeDesc:
if typ[0].kind == tyNone:
typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
incl typ.flags, tfCheckedForDestructor
if def.kind != nkEmpty:
def = semConstExpr(c, def)
if typ == nil:
if def.typ.kind != tyTypeDesc:
typ = newTypeWithSons(c, tyStatic, @[def.typ])
else:
typ = semGenericConstraints(c, typ)
# the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]``
# from manyloc/named_argument_bug/triengine:
def.typ = def.typ.skipTypes({tyTypeDesc})
if not containsGenericType(def.typ):
def = fitNode(c, typ, def, def.info)

if def.kind != nkEmpty:
def = semConstExpr(c, def)
if typ == nil:
if def.typ.kind != tyTypeDesc:
typ = newTypeWithSons(c, tyStatic, @[def.typ])
else:
# the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]``
# from manyloc/named_argument_bug/triengine:
def.typ = def.typ.skipTypes({tyTypeDesc})
if not containsGenericType(def.typ):
def = fitNode(c, typ, def, def.info)

if typ == nil:
typ = newTypeS(tyGenericParam, c)
if father == nil: typ.flags.incl tfWildcard

typ.flags.incl tfGenericTypeParam
typ = newTypeS(tyGenericParam, c)
if father == nil: typ.flags.incl tfWildcard

typ.flags.incl tfGenericTypeParam

for j in 0..<a.len-2:
let finalType = if j == 0: typ
else: copyType(typ, typ.owner, false)
# it's important the we create an unique
# type for each generic param. the index
# of the parameter will be stored in the
# attached symbol.
var paramName = a[j]
var covarianceFlag = tfUnresolved

if paramName.safeLen == 2:
if not nimEnableCovariance or paramName[0].ident.s == "in":
if father == nil or sfImportc notin father.sym.flags:
localError(c.config, paramName.info, errInOutFlagNotExtern % $paramName[0])
covarianceFlag = if paramName[0].ident.s == "in": tfContravariant
else: tfCovariant
if father != nil: father.flags.incl tfCovariant
paramName = paramName[1]

var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
newSymG(skGenericParam, paramName, c).linkTo(finalType)
else:
newSymG(skType, paramName, c).linkTo(finalType)

for j in 0..<a.len-2:
let finalType = if j == 0: typ
else: copyType(typ, typ.owner, false)
# it's important the we create an unique
# type for each generic param. the index
# of the parameter will be stored in the
# attached symbol.
var paramName = a[j]
var covarianceFlag = tfUnresolved

if paramName.safeLen == 2:
if not nimEnableCovariance or paramName[0].ident.s == "in":
if father == nil or sfImportc notin father.sym.flags:
localError(c.config, paramName.info, errInOutFlagNotExtern % $paramName[0])
covarianceFlag = if paramName[0].ident.s == "in": tfContravariant
else: tfCovariant
if father != nil: father.flags.incl tfCovariant
paramName = paramName[1]

var s = if finalType.kind == tyStatic or tfWildcard in typ.flags:
newSymG(skGenericParam, paramName, c).linkTo(finalType)
else:
newSymG(skType, paramName, c).linkTo(finalType)

if covarianceFlag != tfUnresolved: s.typ.flags.incl(covarianceFlag)
if def.kind != nkEmpty: s.ast = def
if father != nil: addSonSkipIntLit(father, s.typ)
s.position = result.len
result.add newSymNode(s)
if sfGenSym notin s.flags: addDecl(c, s)
if covarianceFlag != tfUnresolved: s.typ.flags.incl(covarianceFlag)
if def.kind != nkEmpty: s.ast = def
s.position = result.len
result.addSym(s)
else:
illFormedAst(n, c.config)
8 changes: 8 additions & 0 deletions tests/macros/tmacro2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ const t = mac("HEllo World")
echo s, " ", t


#-----------------------------------------------------------------------------
# issue #15326
macro m(n:typed):auto =
result = n

proc f[T](x:T): T {.m.} = x

discard f(3)

0 comments on commit d938c64

Please sign in to comment.