From 849208d779e860230bb8682b3b356ba2942dd889 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 17 Jun 2011 01:04:33 +0200 Subject: got rid of unsound co/contravariance in procvars --- compiler/sigmatch.nim | 67 ++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'compiler') diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c9ab27123..ac1429e4e 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -189,6 +189,39 @@ proc constraintRel(mapping: var TIdTable, f, a: PType): TTypeRelation = result = isNone if f.kind == a.kind: result = isGeneric +proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = + proc inconsistentVarTypes(f, a: PType): bool {.inline.} = + result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar) + + case a.kind + of tyNil: result = isSubtype + of tyProc: + if sonsLen(f) != sonsLen(a) or f.callconv != a.callconv: return + # Note: We have to do unification for the parameters before the + # return type! + result = isEqual # start with maximum; also correct for no + # params at all + for i in countup(1, sonsLen(f)-1): + var m = typeRel(mapping, f.sons[i], a.sons[i]) + if m <= isSubtype or inconsistentVarTypes(f.sons[i], a.sons[i]): + return isNone + else: result = minRel(m, result) + if f.sons[0] != nil: + if a.sons[0] != nil: + var m = typeRel(mapping, f.sons[0], a.sons[0]) + # Subtype is sufficient for return types! + if m < isSubtype or inconsistentVarTypes(f.sons[0], a.sons[0]): + result = isNone + elif m == isSubtype: result = isConvertible + else: result = minRel(m, result) + else: + result = isNone + elif a.sons[0] != nil: + result = isNone + if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags: + result = isNone + else: nil + proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = # is a subtype of f? result = isNone @@ -316,39 +349,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = of tyNil: result = isSubtype else: nil of tyProc: - case a.kind - of tyNil: result = isSubtype - of tyProc: - if (sonsLen(f) == sonsLen(a)) and (f.callconv == a.callconv): - # Note: We have to do unification for the parameters before the - # return type! - result = isEqual # start with maximum; also correct for no - # params at all - var m: TTypeRelation - for i in countup(1, sonsLen(f) - 1): - m = typeRel(mapping, f.sons[i], a.sons[i]) - if (m == isNone) and - (typeRel(mapping, a.sons[i], f.sons[i]) == isSubtype): - # allow ``f.son`` as subtype of ``a.son``! - result = isConvertible - elif m < isSubtype: - return isNone - else: - result = minRel(m, result) - if f.sons[0] != nil: - if a.sons[0] != nil: - m = typeRel(mapping, f.sons[0], a.sons[0]) - # Subtype is sufficient for return types! - if m < isSubtype: result = isNone - elif m == isSubtype: result = isConvertible - else: result = minRel(m, result) - else: - result = isNone - elif a.sons[0] != nil: - result = isNone - if (tfNoSideEffect in f.flags) and not (tfNoSideEffect in a.flags): - result = isNone - else: nil + result = procTypeRel(mapping, f, a) of tyPointer: case a.kind of tyPointer: result = isEqual -- cgit 1.4.1-2-gfad0