fixes #267
This commit is contained in:
parent
c093139494
commit
7fccdedcb5
5 changed files with 192 additions and 105 deletions
|
|
@ -365,12 +365,8 @@ type
|
||||||
tfFromGeneric, # type is an instantiation of a generic; this is needed
|
tfFromGeneric, # type is an instantiation of a generic; this is needed
|
||||||
# because for instantiations of objects, structural
|
# because for instantiations of objects, structural
|
||||||
# type equality has to be used
|
# type equality has to be used
|
||||||
tfInstantiated, # XXX: used to mark generic params after instantiation.
|
tfUnresolved, # marks unresolved typedesc params: e.g.
|
||||||
# if the concrete type happens to be an implicit generic
|
# proc foo(T: typedesc, list: seq[T]): var T
|
||||||
# this can lead to invalid proc signatures in the second
|
|
||||||
# pass of semProcTypeNode performed after instantiation.
|
|
||||||
# this won't be needed if we don't perform this redundant
|
|
||||||
# second pass (stay tuned).
|
|
||||||
tfRetType, # marks return types in proc (used to detect type classes
|
tfRetType, # marks return types in proc (used to detect type classes
|
||||||
# used as return types for return type inference)
|
# used as return types for return type inference)
|
||||||
tfAll, # type class requires all constraints to be met (default)
|
tfAll, # type class requires all constraints to be met (default)
|
||||||
|
|
@ -1045,7 +1041,6 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
|
||||||
if keepId:
|
if keepId:
|
||||||
result.id = t.id
|
result.id = t.id
|
||||||
else:
|
else:
|
||||||
result.id = getID()
|
|
||||||
when debugIds: RegisterId(result)
|
when debugIds: RegisterId(result)
|
||||||
result.sym = t.sym # backend-info should not be copied
|
result.sym = t.sym # backend-info should not be copied
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,11 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
|
||||||
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
||||||
result = newType(kind, getCurrOwner())
|
result = newType(kind, getCurrOwner())
|
||||||
|
|
||||||
|
proc newTypeWithSons*(c: PContext, kind: TTypeKind,
|
||||||
|
sons: seq[PType]): PType =
|
||||||
|
result = newType(kind, getCurrOwner())
|
||||||
|
result.sons = sons
|
||||||
|
|
||||||
proc errorType*(c: PContext): PType =
|
proc errorType*(c: PContext): PType =
|
||||||
## creates a type representing an error state
|
## creates a type representing an error state
|
||||||
result = newTypeS(tyError, c)
|
result = newTypeS(tyError, c)
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
||||||
#t = instGenericContainer(c, a, t)
|
#t = instGenericContainer(c, a, t)
|
||||||
t = generateTypeInstance(c, pt, a, t)
|
t = generateTypeInstance(c, pt, a, t)
|
||||||
#t = ReplaceTypeVarsT(cl, t)
|
#t = ReplaceTypeVarsT(cl, t)
|
||||||
t.flags.incl tfInstantiated
|
|
||||||
s.typ = t
|
s.typ = t
|
||||||
addDecl(c, s)
|
addDecl(c, s)
|
||||||
entry.concreteTypes[i] = t
|
entry.concreteTypes[i] = t
|
||||||
|
|
@ -84,11 +83,28 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
|
||||||
else:
|
else:
|
||||||
for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)
|
for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)
|
||||||
|
|
||||||
|
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind)
|
||||||
|
|
||||||
proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
||||||
if n.sons[bodyPos].kind != nkEmpty:
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
# add it here, so that recursive generic procs are possible:
|
# add it here, so that recursive generic procs are possible:
|
||||||
addDecl(c, result)
|
addDecl(c, result)
|
||||||
pushProcCon(c, result)
|
pushProcCon(c, result)
|
||||||
|
# add params to scope
|
||||||
|
let origFormalParams = result.typ.n
|
||||||
|
result.typ.n = newNodeI(nkFormalParams,
|
||||||
|
origFormalParams.info,
|
||||||
|
origFormalParams.len)
|
||||||
|
result.typ.n.sons[0] = copyNode(origFormalParams.sons[0])
|
||||||
|
for i in 1 .. <result.typ.len:
|
||||||
|
let origParam = origFormalParams[i].sym
|
||||||
|
var param = copySym(origParam)
|
||||||
|
result.typ.n.sons[i] = newSymNode(param)
|
||||||
|
param.typ = result.typ.sons[i]
|
||||||
|
param.ast = origParam.ast
|
||||||
|
param.owner = result
|
||||||
|
addParamOrResult(c, param, result.kind)
|
||||||
|
# debug result.typ.n
|
||||||
maybeAddResult(c, result, n)
|
maybeAddResult(c, result, n)
|
||||||
var b = n.sons[bodyPos]
|
var b = n.sons[bodyPos]
|
||||||
var symMap: TIdTable
|
var symMap: TIdTable
|
||||||
|
|
@ -123,6 +139,70 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
|
||||||
s.ast.sons[genericParamsPos].kind == nkEmpty:
|
s.ast.sons[genericParamsPos].kind == nkEmpty:
|
||||||
c.threadEntries.add(s)
|
c.threadEntries.add(s)
|
||||||
|
|
||||||
|
proc instGenericContainer(c: PContext, info: TLineInfo, header: PType): PType =
|
||||||
|
var cl: TReplTypeVars
|
||||||
|
InitIdTable(cl.symMap)
|
||||||
|
InitIdTable(cl.typeMap)
|
||||||
|
cl.info = info
|
||||||
|
cl.c = c
|
||||||
|
result = ReplaceTypeVarsT(cl, header)
|
||||||
|
|
||||||
|
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||||
|
result = instGenericContainer(c, n.info, header)
|
||||||
|
|
||||||
|
proc fixupProcTypeR(c: PContext, genericType: PType,
|
||||||
|
inst: TInstantiation): PType =
|
||||||
|
result = genericType
|
||||||
|
if result == nil: return
|
||||||
|
|
||||||
|
case genericType.kind
|
||||||
|
of tyGenericParam, tyTypeClass:
|
||||||
|
result = inst.concreteTypes[genericType.sym.position]
|
||||||
|
of tyTypeDesc:
|
||||||
|
result = inst.concreteTypes[genericType.sym.position]
|
||||||
|
if tfUnresolved in genericType.flags:
|
||||||
|
result = result.sons[0]
|
||||||
|
of tyExpr:
|
||||||
|
result = inst.concreteTypes[genericType.sym.position]
|
||||||
|
of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc,
|
||||||
|
tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs:
|
||||||
|
if genericType.sons == nil: return
|
||||||
|
for i in 0 .. <genericType.sons.len:
|
||||||
|
let changed = fixupProcTypeR(c, genericType.sons[i], inst)
|
||||||
|
if changed != genericType.sons[i]:
|
||||||
|
if result == genericType:
|
||||||
|
# the first detected change initializes the result
|
||||||
|
result = copyType(genericType, genericType.owner, true)
|
||||||
|
if genericType.n != nil:
|
||||||
|
result.n = copyTree(genericType.n)
|
||||||
|
result.sons[i] = changed
|
||||||
|
if result.n != nil:
|
||||||
|
if result.n.kind == nkRecList:
|
||||||
|
result.n.sons[i].typ = changed
|
||||||
|
if result.n.kind == nkFormalParams:
|
||||||
|
if i == 0:
|
||||||
|
nil
|
||||||
|
else:
|
||||||
|
let origParam = result.n.sons[i].sym
|
||||||
|
var param = copySym(origParam)
|
||||||
|
param.typ = changed
|
||||||
|
param.ast = origParam.ast
|
||||||
|
result.n.sons[i] = newSymNode(param)
|
||||||
|
|
||||||
|
of tyGenericInvokation:
|
||||||
|
result = newTypeWithSons(c, tyGenericInvokation, genericType.sons)
|
||||||
|
for i in 1 .. <genericType.sons.len:
|
||||||
|
result.sons[i] = fixupProcTypeR(c, result.sons[i], inst)
|
||||||
|
result = instGenericContainer(c, getInfoContext(-1), result)
|
||||||
|
else:
|
||||||
|
nil
|
||||||
|
|
||||||
|
proc fixupProcType(c: PContext, genericType: PType,
|
||||||
|
inst: TInstantiation): PType =
|
||||||
|
result = copyType(genericType, genericType.owner, false)
|
||||||
|
for i in 0 .. <result.sons.len:
|
||||||
|
result.sons[i] = fixupProcTypeR(c, result.sons[i], inst)
|
||||||
|
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
# no need to instantiate generic templates/macros:
|
# no need to instantiate generic templates/macros:
|
||||||
|
|
@ -152,16 +232,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
var entry = TInstantiation.new
|
var entry = TInstantiation.new
|
||||||
entry.sym = result
|
entry.sym = result
|
||||||
instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
|
instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
|
||||||
|
result.typ = fixupProcType(c, fn.typ, entry[])
|
||||||
n.sons[genericParamsPos] = ast.emptyNode
|
n.sons[genericParamsPos] = ast.emptyNode
|
||||||
# semantic checking for the parameters:
|
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
|
||||||
removeDefaultParamValues(n.sons[ParamsPos])
|
|
||||||
semParamList(c, n.sons[ParamsPos], nil, result)
|
|
||||||
else:
|
|
||||||
result.typ = newTypeS(tyProc, c)
|
|
||||||
rawAddSon(result.typ, nil)
|
|
||||||
result.typ.callConv = fn.typ.callConv
|
|
||||||
if result.kind == skIterator: result.typ.flags.incl(tfIterator)
|
|
||||||
var oldPrc = GenericCacheGet(fn, entry[])
|
var oldPrc = GenericCacheGet(fn, entry[])
|
||||||
if oldPrc == nil:
|
if oldPrc == nil:
|
||||||
fn.procInstCache.safeAdd(entry)
|
fn.procInstCache.safeAdd(entry)
|
||||||
|
|
@ -183,11 +255,4 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
dec(c.InstCounter)
|
dec(c.InstCounter)
|
||||||
if result.kind == skMethod: finishMethod(c, result)
|
if result.kind == skMethod: finishMethod(c, result)
|
||||||
|
|
||||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
|
||||||
var cl: TReplTypeVars
|
|
||||||
InitIdTable(cl.symMap)
|
|
||||||
InitIdTable(cl.typeMap)
|
|
||||||
cl.info = n.info
|
|
||||||
cl.c = c
|
|
||||||
result = ReplaceTypeVarsT(cl, header)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,9 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
if result.typ.sym == nil:
|
if result.typ.sym == nil:
|
||||||
LocalError(n.info, errTypeExpected)
|
LocalError(n.info, errTypeExpected)
|
||||||
return errorSym(c, n)
|
return errorSym(c, n)
|
||||||
return result.typ.sym
|
result = result.typ.sym.copySym
|
||||||
|
result.typ = copyType(result.typ, result.typ.owner, true)
|
||||||
|
result.typ.flags.incl tfUnresolved
|
||||||
if result.kind != skType:
|
if result.kind != skType:
|
||||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||||
var ov: TOverloadIter
|
var ov: TOverloadIter
|
||||||
|
|
@ -573,82 +575,96 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||||
else:
|
else:
|
||||||
if sfGenSym notin param.flags: addDecl(c, param)
|
if sfGenSym notin param.flags: addDecl(c, param)
|
||||||
|
|
||||||
proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
|
|
||||||
tuple[typ: PType, id: PIdent] =
|
|
||||||
# if typ is not-nil, the param should be turned into a generic param
|
|
||||||
# if id is not nil, the generic param will bind just once (see below)
|
|
||||||
case paramType.kind:
|
|
||||||
of tyExpr:
|
|
||||||
if paramType.sonsLen == 0:
|
|
||||||
# proc(a, b: expr)
|
|
||||||
# no constraints, treat like generic param
|
|
||||||
result.typ = newTypeS(tyGenericParam, c)
|
|
||||||
else:
|
|
||||||
# proc(a: expr{string}, b: expr{nkLambda})
|
|
||||||
# overload on compile time values and AST trees
|
|
||||||
result.typ = newTypeS(tyExpr, c)
|
|
||||||
result.typ.sons = paramType.sons
|
|
||||||
of tyTypeDesc:
|
|
||||||
if tfInstantiated notin paramType.flags:
|
|
||||||
result.typ = newTypeS(tyTypeDesc, c)
|
|
||||||
result.typ.sons = paramType.sons
|
|
||||||
of tyDistinct:
|
|
||||||
result = paramTypeClass(c, paramType.lastSon, procKind)
|
|
||||||
# disable the bindOnce behavior for the type class
|
|
||||||
result.id = nil
|
|
||||||
return
|
|
||||||
of tyGenericBody:
|
|
||||||
# type Foo[T] = object
|
|
||||||
# proc x(a: Foo, b: Foo)
|
|
||||||
result.typ = newTypeS(tyTypeClass, c)
|
|
||||||
result.typ.addSonSkipIntLit(paramType)
|
|
||||||
of tyTypeClass:
|
|
||||||
result.typ = copyType(paramType, getCurrOwner(), false)
|
|
||||||
else: nil
|
|
||||||
# bindOnce by default
|
|
||||||
if paramType.sym != nil: result.id = paramType.sym.name
|
|
||||||
|
|
||||||
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
paramType: PType, paramName: string,
|
paramType: PType, paramName: string,
|
||||||
info: TLineInfo): PType =
|
info: TLineInfo, anon = false): PType =
|
||||||
result = paramType
|
|
||||||
if procKind in {skMacro, skTemplate}:
|
if procKind in {skMacro, skTemplate}:
|
||||||
# generic param types in macros and templates affect overload
|
# generic param types in macros and templates affect overload
|
||||||
# resolution, but don't work as generic params when it comes
|
# resolution, but don't work as generic params when it comes
|
||||||
# to proc instantiation. We don't need to lift such params here.
|
# to proc instantiation. We don't need to lift such params here.
|
||||||
return
|
return
|
||||||
## Params having implicit generic types or pseudo types such as 'expr'
|
|
||||||
## need to be added to the generic params lists.
|
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
||||||
## 'expr' is different from 'expr{string}' so we must first call
|
let finalTypId = if typId != nil: typId
|
||||||
## paramTypeClass to get the actual type we are going to use.
|
else: getIdent(paramName & ":type")
|
||||||
var (typeClass, paramTypId) = paramTypeClass(c, paramType, procKind)
|
|
||||||
let isAnon = paramTypId == nil
|
|
||||||
if typeClass != nil:
|
|
||||||
if isAnon: paramTypId = getIdent(paramName & ":type")
|
|
||||||
if genericParams == nil:
|
|
||||||
# genericParams is nil when the proc is being instantiated
|
|
||||||
# the resolved type will be in scope then
|
|
||||||
let s = searchInScopes(c, paramTypId)
|
|
||||||
# tests/run/tinterf triggers this:
|
|
||||||
if s != nil: result = s.typ
|
|
||||||
else:
|
|
||||||
LocalError(info, errCannotInstantiateX, paramName)
|
|
||||||
result = errorType(c)
|
|
||||||
else:
|
|
||||||
block addImplicitGeneric:
|
|
||||||
# is this a bindOnce type class already present in the param list?
|
# is this a bindOnce type class already present in the param list?
|
||||||
for i in countup(0, genericParams.len - 1):
|
for i in countup(0, genericParams.len - 1):
|
||||||
if genericParams.sons[i].sym.name.id == paramTypId.id:
|
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||||
result = genericParams.sons[i].typ
|
return genericParams.sons[i].typ
|
||||||
break addImplicitGeneric
|
|
||||||
|
|
||||||
var s = newSym(skType, paramTypId, getCurrOwner(), info)
|
var s = newSym(skType, finalTypId, getCurrOwner(), info)
|
||||||
if isAnon: s.flags.incl(sfAnon)
|
if typId == nil: s.flags.incl(sfAnon)
|
||||||
s.linkTo(typeClass)
|
s.linkTo(typeClass)
|
||||||
s.position = genericParams.len
|
s.position = genericParams.len
|
||||||
genericParams.addSon(newSymNode(s))
|
genericParams.addSon(newSymNode(s))
|
||||||
result = typeClass
|
result = typeClass
|
||||||
|
|
||||||
|
# XXX: There are codegen errors if this is turned into a nested proc
|
||||||
|
template liftingWalk(typ: PType, anonFlag = false): expr =
|
||||||
|
liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
|
||||||
|
#proc liftingWalk(paramType: PType, anon = false): PType =
|
||||||
|
|
||||||
|
var paramTypId = if not anon and paramType.sym != nil: paramType.sym.name
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
template addImplicitGeneric(e: expr): expr =
|
||||||
|
addImplicitGenericImpl(e, paramTypId)
|
||||||
|
|
||||||
|
case paramType.kind:
|
||||||
|
of tyExpr:
|
||||||
|
if paramType.sonsLen == 0:
|
||||||
|
# proc(a, b: expr)
|
||||||
|
# no constraints, treat like generic param
|
||||||
|
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||||
|
else:
|
||||||
|
# proc(a: expr{string}, b: expr{nkLambda})
|
||||||
|
# overload on compile time values and AST trees
|
||||||
|
result = addImplicitGeneric(c.newTypeWithSons(tyExpr, paramType.sons))
|
||||||
|
of tyTypeDesc:
|
||||||
|
if tfUnresolved notin paramType.flags:
|
||||||
|
result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons))
|
||||||
|
of tyDistinct:
|
||||||
|
if paramType.sonsLen == 1:
|
||||||
|
# disable the bindOnce behavior for the type class
|
||||||
|
result = liftingWalk(paramType.sons[0], true)
|
||||||
|
of tySequence, tySet, tyArray, tyOpenArray:
|
||||||
|
# XXX: this is a bit strange, but proc(s: seq)
|
||||||
|
# produces tySequence(tyGenericParam, null).
|
||||||
|
# This also seems to be true when creating aliases
|
||||||
|
# like: type myseq = distinct seq.
|
||||||
|
# Maybe there is another better place to associate
|
||||||
|
# the seq type class with the seq identifier.
|
||||||
|
if paramType.lastSon == nil:
|
||||||
|
let typ = c.newTypeWithSons(tyTypeClass, @[newTypeS(paramType.kind, c)])
|
||||||
|
result = addImplicitGeneric(typ)
|
||||||
|
else:
|
||||||
|
for i in 0 .. <paramType.sons.len:
|
||||||
|
var lifted = liftingWalk(paramType.sons[i])
|
||||||
|
if lifted != nil:
|
||||||
|
paramType.sons[i] = lifted
|
||||||
|
result = paramType
|
||||||
|
of tyGenericBody:
|
||||||
|
# type Foo[T] = object
|
||||||
|
# proc x(a: Foo, b: Foo)
|
||||||
|
var typ = newTypeS(tyTypeClass, c)
|
||||||
|
typ.addSonSkipIntLit(paramType)
|
||||||
|
result = addImplicitGeneric(typ)
|
||||||
|
of tyGenericInst:
|
||||||
|
for i in 1 .. (paramType.sons.len - 2):
|
||||||
|
var lifted = liftingWalk(paramType.sons[i])
|
||||||
|
if lifted != nil:
|
||||||
|
paramType.sons[i] = lifted
|
||||||
|
result = paramType
|
||||||
|
|
||||||
|
if result != nil:
|
||||||
|
result.kind = tyGenericInvokation
|
||||||
|
result.sons.setLen(result.sons.len - 1)
|
||||||
|
of tyTypeClass:
|
||||||
|
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false))
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
# result = liftingWalk(paramType)
|
||||||
|
|
||||||
proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
|
proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
|
||||||
if n.kind == nkCurlyExpr:
|
if n.kind == nkCurlyExpr:
|
||||||
result = semTypeNode(c, n.sons[0], nil)
|
result = semTypeNode(c, n.sons[0], nil)
|
||||||
|
|
@ -686,7 +702,6 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
length = sonsLen(a)
|
length = sonsLen(a)
|
||||||
hasType = a.sons[length-2].kind != nkEmpty
|
hasType = a.sons[length-2].kind != nkEmpty
|
||||||
hasDefault = a.sons[length-1].kind != nkEmpty
|
hasDefault = a.sons[length-1].kind != nkEmpty
|
||||||
|
|
||||||
if hasType:
|
if hasType:
|
||||||
typ = semParamType(c, a.sons[length-2], constraint)
|
typ = semParamType(c, a.sons[length-2], constraint)
|
||||||
|
|
||||||
|
|
@ -707,8 +722,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
||||||
for j in countup(0, length-3):
|
for j in countup(0, length-3):
|
||||||
var arg = newSymG(skParam, a.sons[j], c)
|
var arg = newSymG(skParam, a.sons[j], c)
|
||||||
var finalType = liftParamType(c, kind, genericParams, typ,
|
let lifted = liftParamType(c, kind, genericParams, typ,
|
||||||
arg.name.s, arg.info).skipIntLit
|
arg.name.s, arg.info)
|
||||||
|
let finalType = if lifted != nil: lifted else: typ.skipIntLit
|
||||||
arg.typ = finalType
|
arg.typ = finalType
|
||||||
arg.position = counter
|
arg.position = counter
|
||||||
arg.constraint = constraint
|
arg.constraint = constraint
|
||||||
|
|
@ -726,7 +742,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
# compiler only checks for 'nil':
|
# compiler only checks for 'nil':
|
||||||
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
||||||
if r.sym == nil or sfAnon notin r.sym.flags:
|
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||||
r = liftParamType(c, kind, genericParams, r, "result", n.sons[0].info)
|
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
||||||
|
n.sons[0].info)
|
||||||
|
if lifted != nil: r = lifted
|
||||||
r.flags.incl tfRetType
|
r.flags.incl tfRetType
|
||||||
result.sons[0] = skipIntLit(r)
|
result.sons[0] = skipIntLit(r)
|
||||||
res.typ = result.sons[0]
|
res.typ = result.sons[0]
|
||||||
|
|
@ -1012,6 +1030,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
if n.kind != nkGenericParams:
|
if n.kind != nkGenericParams:
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
return
|
return
|
||||||
|
var position = 0
|
||||||
for i in countup(0, sonsLen(n)-1):
|
for i in countup(0, sonsLen(n)-1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind != nkIdentDefs: illFormedAst(n)
|
if a.kind != nkIdentDefs: illFormedAst(n)
|
||||||
|
|
@ -1049,6 +1068,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||||
if def.kind != nkEmpty: s.ast = def
|
if def.kind != nkEmpty: s.ast = def
|
||||||
s.typ.sym = s
|
s.typ.sym = s
|
||||||
if father != nil: addSonSkipIntLit(father, s.typ)
|
if father != nil: addSonSkipIntLit(father, s.typ)
|
||||||
s.position = i
|
s.position = position
|
||||||
|
inc position
|
||||||
addSon(result, newSymNode(s))
|
addSon(result, newSymNode(s))
|
||||||
if sfGenSym notin s.flags: addDecl(c, s)
|
if sfGenSym notin s.flags: addDecl(c, s)
|
||||||
|
|
|
||||||
|
|
@ -982,6 +982,8 @@ proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool =
|
||||||
# if the loop finished without returning, either all constraints matched
|
# if the loop finished without returning, either all constraints matched
|
||||||
# or none of them matched.
|
# or none of them matched.
|
||||||
result = if tfAny in typeClass.flags: false else: true
|
result = if tfAny in typeClass.flags: false else: true
|
||||||
|
if result == true:
|
||||||
|
IdTablePut(bindings, typeClass, t)
|
||||||
|
|
||||||
proc matchTypeClass*(typeClass, typ: PType): bool =
|
proc matchTypeClass*(typeClass, typ: PType): bool =
|
||||||
var bindings: TIdTable
|
var bindings: TIdTable
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue