summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-03-03 12:05:03 +0100
committerAraq <rumpf_a@web.de>2013-03-03 12:05:03 +0100
commit5b0d8246f79730a473a869792f12938089ecced6 (patch)
tree3ff8d89a38db10598068e991cf2b2621411ab6a1
parenteebee0eff2360219d02d4cf40675734f3361090a (diff)
downloadNim-5b0d8246f79730a473a869792f12938089ecced6.tar.gz
make some tests green
-rwxr-xr-xcompiler/ccgexprs.nim2
-rw-r--r--compiler/ccgtrav.nim5
-rwxr-xr-xcompiler/ccgtypes.nim20
-rwxr-xr-xcompiler/ccgutils.nim5
-rw-r--r--compiler/parampatterns.nim11
-rwxr-xr-xcompiler/semcall.nim2
-rwxr-xr-xcompiler/semexprs.nim46
-rwxr-xr-xcompiler/semfold.nim10
-rwxr-xr-xcompiler/semstmts.nim10
-rwxr-xr-xcompiler/semtypes.nim4
-rwxr-xr-xcompiler/sigmatch.nim20
-rwxr-xr-xcompiler/types.nim34
-rwxr-xr-xtodo.txt6
13 files changed, 98 insertions, 77 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index cc97baaa4..6b1a4b15d 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1054,7 +1054,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
   # generate call to newSeq before adding the elements per hand:
   genNewSeqAux(p, d, intLiteral(sonsLen(t)))
   for i in countup(0, sonsLen(t) - 1):
-    initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
+    initLoc(arr, locExpr, elemType(skipTypes(t.typ, typedescInst)), OnHeap)
     arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
     arr.s = OnHeap            # we know that sequences are on the heap
     expr(p, t.sons[i], arr)
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 7a0b564a2..aa8b85600 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -59,7 +59,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
   if typ == nil: return
   var p = c.p
   case typ.kind
-  of tyGenericInst, tyGenericBody:
+  of tyGenericInst, tyGenericBody, tyTypeDesc:
     genTraverseProc(c, accessor, lastSon(typ))
   of tyArrayConstr, tyArray:
     let arraySize = lengthOrd(typ.sons[0])
@@ -111,10 +111,11 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
   lineF(p, cpsInit, "a = ($1)p;$n", t)
   
   c.p = p
+  assert typ.kind != tyTypedesc
   if typ.kind == tySequence:
     genTraverseProcSeq(c, "a".toRope, typ)
   else:
-    if skipTypes(typ.sons[0], abstractInst).kind in {tyArrayConstr, tyArray}:
+    if skipTypes(typ.sons[0], typedescInst).kind in {tyArrayConstr, tyArray}:
       # C's arrays are broken beyond repair:
       genTraverseProc(c, "a".toRope, typ.sons[0])
     else:
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index c65d9072d..1b5d9124b 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -193,8 +193,8 @@ proc mapType(typ: PType): TCTypeKind =
       of 8: result = ctInt64
       else: internalError("mapType")
   of tyRange: result = mapType(typ.sons[0])
-  of tyPtr, tyVar, tyRef: 
-    var base = skipTypes(typ.sons[0], abstractInst)
+  of tyPtr, tyVar, tyRef:
+    var base = skipTypes(typ.sons[0], typedescInst)
     case base.kind
     of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
     else: result = ctPtr
@@ -208,7 +208,7 @@ proc mapType(typ: PType): TCTypeKind =
   else: InternalError("mapType")
   
 proc mapReturnType(typ: PType): TCTypeKind = 
-  if skipTypes(typ, abstractInst).kind == tyArray: result = ctPtr
+  if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
   else: result = mapType(typ)
   
 proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope
@@ -224,10 +224,10 @@ proc isInvalidReturnType(rettype: PType): bool =
   else: 
     case mapType(rettype)
     of ctArray: 
-      result = not (skipTypes(rettype, abstractInst).kind in
+      result = not (skipTypes(rettype, typedescInst).kind in
           {tyVar, tyRef, tyPtr})
     of ctStruct: 
-      result = needsComplexAssignment(skipTypes(rettype, abstractInst))
+      result = needsComplexAssignment(skipTypes(rettype, typedescInst))
     else: result = false
   
 const 
@@ -253,7 +253,7 @@ proc getGlobalTempName(): PRope =
   result = rfmt(nil, "TMP$1", toRope(backendId()))
 
 proc ccgIntroducedPtr(s: PSym): bool = 
-  var pt = skipTypes(s.typ, abstractInst)
+  var pt = skipTypes(s.typ, typedescInst)
   assert skResult != s.kind
   if tfByRef in pt.flags: return true
   elif tfByCopy in pt.flags: return false
@@ -280,13 +280,13 @@ proc fillResult(param: PSym) =
 proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
   when false:
     if t.Kind in {tyRef, tyPtr, tyVar}:
-      var b = skipTypes(t.sons[0], abstractInst)
+      var b = skipTypes(t.sons[0], typedescInst)
       if b.kind == tySet and mapSetType(b) == ctArray:
         return getTypeDescAux(m, b, check)
   result = getTypeDescAux(m, t, check)
 
 proc paramStorageLoc(param: PSym): TStorageLoc =
-  if param.typ.skipTypes({tyVar}).kind notin {tyArray, tyOpenArray}:
+  if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray}:
     result = OnStack
   else:
     result = OnUnknown
@@ -572,7 +572,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
     assert(CacheGetType(m.typeCache, t) == nil)
     IdTablePut(m.typeCache, t, con(result, "*"))
     if not isImportedType(t): 
-      if skipTypes(t.sons[0], abstractInst).kind != tyEmpty: 
+      if skipTypes(t.sons[0], typedescInst).kind != tyEmpty: 
         const
           cppSeq = "struct $2 : #TGenericSeq {$n"
           cSeq = "struct $2 {$n" &
@@ -915,7 +915,7 @@ include ccgtrav
 proc genTypeInfo(m: BModule, typ: PType): PRope = 
   var t = getUniqueType(typ)
   result = ropef("NTI$1", [toRope(t.id)])
-  let owner = typ.skipTypes(abstractPtrs).owner.getModule
+  let owner = typ.skipTypes(typedescPtrs).owner.getModule
   if owner != m.module:
     # make sure the type info is created in the owner module
     discard genTypeInfo(owner.bmod, typ)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 90696825b..7e5c62daa 100755
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -80,7 +80,7 @@ proc GetUniqueType*(key: PType): PType =
     # no canonicalization for integral types, so that e.g. ``pid_t`` is
     # produced instead of ``NI``.
     result = key
-  of  tyEmpty, tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString, 
+  of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString, 
       tyCString, tyNone, tyBigNum:
     result = gCanonicalTypes[k]
     if result == nil:
@@ -88,7 +88,8 @@ proc GetUniqueType*(key: PType): PType =
       result = key
   of tyGenericParam, tyTypeClass:
     InternalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
+  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter, 
+      tyTypeDesc:
     result = GetUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index 21c7faf19..de7bcaeee 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -187,21 +187,24 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
       else:
         result = arLValue
   of nkDotExpr: 
-    if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}: 
+    if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in 
+        {tyVar, tyPtr, tyRef}: 
       result = arLValue
-    else: 
+    else:
       result = isAssignable(owner, n.sons[0])
     if result != arNone and sfDiscriminant in n.sons[1].sym.flags: 
       result = arDiscriminant
   of nkBracketExpr: 
-    if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}: 
+    if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
+        {tyVar, tyPtr, tyRef}: 
       result = arLValue
     else:
       result = isAssignable(owner, n.sons[0])
   of nkHiddenStdConv, nkHiddenSubConv, nkConv: 
     # Object and tuple conversions are still addressable, so we skip them
     # XXX why is 'tyOpenArray' allowed here?
-    if skipTypes(n.typ, abstractPtrs).kind in {tyOpenArray, tyTuple, tyObject}: 
+    if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
+        {tyOpenArray, tyTuple, tyObject}:
       result = isAssignable(owner, n.sons[1])
     elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
       # types that are equal modulo distinction preserve l-value:
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 68c627a39..46595c1e7 100755
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -204,7 +204,7 @@ proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym =
   call.add(newIdentNode(fn.name, fn.info))
   for i in 1.. <fn.typ.n.len:
     let param = fn.typ.n.sons[i]
-    let t = skipTypes(param.typ, abstractVar)
+    let t = skipTypes(param.typ, abstractVar-{tyTypeDesc})
     call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct))
   var resolved = semOverloadedCall(c, call, call, {fn.kind})
   if resolved != nil:
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index b6e328926..98cc2fa45 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -11,7 +11,7 @@
 # included from sem.nim
 
 proc restoreOldStyleType(n: PNode) =
-  # XXX: semExprWithType used to return the same type
+  # semExprWithType used to return the same type
   # for nodes such as (100) or (int). 
   # This is inappropriate. The type of the first expression
   # should be "int", while the type of the second one should 
@@ -75,7 +75,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   case s.kind
   of skConst:
     markUsed(n, s)
-    case skipTypes(s.typ, abstractInst).kind
+    case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
     of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, 
         tyTuple, tySet, tyUInt..tyUInt64:
       result = inlineConst(n, s)
@@ -145,7 +145,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
       result = convNotNeedeed
     return
   var d = skipTypes(castDest, abstractVar)
-  var s = skipTypes(src, abstractVar)
+  var s = skipTypes(src, abstractVar-{tyTypeDesc})
   while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
     d = base(d)
     s = base(s)
@@ -154,7 +154,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
   elif d.Kind == tyObject and s.Kind == tyObject:
     result = checkConversionBetweenObjects(d, s)
   elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
-      (skipTypes(src, abstractVarRange).Kind in IntegralTypes):
+      (skipTypes(src, abstractVarRange-{tyTypeDesc}).Kind in IntegralTypes):
     # accept conversion between integral types
   else:
     # we use d, s here to speed up that operation a bit:
@@ -181,7 +181,7 @@ proc isCastable(dst, src: PType): bool =
   else: 
     result = (ds >= ss) or
         (skipTypes(dst, abstractInst).kind in IntegralTypes) or
-        (skipTypes(src, abstractInst).kind in IntegralTypes)
+        (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
   
 proc isSymChoice(n: PNode): bool {.inline.} =
   result = n.kind in nkSymChoices
@@ -195,7 +195,7 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
   var op = result.sons[1]
-     
+  
   if not isSymChoice(op):
     let status = checkConvertible(result.typ, op.typ)
     case status
@@ -234,24 +234,24 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
     LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
   else: 
     n.sons[1] = semExprWithType(c, n.sons[1])
-    restoreOldStyleType(n.sons[1])
     var typ = skipTypes(n.sons[1].typ, abstractVarRange)
     case typ.Kind
     of tySequence, tyString, tyOpenArray, tyVarargs: 
       n.typ = getSysType(tyInt)
     of tyArrayConstr, tyArray: 
-      n.typ = n.sons[1].typ.sons[0] # indextype
+      n.typ = typ.sons[0] # indextype
     of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: 
-      n.typ = n.sons[1].typ
+      # do not skip the range!
+      n.typ = n.sons[1].typ.skipTypes(abstractVar)
     else: LocalError(n.info, errInvalidArgForX, opToStr[m])
   result = n
 
-proc semSizeof(c: PContext, n: PNode): PNode = 
+proc semSizeof(c: PContext, n: PNode): PNode =
   if sonsLen(n) != 2:
     LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
-  else: 
+  else:
     n.sons[1] = semExprWithType(c, n.sons[1])
-    restoreOldStyleType(n.sons[1])
+    #restoreOldStyleType(n.sons[1])
   n.typ = getSysType(tyInt)
   result = n
 
@@ -261,10 +261,10 @@ proc semOf(c: PContext, n: PNode): PNode =
     n.sons[2] = semExprWithType(c, n.sons[2])
     #restoreOldStyleType(n.sons[1])
     #restoreOldStyleType(n.sons[2])
-    let a = skipTypes(n.sons[1].typ, typedescPtrs)
-    let b = skipTypes(n.sons[2].typ, typedescPtrs)
-    let x = skipTypes(n.sons[1].typ, abstractPtrs)
-    let y = skipTypes(n.sons[2].typ, abstractPtrs)
+    let a = skipTypes(n.sons[1].typ, abstractPtrs)
+    let b = skipTypes(n.sons[2].typ, abstractPtrs)
+    let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
+    let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
 
     if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
       LocalError(n.info, errXExpectsObjectTypes, "of")
@@ -481,7 +481,8 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
   case n.kind
   of nkSym: 
     # n.sym.typ can be nil in 'check' mode ...
-    if n.sym.typ != nil and skipTypes(n.sym.typ, abstractInst).kind != tyVar: 
+    if n.sym.typ != nil and
+        skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
       incl(n.sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
   of nkDotExpr: 
@@ -489,12 +490,12 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
     if n.sons[1].kind != nkSym: 
       internalError(n.info, "analyseIfAddressTaken")
       return
-    if skipTypes(n.sons[1].sym.typ, abstractInst).kind != tyVar: 
+    if skipTypes(n.sons[1].sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
       incl(n.sons[1].sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
   of nkBracketExpr: 
     checkMinSonsLen(n, 1)
-    if skipTypes(n.sons[0].typ, abstractInst).kind != tyVar: 
+    if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind != tyVar: 
       if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
   else: 
@@ -515,13 +516,13 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
     # BUGFIX: check for L-Value still needs to be done for the arguments!
     for i in countup(1, sonsLen(n) - 1): 
       if i < sonsLen(t) and t.sons[i] != nil and
-          skipTypes(t.sons[i], abstractInst).kind == tyVar: 
+          skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar: 
         if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}: 
           LocalError(n.sons[i].info, errVarForOutParamNeeded)
     return
   for i in countup(1, sonsLen(n) - 1): 
     if i < sonsLen(t) and
-        skipTypes(t.sons[i], abstractInst).kind == tyVar:
+        skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
       n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
   
 include semmagic
@@ -711,7 +712,8 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = evalAtCompileTime(c, result)
 
 proc buildStringify(c: PContext, arg: PNode): PNode = 
-  if arg.typ != nil and skipTypes(arg.typ, abstractInst).kind == tyString:
+  if arg.typ != nil and 
+      skipTypes(arg.typ, abstractInst-{tyTypeDesc}).kind == tyString:
     result = arg
   else:
     result = newNodeI(nkCall, arg.info)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index d0805d921..e46bb0459 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -587,16 +587,18 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
           LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined, 
                      "sizeof")
           result = nil
-        elif skipTypes(a.typ, abstractInst).kind in {tyArray,tyObject,tyTuple}:
+        elif skipTypes(a.typ, typedescInst).kind in
+             IntegralTypes+NilableTypes+{tySet}:
+          #{tyArray,tyObject,tyTuple}:
+          result = newIntNodeT(getSize(a.typ), n)
+        else:
           result = nil
           # XXX: size computation for complex types is still wrong
-        else:
-          result = newIntNodeT(getSize(a.typ), n)
       of mLow: 
         result = newIntNodeT(firstOrd(n.sons[1].typ), n)
       of mHigh: 
         if  skipTypes(n.sons[1].typ, abstractVar).kind notin
-            {tyOpenArray, tyVarargs, tySequence, tyString}: 
+            {tyOpenArray, tyVarargs, tySequence, tyString}:
           result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
         else:
           var a = getArrayConstr(m, n.sons[1])
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index dacd397a2..1821e5400 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -119,11 +119,11 @@ proc semWhile(c: PContext, n: PNode): PNode =
   closeScope(c.tab)
 
 proc toCover(t: PType): biggestInt = 
-  var t2 = skipTypes(t, abstractVarRange)
+  var t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
   if t2.kind == tyEnum and enumHasHoles(t2): 
     result = sonsLen(t2.n)
   else:
-    result = lengthOrd(skipTypes(t, abstractVar))
+    result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
 
 proc semCase(c: PContext, n: PNode): PNode = 
   # check selector:
@@ -133,7 +133,7 @@ proc semCase(c: PContext, n: PNode): PNode =
   n.sons[0] = semExprWithType(c, n.sons[0])
   var chckCovered = false
   var covered: biggestint = 0
-  case skipTypes(n.sons[0].Typ, abstractVarRange).Kind
+  case skipTypes(n.sons[0].Typ, abstractVarRange-{tyTypeDesc}).Kind
   of tyInt..tyInt64, tyChar, tyEnum: 
     chckCovered = true
   of tyFloat..tyFloat128, tyString, tyError: 
@@ -411,12 +411,12 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
     LocalError(n.info, errWrongNumberOfVariables)
     return result
   
-  var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
+  var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
   if tupleTypeA.kind notin {tyTuple, tyObject}:
     localError(n.info, errGenerated, "no object or tuple type")
     return result
   for i in 1..call.len-1:
-    var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar)
+    var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
     if not SameType(tupleTypeA, tupleTypeB):
       typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
   
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index bda0047ca..dbb05dc5f 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -45,7 +45,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       e = newSymS(skEnumField, n.sons[i].sons[0], c)
       var v = semConstExpr(c, n.sons[i].sons[1])
       var strVal: PNode = nil
-      case skipTypes(v.typ, abstractInst).kind 
+      case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind 
       of tyTuple: 
         if sonsLen(v) == 2:
           strVal = v.sons[1] # second tuple part is the string value
@@ -388,7 +388,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     return
   incl(a.sons[0].sym.flags, sfDiscriminant)
   var covered: biggestInt = 0
-  var typ = skipTypes(a.sons[0].Typ, abstractVar)
+  var typ = skipTypes(a.sons[0].Typ, abstractVar-{tyTypeDesc})
   if not isOrdinalType(typ): 
     LocalError(n.info, errSelectorMustBeOrdinal)
   elif firstOrd(typ) < 0: 
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 896d08665..882f582cb 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -171,12 +171,19 @@ proc NotFoundError*(c: PContext, n: PNode) =
     # fail fast:
     GlobalError(n.info, errTypeMismatch, "")
   var result = msgKindToString(errTypeMismatch)
-  for i in countup(1, sonsLen(n) - 1): 
-    #debug(n.sons[i].typ)
+  for i in countup(1, sonsLen(n) - 1):
+    var nt = n.sons[i].typ
     if n.sons[i].kind == nkExprEqExpr: 
       add(result, renderTree(n.sons[i].sons[0]))
       add(result, ": ")
-    let nt = n.sons[i].typ
+      if nt.isNil:
+        n.sons[i].sons[1] = c.semExprWithType(c, n.sons[i].sons[1])
+        nt = n.sons[i].sons[1].typ
+        n.sons[i].typ = nt
+    else:
+      if nt.isNil:
+        n.sons[i] = c.semExprWithType(c, n.sons[i])
+        nt = n.sons[i].typ
     if nt.kind == tyError: return
     add(result, typeToString(nt))
     if i != sonsLen(n) - 1: add(result, ", ")
@@ -188,7 +195,6 @@ proc NotFoundError*(c: PContext, n: PNode) =
     if sym.kind in RoutineKinds:
       add(candidates, getProcHeader(sym))
       add(candidates, "\n")
-      #debug(sym.typ)
     sym = nextOverloadIter(o, c, n.sons[0])
   if candidates != "": 
     add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
@@ -712,7 +718,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
       result = copyTree(arg)
       result.typ = getInstantiatedType(c, arg, m, f) 
       # BUG: f may not be the right key!
-      if skipTypes(result.typ, abstractVar).kind in {tyTuple}:
+      if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
         result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) 
         # BUGFIX: use ``result.typ`` and not `f` here
   of isFromIntLit:
@@ -723,7 +729,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
   of isEqual: 
     inc(m.exactMatches)
     result = copyTree(arg)
-    if skipTypes(f, abstractVar).kind in {tyTuple}: 
+    if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
       result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
   of isNone:
     # do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
@@ -885,7 +891,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           # is ok... but don't increment any counters...
           # we have no formal here to snoop at:
           n.sons[a] = prepareOperand(c, n.sons[a])
-          if skipTypes(n.sons[a].typ, abstractVar).kind == tyString:
+          if skipTypes(n.sons[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
             addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString),
                                         copyTree(n.sons[a]), m, c))
           else:
diff --git a/compiler/types.nim b/compiler/types.nim
index 68a1b8056..fe8e03c07 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -49,16 +49,18 @@ proc isOrdinalType*(t: PType): bool
 proc enumHasHoles*(t: PType): bool
 const 
   abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
-                   tyConst, tyMutable}
+                   tyConst, tyMutable, tyTypeDesc}
   abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
-                  tyConst, tyMutable}
+                  tyConst, tyMutable, tyTypeDesc}
   abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal,
-                    tyConst, tyMutable}
+                    tyConst, tyMutable, tyTypeDesc}
   abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
-                       tyConst, tyMutable}
-  abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal}
+                       tyConst, tyMutable, tyTypeDesc}
+  abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
+                   tyTypeDesc}
 
-  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable}
+  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable, 
+               tyTypeDesc}
   typedescPtrs* = abstractPtrs + {tyTypeDesc}
   typedescInst* = abstractInst + {tyTypeDesc}
 
@@ -327,7 +329,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
   result = false
   if typ == nil: return 
   if tfAcyclic in typ.flags: return 
-  var t = skipTypes(typ, abstractInst)
+  var t = skipTypes(typ, abstractInst-{tyTypeDesc})
   if tfAcyclic in t.flags: return 
   case t.kind
   of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
@@ -542,7 +544,7 @@ proc firstOrd(t: PType): biggestInt =
     else: 
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct, tyConst, tyMutable:
+  of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc:
     result = firstOrd(lastSon(t))
   else: 
     InternalError("invalid kind for first(" & $t.kind & ')')
@@ -575,7 +577,7 @@ proc lastOrd(t: PType): biggestInt =
   of tyEnum: 
     assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
     result = t.n.sons[sonsLen(t.n) - 1].sym.position
-  of tyGenericInst, tyDistinct, tyConst, tyMutable: 
+  of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc: 
     result = lastOrd(lastSon(t))
   of tyProxy: result = 0
   else: 
@@ -841,7 +843,8 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
   of tyGenericInst:
     result = sameTypeAux(lastSon(a), lastSon(b), c)
   of tyTypeDesc:
-    if TypeDescExactMatch in c.flags:
+    if c.cmp == dcEqIgnoreDistinct: result = false
+    elif TypeDescExactMatch in c.flags:
       CycleCheck()
       result = sameChildrenAux(x, y, c) and sameFlags(a, b)
     else:
@@ -971,11 +974,11 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   result = true
   if typ == nil: return
   if ContainsOrIncl(marker, typ.id): return 
-  var t = skipTypes(typ, abstractInst)
+  var t = skipTypes(typ, abstractInst-{tyTypeDesc})
   case t.kind
   of tyVar:
     if kind == skConst: return false
-    var t2 = skipTypes(t.sons[0], abstractInst)
+    var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
     case t2.kind
     of tyVar: 
       result = false          # ``var var`` is always an invalid type:
@@ -989,8 +992,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
       if not result: break 
     if result and t.sons[0] != nil:
       result = typeAllowedAux(marker, t.sons[0], skResult)
-  of tyExpr, tyStmt, tyTypeDesc: 
+  of tyExpr, tyStmt, tyTypeDesc:
     result = true
+    # XXX er ... no? these should not be allowed!
   of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, 
       tyTypeClass:
     result = false
@@ -1003,7 +1007,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   of tyGenericInst, tyDistinct: 
     result = typeAllowedAux(marker, lastSon(t), kind)
   of tyRange: 
-    result = skipTypes(t.sons[0], abstractInst).kind in
+    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)
@@ -1171,6 +1175,8 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
     result = align(result, a)
   of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
     result = computeSizeAux(lastSon(typ), a)
+  of tyTypeDesc:
+    result = (if typ.len == 1: computeSizeAux(typ.sons[0], a) else: -1)
   of tyProxy: result = 1
   else:
     #internalError("computeSizeAux()")
diff --git a/todo.txt b/todo.txt
index 4aa9f6fad..83730bf54 100755
--- a/todo.txt
+++ b/todo.txt
@@ -13,6 +13,9 @@ version 0.9.2
 - fix:
   - 'result' is not properly cleaned for NRVO
 - document NimMain and check whether it works for threading
+- fix destructors; don't work yet when used as expression; alternative for 
+  version 1: disallow expressions yielding a type with a destructor that are
+  not in a 'let/var' context  (p(a.openFile, b.openFile) makes no sense anyway)
 
 
 version 0.9.4
@@ -65,9 +68,6 @@ version 0.9.XX
 - object branch transitions can't work with the current 'reset'; add a 'reset'
   with an additional parameter --> re-evaluate this issue after constructors
   have been added
-- fix destructors; don't work yet when used as expression; alternative for 
-  version 1: disallow expressions yielding a type with a destructor that are
-  not in a 'let/var' context  (p(a.openFile, b.openFile) makes no sense anyway)
 - document nimdoc properly finally
 - make 'clamp' a magic for the range stuff
 - better type syntax for functions and tuples: tuple(int, int); (int,int)->int