diff options
author | Araq <rumpf_a@web.de> | 2015-01-21 12:58:18 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-01-23 00:36:56 +0100 |
commit | 5ae8689b63526e4e898aa08a69c0107662a7349d (patch) | |
tree | 07d385d968976b1315ef730b37e27043f5813bea | |
parent | db4d315cf4f551954ef83067fa967b6a3ef9babb (diff) | |
download | Nim-5ae8689b63526e4e898aa08a69c0107662a7349d.tar.gz |
better error message for 'invalid type'
-rw-r--r-- | compiler/sem.nim | 10 | ||||
-rw-r--r-- | compiler/semexprs.nim | 6 | ||||
-rw-r--r-- | compiler/semstmts.nim | 7 | ||||
-rw-r--r-- | compiler/types.nim | 101 | ||||
-rw-r--r-- | tests/generics/tgeneric_inheritance.nim | 2 |
5 files changed, 67 insertions, 59 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim index 9ac7ad139..5e7ce6bb7 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -175,9 +175,15 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym proc semStmtScope(c: PContext, n: PNode): PNode +proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) = + let t = typeAllowed(typ, kind) + if t != nil: + if t == typ: localError(info, "invalid type: " & typeToString(typ)) + else: localError(info, "invalid type: " & typeToString(t) & + " in this context: " & typeToString(typ)) + proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} = - if not typeAllowed(typ, skConst): - localError(typ.n.info, errXisNoType, typeToString(typ)) + typeAllowedCheck(typ.n.info, typ, skConst) proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9d9a5a50c..8221ed372 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -214,9 +214,9 @@ proc isCastable(dst, src: PType): bool = result = false elif srcSize < 0: result = false - elif not typeAllowed(dst, skParam): + elif typeAllowed(dst, skParam) != nil: result = false - else: + else: result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) @@ -692,7 +692,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine: return - if n.typ != nil and not typeAllowed(n.typ, skConst): return + if n.typ != nil and typeAllowed(n.typ, skConst) != nil: return var call = newNodeIT(nkCall, n.info, n.typ) call.add(n.sons[0]) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3b90337e5..fe12d9610 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -380,8 +380,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = # this can only happen for errornous var statements: if typ == nil: continue - if not typeAllowed(typ, symkind): - localError(a.info, errXisNoType, typeToString(typ)) + typeAllowedCheck(a.info, typ, symkind) var tup = skipTypes(typ, {tyGenericInst}) if a.kind == nkVarTuple: if tup.kind != tyTuple: @@ -456,7 +455,7 @@ proc semConst(c: PContext, n: PNode): PNode = if typ == nil: localError(a.sons[2].info, errConstExprExpected) continue - if not typeAllowed(typ, skConst) and def.kind != nkNilLit: + if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit: localError(a.info, errXisNoType, typeToString(typ)) continue v.typ = typ @@ -1187,6 +1186,8 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode = else: discard proc semStaticStmt(c: PContext, n: PNode): PNode = + #echo "semStaticStmt" + #writeStackTrace() let a = semStmt(c, n.sons[0]) n.sons[0] = a evalStaticStmt(c.module, a, c.p.owner) diff --git a/compiler/types.nim b/compiler/types.nim index e7841a9ab..78d390f13 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -85,8 +85,6 @@ proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult # this does a complex analysis whether a call to ``objectInit`` needs to be # made or intializing of the type field suffices or if there is no type field # at all in this type. -proc typeAllowed*(t: PType, kind: TSymKind): bool -# implementation proc invalidGenericInst(f: PType): bool = result = f.kind == tyGenericInst and lastSon(f) == nil @@ -1027,22 +1025,21 @@ type TTypeAllowedFlags = set[TTypeAllowedFlag] proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool + flags: TTypeAllowedFlags = {}): PType proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool = - result = true + flags: TTypeAllowedFlags = {}): PType = if n != nil: result = typeAllowedAux(marker, n.typ, kind, flags) #if not result: debug(n.typ) - if result: + if result == nil: case n.kind of nkNone..nkNilLit: discard - else: - for i in countup(0, sonsLen(n) - 1): + else: + for i in countup(0, sonsLen(n) - 1): result = typeAllowedNode(marker, n.sons[i], kind, flags) - if not result: break + if result != nil: break proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], last: TTypeKind): bool = @@ -1054,84 +1051,88 @@ proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], result = a.kind == last proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool = + flags: TTypeAllowedFlags = {}): PType = assert(kind in {skVar, skLet, skConst, skParam, skResult}) # if we have already checked the type, return true, because we stop the # evaluation if something is wrong: - result = true + result = nil if typ == nil: return - if containsOrIncl(marker, typ.id): return + if containsOrIncl(marker, typ.id): return var t = skipTypes(typ, abstractInst-{tyTypeDesc}) case t.kind of tyVar: - if kind == skConst: return false + if kind == skConst: return t var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}) case t2.kind of tyVar: - result = taHeap in flags # ``var var`` is illegal on the heap: - of tyOpenArray: - result = kind == skParam and typeAllowedAux(marker, t2, kind, flags) + if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap + of tyOpenArray: + if kind != skParam: result = t + else: result = typeAllowedAux(marker, t2, kind, flags) else: - result = kind in {skParam, skResult} and - typeAllowedAux(marker, t2, kind, flags) - of tyProc: + if kind notin {skParam, skResult}: result = t + else: result = typeAllowedAux(marker, t2, kind, flags) + of tyProc: for i in countup(1, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], skParam, flags) - if not result: break - if result and t.sons[0] != nil: + if result != nil: break + if result.isNil and t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skResult, flags) of tyExpr, tyStmt, tyTypeDesc, tyStatic: - result = true + result = nil # XXX er ... no? these should not be allowed! of tyEmpty: - result = taField in flags + if taField notin flags: result = t of tyTypeClasses: - result = tfGenericTypeParam in t.flags or - taField notin flags + if not (tfGenericTypeParam in t.flags or taField notin flags): result = t of tyGenericBody, tyGenericParam, tyGenericInvokation, tyNone, tyForward, tyFromExpr, tyFieldAccessor: - result = false + result = t of tyNil: - result = kind == skConst + if kind != skConst: result = t of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: - result = true - of tyOrdinal: - result = kind == skParam - of tyGenericInst, tyDistinct: + result = nil + of tyOrdinal: + if kind != skParam: result = t + of tyGenericInst, tyDistinct: result = typeAllowedAux(marker, lastSon(t), kind, flags) - of tyRange: - result = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind in - {tyChar, tyEnum, tyInt..tyFloat128} - of tyOpenArray, tyVarargs: - result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar, flags) - of tySequence: - result = t.sons[0].kind == tyEmpty or - typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap}) + of tyRange: + if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin + {tyChar, tyEnum, tyInt..tyFloat128}: result = t + of tyOpenArray, tyVarargs: + if kind != skParam: result = t + else: result = typeAllowedAux(marker, t.sons[0], skVar, flags) + of tySequence: + if t.sons[0].kind != tyEmpty: + result = typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap}) of tyArray: - result = t.sons[1].kind == tyEmpty or - typeAllowedAux(marker, t.sons[1], skVar, flags) + if t.sons[1].kind != tyEmpty: + result = typeAllowedAux(marker, t.sons[1], skVar, flags) of tyRef: - if kind == skConst: return false - result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) + if kind == skConst: result = t + else: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) of tyPtr: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) of tyArrayConstr, tySet, tyConst, tyMutable, tyIter: for i in countup(0, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], kind, flags) - if not result: break + if result != nil: break of tyObject, tyTuple: - if kind == skConst and t.kind == tyObject: return false + if kind == skConst and t.kind == tyObject: return t let flags = flags+{taField} - for i in countup(0, sonsLen(t) - 1): + for i in countup(0, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], kind, flags) - if not result: break - if result and t.n != nil: result = typeAllowedNode(marker, t.n, kind, flags) + if result != nil: break + if result.isNil and t.n != nil: + result = typeAllowedNode(marker, t.n, kind, flags) of tyProxy: # for now same as error node; we say it's a valid type as it should # prevent cascading errors: - result = true + result = nil -proc typeAllowed(t: PType, kind: TSymKind): bool = +proc typeAllowed*(t: PType, kind: TSymKind): PType = + # returns 'nil' on success and otherwise the part of the type that is + # wrong! var marker = initIntSet() result = typeAllowedAux(marker, t, kind, {}) diff --git a/tests/generics/tgeneric_inheritance.nim b/tests/generics/tgeneric_inheritance.nim index 66b5a6c69..432228797 100644 --- a/tests/generics/tgeneric_inheritance.nim +++ b/tests/generics/tgeneric_inheritance.nim @@ -1,5 +1,5 @@ discard """ - output: '0.0' + output: "0.0" """ # bug #1919 |