mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
cleanup of in/out covariance handling
This commit is contained in:
@@ -212,8 +212,6 @@ type
|
||||
nkIteratorTy, # iterator type
|
||||
nkSharedTy, # 'shared T'
|
||||
# we use 'nkPostFix' for the 'not nil' addition
|
||||
nkInTy, # prefix `in` used to mark contravariant types
|
||||
nkOutTy, # prefix `out` used to mark covariant types
|
||||
nkEnumTy, # enum body
|
||||
nkEnumFieldDef, # `ident = expr` in an enumeration
|
||||
nkArgList, # argument list
|
||||
@@ -226,7 +224,7 @@ type
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
TSymFlag* = enum # already 32 flags!
|
||||
TSymFlag* = enum # already 33 flags!
|
||||
sfUsed, # read access of sym (for warnings) or simply used
|
||||
sfExported, # symbol is exported from module
|
||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||
@@ -270,9 +268,6 @@ type
|
||||
sfDiscardable, # returned value may be discarded implicitly
|
||||
sfOverriden, # proc is overriden
|
||||
sfGenSym # symbol is 'gensym'ed; do not add to symbol table
|
||||
sfCovariant # covariant generic param mimicing a ptr type
|
||||
sfWeakCovariant # covariant generic param mimicing a seq/array type
|
||||
sfContravariant # contravariant generic param
|
||||
|
||||
TSymFlags* = set[TSymFlag]
|
||||
|
||||
@@ -460,7 +455,7 @@ type
|
||||
nfBlockArg # this a stmtlist appearing in a call (e.g. a do block)
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 30)
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that)
|
||||
tfVarargs, # procedure has C styled varargs
|
||||
# tyArray type represeting a varargs list
|
||||
tfNoSideEffect, # procedure type does not allow side effects
|
||||
@@ -513,6 +508,9 @@ type
|
||||
tfTriggersCompileTime # uses the NimNode type which make the proc
|
||||
# implicitly '.compiletime'
|
||||
tfRefsAnonObj # used for 'ref object' and 'ptr object'
|
||||
tfCovariant # covariant generic param mimicing a ptr type
|
||||
tfWeakCovariant # covariant generic param mimicing a seq/array type
|
||||
tfContravariant # contravariant generic param
|
||||
|
||||
TTypeFlags* = set[TTypeFlag]
|
||||
|
||||
|
||||
@@ -1521,9 +1521,9 @@ proc parseGenericParam(p: var TParser): PNode =
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
of tkIn, tkOut:
|
||||
let kind = if p.tok.tokType == tkIn: nkInTy
|
||||
else: nkOutTy
|
||||
a = newNodeP(kind, p)
|
||||
let x = p.lex.cache.getIdent(if p.tok.tokType == tkIn: "in" else: "out")
|
||||
a = newNodeP(nkPrefix, p)
|
||||
a.addSon newIdentNodeP(x, p)
|
||||
getTok(p)
|
||||
expectIdent(p)
|
||||
a.addSon(parseSymbol(p))
|
||||
|
||||
@@ -758,7 +758,7 @@ proc checkCovariantParamsUsages(genericType: PType) =
|
||||
|
||||
case t.kind
|
||||
of tyGenericParam:
|
||||
t.sym.flags.incl sfWeakCovariant
|
||||
t.flags.incl tfWeakCovariant
|
||||
return true
|
||||
|
||||
of tyObject:
|
||||
@@ -783,17 +783,17 @@ proc checkCovariantParamsUsages(genericType: PType) =
|
||||
for i in 1 .. <t.len:
|
||||
let param = t[i]
|
||||
if param.kind == tyGenericParam:
|
||||
if sfCovariant in param.sym.flags:
|
||||
let formalFlags = targetBody[i-1].sym.flags
|
||||
if sfCovariant notin formalFlags:
|
||||
if tfCovariant in param.flags:
|
||||
let formalFlags = targetBody[i-1].flags
|
||||
if tfCovariant notin formalFlags:
|
||||
error("covariant param '" & param.sym.name.s &
|
||||
"' used in a non-covariant position")
|
||||
elif sfWeakCovariant in formalFlags:
|
||||
param.sym.flags.incl sfWeakCovariant
|
||||
elif tfWeakCovariant in formalFlags:
|
||||
param.flags.incl tfWeakCovariant
|
||||
result = true
|
||||
elif sfContravariant in param.sym.flags:
|
||||
elif tfContravariant in param.flags:
|
||||
let formalParam = targetBody[i-1].sym
|
||||
if sfContravariant notin formalParam.flags:
|
||||
if tfContravariant notin formalParam.typ.flags:
|
||||
error("contravariant param '" & param.sym.name.s &
|
||||
"' used in a non-contravariant position")
|
||||
result = true
|
||||
@@ -865,7 +865,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
body.sym = s
|
||||
body.size = -1 # could not be computed properly
|
||||
s.typ.sons[sonsLen(s.typ) - 1] = body
|
||||
if sfCovariant in s.flags:
|
||||
if tfCovariant in s.typ.flags:
|
||||
checkCovariantParamsUsages(s.typ)
|
||||
# XXX: This is a temporary limitation:
|
||||
# The codegen currently produces various failures with
|
||||
|
||||
@@ -1585,24 +1585,23 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
# of the parameter will be stored in the
|
||||
# attached symbol.
|
||||
var paramName = a.sons[j]
|
||||
var covarianceFlag = sfPure
|
||||
var covarianceFlag = tfUnresolved
|
||||
|
||||
if paramName.kind in {nkInTy, nkOutTy}:
|
||||
if not nimEnableCovariance or paramName.kind == nkInTy:
|
||||
if paramName.safeLen == 2:
|
||||
if not nimEnableCovariance or paramName[0].ident.s == "in":
|
||||
if father == nil or sfImportc notin father.sym.flags:
|
||||
localError(paramName.info, errInOutFlagNotExtern,
|
||||
if paramName.kind == nkInTy: "in" else: "out")
|
||||
covarianceFlag = if paramName.kind == nkInTy: sfContravariant
|
||||
else: sfCovariant
|
||||
if father != nil: father.sym.flags.incl sfCovariant
|
||||
paramName = paramName[0]
|
||||
localError(paramName.info, errInOutFlagNotExtern, paramName[0].ident.s)
|
||||
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 != sfPure: s.flags.incl(covarianceFlag)
|
||||
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
|
||||
|
||||
@@ -883,7 +883,7 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
|
||||
let body = f.base
|
||||
return body == a.base and
|
||||
a.sonsLen == 3 and
|
||||
sfWeakCovariant notin body.sons[0].sym.flags and
|
||||
tfWeakCovariant notin body.sons[0].flags and
|
||||
baseTypesCheck(f.sons[1], a.sons[1])
|
||||
else:
|
||||
return false
|
||||
@@ -1302,22 +1302,22 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
result = typeRel(c, ff, aa, nextFlags)
|
||||
if result notin {isEqual, isGeneric}:
|
||||
if trNoCovariance notin flags and ff.kind == aa.kind:
|
||||
let paramFlags = rootf.base.sons[i-1].sym.flags
|
||||
let paramFlags = rootf.base.sons[i-1].flags
|
||||
hasCovariance =
|
||||
if sfCovariant in paramFlags:
|
||||
if sfWeakCovariant in paramFlags:
|
||||
if tfCovariant in paramFlags:
|
||||
if tfWeakCovariant in paramFlags:
|
||||
isCovariantPtr(c, ff, aa)
|
||||
else:
|
||||
ff.kind notin {tyRef, tyPtr} and result == isSubtype
|
||||
else:
|
||||
sfContravariant in paramFlags and
|
||||
tfContravariant in paramFlags and
|
||||
typeRel(c, aa, ff) == isSubtype
|
||||
if hasCovariance:
|
||||
continue
|
||||
|
||||
return isNone
|
||||
if prev == nil: put(c, f, a)
|
||||
result = if hasCovariance: isGeneric else: isGeneric
|
||||
result = isGeneric
|
||||
else:
|
||||
let fKind = rootf.lastSon.kind
|
||||
if fKind in {tyAnd, tyOr}:
|
||||
|
||||
@@ -68,8 +68,6 @@ type
|
||||
nnkProcTy,
|
||||
nnkIteratorTy, # iterator type
|
||||
nnkSharedTy, # 'shared T'
|
||||
nnkInTy,
|
||||
nnkOutTy,
|
||||
nnkEnumTy,
|
||||
nnkEnumFieldDef,
|
||||
nnkArglist, nnkPattern
|
||||
|
||||
Reference in New Issue
Block a user