summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2016-11-14 23:18:30 +0100
committerAraq <rumpf_a@web.de>2016-11-14 23:18:30 +0100
commite6c5622aa74c1014b022071d9d525a0e13805246 (patch)
treefe50571aaf2f34ec7f36fb1068b5f3ffbd97250d
parentb234b082b60e57ec07a380599b6b7a311026d0ed (diff)
downloadNim-e6c5622aa74c1014b022071d9d525a0e13805246.tar.gz
removed tyArrayConstr completely from the compiler; introduced tyAlias instead in preparation for further bugfixes
-rw-r--r--compiler/aliases.nim4
-rw-r--r--compiler/ast.nim12
-rw-r--r--compiler/canonicalizer.nim2
-rw-r--r--compiler/ccgcalls.nim12
-rw-r--r--compiler/ccgexprs.nim25
-rw-r--r--compiler/ccgtrav.nim4
-rw-r--r--compiler/ccgtypes.nim18
-rw-r--r--compiler/ccgutils.nim4
-rw-r--r--compiler/cgen.nim4
-rw-r--r--compiler/cgmeth.nim4
-rw-r--r--compiler/evalffi.nim56
-rw-r--r--compiler/guards.nim2
-rw-r--r--compiler/jsgen.nim25
-rw-r--r--compiler/jstypes.nim6
-rw-r--r--compiler/lowerings.nim2
-rw-r--r--compiler/renderer.nim3
-rw-r--r--compiler/sem.nim8
-rw-r--r--compiler/semasgn.nim6
-rw-r--r--compiler/semcall.nim2
-rw-r--r--compiler/semdestruct.nim4
-rw-r--r--compiler/semexprs.nim44
-rw-r--r--compiler/semfold.nim3
-rw-r--r--compiler/semmacrosanity.nim2
-rw-r--r--compiler/semstmts.nim10
-rw-r--r--compiler/semtypes.nim17
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sighashes.nim2
-rw-r--r--compiler/sigmatch.nim24
-rw-r--r--compiler/suggest.nim4
-rw-r--r--compiler/transf.nim4
-rw-r--r--compiler/trees.nim2
-rw-r--r--compiler/types.nim80
-rw-r--r--compiler/vmdeps.nim4
-rw-r--r--compiler/vmgen.nim2
-rw-r--r--compiler/vmmarshal.nim4
35 files changed, 201 insertions, 206 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index 4186900ec..0c836bb24 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -49,9 +49,9 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
     if a.sons[0] != nil:
       result = isPartOfAux(a.sons[0].skipTypes(skipPtrs), b, marker)
     if result == arNo: result = isPartOfAux(a.n, b, marker)
-  of tyGenericInst, tyDistinct:
+  of tyGenericInst, tyDistinct, tyAlias:
     result = isPartOfAux(lastSon(a), b, marker)
-  of tyArray, tyArrayConstr, tySet, tyTuple:
+  of tyArray, tySet, tyTuple:
     for i in countup(0, sonsLen(a) - 1):
       result = isPartOfAux(a.sons[i], b, marker)
       if result == arYes: return
diff --git a/compiler/ast.nim b/compiler/ast.nim
index cd94efd41..ffcd08c77 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -322,7 +322,7 @@ type
                      # (apparently something with bootstrapping)
                      # if you need to add a type, they can apparently be reused
     tyNone, tyBool, tyChar,
-    tyEmpty, tyArrayConstr, tyNil, tyExpr, tyStmt, tyTypeDesc,
+    tyEmpty, tyAlias, tyNil, tyExpr, tyStmt, tyTypeDesc,
     tyGenericInvocation, # ``T[a, b]`` for types to invoke
     tyGenericBody,       # ``T[a, b, body]`` last parameter is the body
     tyGenericInst,       # ``T[a, b, realInstance]`` instantiated generic type
@@ -907,7 +907,7 @@ const
   GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
     tyGenericParam}
 
-  StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
+  StructuralEquivTypes*: TTypeKinds = {tyNil, tyTuple, tyArray,
     tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
     tyVarargs}
 
@@ -920,7 +920,7 @@ const
     tyUInt..tyUInt64}
   IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
     tyFloat..tyFloat128, tyUInt..tyUInt64}
-  ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
+  ConstantDataTypes*: TTypeKinds = {tyArray, tySet,
                                     tyTuple, tySequence}
   NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
     tyProc, tyString, tyError}
@@ -1370,8 +1370,8 @@ proc propagateToOwner*(owner, elem: PType) =
     owner.flags.incl tfHasMeta
 
   if tfHasAsgn in elem.flags:
-    let o2 = elem.skipTypes({tyGenericInst})
-    if o2.kind in {tyTuple, tyObject, tyArray, tyArrayConstr,
+    let o2 = elem.skipTypes({tyGenericInst, tyAlias})
+    if o2.kind in {tyTuple, tyObject, tyArray,
                    tySequence, tySet, tyDistinct}:
       o2.flags.incl tfHasAsgn
       owner.flags.incl tfHasAsgn
@@ -1381,7 +1381,7 @@ proc propagateToOwner*(owner, elem: PType) =
 
   if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
                        tyGenericInvocation, tyPtr}:
-    let elemB = elem.skipTypes({tyGenericInst})
+    let elemB = elem.skipTypes({tyGenericInst, tyAlias})
     if elemB.isGCedMem or tfHasGCedMem in elemB.flags:
       # for simplicity, we propagate this flag even to generics. We then
       # ensure this doesn't bite us in sempass2.
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
index 2abe0a0e6..d17d928c8 100644
--- a/compiler/canonicalizer.nim
+++ b/compiler/canonicalizer.nim
@@ -132,7 +132,7 @@ proc hashType(c: var MD5Context, t: PType) =
       c.hashType t.sons[i]
   of tyFromExpr, tyFieldAccessor:
     c.hashTree(t.n)
-  of tyArrayConstr:
+  of tyArray:
     c.hashTree(t.sons[0].n)
     c.hashType(t.sons[1])
   of tyTuple:
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 48157925c..772a208cb 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -95,7 +95,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
     initLocExpr(p, q[3], c)
     let fmt =
       case skipTypes(a.t, abstractVar+{tyPtr}).kind
-      of tyOpenArray, tyVarargs, tyArray, tyArrayConstr:
+      of tyOpenArray, tyVarargs, tyArray:
         "($1)+($2), ($3)-($2)+1"
       of tyString, tySequence:
         if skipTypes(n.typ, abstractInst).kind == tyVar and
@@ -116,13 +116,13 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
         result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
       else:
         result = "$1->data, $1->$2" % [a.rdLoc, lenField(p)]
-    of tyArray, tyArrayConstr:
+    of tyArray:
       result = "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))]
     of tyPtr, tyRef:
       case lastSon(a.t).kind
       of tyString, tySequence:
         result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
-      of tyArray, tyArrayConstr:
+      of tyArray:
         result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))]
       else:
         internalError("openArrayLoc: " & typeToString(a.t))
@@ -331,7 +331,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
   # skip the deref:
   var ri = ri[i]
   while ri.kind == nkObjDownConv: ri = ri[0]
-  let t = typ.sons[i].skipTypes({tyGenericInst})
+  let t = typ.sons[i].skipTypes({tyGenericInst, tyAlias})
   if t.kind == tyVar:
     let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
     if x.typ.kind == tyPtr:
@@ -527,7 +527,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
     line(p, cpsStmts, pl)
 
 proc genCall(p: BProc, e: PNode, d: var TLoc) =
-  if e.sons[0].typ.skipTypes({tyGenericInst}).callConv == ccClosure:
+  if e.sons[0].typ.skipTypes({tyGenericInst, tyAlias}).callConv == ccClosure:
     genClosureCall(p, nil, e, d)
   elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags:
     genInfixCall(p, nil, e, d)
@@ -538,7 +538,7 @@ proc genCall(p: BProc, e: PNode, d: var TLoc) =
   postStmtActions(p)
 
 proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
-  if ri.sons[0].typ.skipTypes({tyGenericInst}).callConv == ccClosure:
+  if ri.sons[0].typ.skipTypes({tyGenericInst, tyAlias}).callConv == ccClosure:
     genClosureCall(p, le, ri, d)
   elif ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags:
     genInfixCall(p, le, ri, d)
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index d11e6f608..ad88e9750 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -322,7 +322,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
         genGenericAsgn(p, dest, src, flags)
     else:
       linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-  of tyArray, tyArrayConstr:
+  of tyArray:
     if needsComplexAssignment(dest.t):
       genGenericAsgn(p, dest, src, flags)
     else:
@@ -357,7 +357,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
 proc genDeepCopy(p: BProc; dest, src: TLoc) =
   var ty = skipTypes(dest.t, abstractVarRange)
   case ty.kind
-  of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
+  of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray:
     # XXX optimize this
     linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
             addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
@@ -871,7 +871,7 @@ proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
   var ty = skipTypes(n.sons[0].typ, abstractVarRange)
   if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
   case ty.kind
-  of tyArray, tyArrayConstr: genArrayElem(p, n.sons[0], n.sons[1], d)
+  of tyArray: genArrayElem(p, n.sons[0], n.sons[1], d)
   of tyOpenArray, tyVarargs: genOpenArrayElem(p, n.sons[0], n.sons[1], d)
   of tySequence, tyString: genSeqElem(p, n.sons[0], n.sons[1], d)
   of tyCString: genCStringElem(p, n.sons[0], n.sons[1], d)
@@ -1301,15 +1301,14 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
     of tyString, tySequence:
       putIntoDest(p, b, e.typ,
                   "$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.s)
-    of tyArray, tyArrayConstr:
+    of tyArray:
       putIntoDest(p, b, e.typ,
                   "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.s)
     else: internalError(e.sons[0].info, "genRepr()")
     putIntoDest(p, d, e.typ,
         ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
         genTypeInfo(p.module, elemType(t))]), a.s)
-  of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
-     tySequence:
+  of tyCString, tyArray, tyRef, tyPtr, tyPointer, tyNil, tySequence:
     putIntoDest(p, d, e.typ,
                 ropecg(p.module, "#reprAny($1, $2)", [
                 rdLoc(a), genTypeInfo(p.module, t)]), a.s)
@@ -1351,7 +1350,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     else:
       if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
       else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
-  of tyArray, tyArrayConstr:
+  of tyArray:
     # YYY: length(sideeffect) is optimized away incorrectly?
     if op == mHigh: putIntoDest(p, d, e.typ, rope(lastOrd(typ)))
     else: putIntoDest(p, d, e.typ, rope(lengthOrd(typ)))
@@ -1531,8 +1530,7 @@ proc genOrd(p: BProc, e: PNode, d: var TLoc) =
 
 proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
   const
-    ValueTypes = {tyTuple, tyObject, tyArray, tyOpenArray, tyVarargs,
-                  tyArrayConstr}
+    ValueTypes = {tyTuple, tyObject, tyArray, tyOpenArray, tyVarargs}
   # we use whatever C gives us. Except if we have a value-type, we need to go
   # through its address:
   var a: TLoc
@@ -1549,8 +1547,7 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
         [getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.s)
 
 proc genCast(p: BProc, e: PNode, d: var TLoc) =
-  const ValueTypes = {tyFloat..tyFloat128, tyTuple, tyObject,
-                      tyArray, tyArrayConstr}
+  const ValueTypes = {tyFloat..tyFloat128, tyTuple, tyObject, tyArray}
   let
     destt = skipTypes(e.typ, abstractRange)
     srct = skipTypes(e.sons[1].typ, abstractRange)
@@ -1590,7 +1587,7 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
         rope(magic)]), a.s)
 
 proc genConv(p: BProc, e: PNode, d: var TLoc) =
-  let destType = e.typ.skipTypes({tyVar, tyGenericInst})
+  let destType = e.typ.skipTypes({tyVar, tyGenericInst, tyAlias})
   if compareTypes(destType, e.sons[1].typ, dcEqIgnoreDistinct):
     expr(p, e.sons[1], d)
   else:
@@ -1664,7 +1661,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
                                                "$# = #subInt64($#, $#);$n"]
     const fun: array[mInc..mDec, string] = ["$# = #addInt($#, $#);$n",
                                              "$# = #subInt($#, $#);$n"]
-    let underlying = skipTypes(e.sons[1].typ, {tyGenericInst, tyVar, tyRange})
+    let underlying = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tyVar, tyRange})
     if optOverflowCheck notin p.options or underlying.kind in {tyUInt..tyUInt64}:
       binaryStmt(p, e, d, opr[op])
     else:
@@ -1674,7 +1671,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       initLocExpr(p, e.sons[1], a)
       initLocExpr(p, e.sons[2], b)
 
-      let ranged = skipTypes(e.sons[1].typ, {tyGenericInst, tyVar})
+      let ranged = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tyVar})
       let res = binaryArithOverflowRaw(p, ranged, a, b,
         if underlying.kind == tyInt64: fun64[op] else: fun[op])
       putIntoDest(p, a, ranged, "($#)($#)" % [
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index fbba19897..052f2ccbd 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -60,9 +60,9 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
 
   var p = c.p
   case typ.kind
-  of tyGenericInst, tyGenericBody, tyTypeDesc:
+  of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias:
     genTraverseProc(c, accessor, lastSon(typ))
-  of tyArrayConstr, tyArray:
+  of tyArray:
     let arraySize = lengthOrd(typ.sons[0])
     var i: TLoc
     getTemp(p, getSysType(tyInt), i)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 49fd14003..9a7f9e037 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -133,10 +133,10 @@ proc mapType(typ: PType): TCTypeKind =
   of tyBool: result = ctBool
   of tyChar: result = ctChar
   of tySet: result = mapSetType(typ)
-  of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
+  of tyOpenArray, tyArray, tyVarargs: result = ctArray
   of tyObject, tyTuple: result = ctStruct
   of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
-     tyTypeDesc:
+     tyTypeDesc, tyAlias:
     result = mapType(lastSon(typ))
   of tyEnum:
     if firstOrd(typ) < 0:
@@ -152,7 +152,7 @@ proc mapType(typ: PType): TCTypeKind =
   of tyPtr, tyVar, tyRef:
     var base = skipTypes(typ.lastSon, typedescInst)
     case base.kind
-    of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctPtrToArray
+    of tyOpenArray, tyArray, tyVarargs: result = ctPtrToArray
     #of tySet:
     #  if mapSetType(base) == ctArray: result = ctPtrToArray
     #  else: result = ctPtr
@@ -277,7 +277,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
   of tyStatic:
     if typ.n != nil: result = getSimpleTypeDesc(m, lastSon typ)
     else: internalError("tyStatic for getSimpleTypeDesc")
-  of tyGenericInst:
+  of tyGenericInst, tyAlias:
     result = getSimpleTypeDesc(m, lastSon typ)
   else: result = nil
 
@@ -334,7 +334,7 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
 
 proc paramStorageLoc(param: PSym): TStorageLoc =
   if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {
-          tyArray, tyOpenArray, tyVarargs, tyArrayConstr}:
+          tyArray, tyOpenArray, tyVarargs}:
     result = OnStack
   else:
     result = OnUnknown
@@ -543,7 +543,7 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
 
 const
   irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation,
-                          tyDistinct, tyRange, tyStatic}
+                          tyDistinct, tyRange, tyStatic, tyAlias}
 
 proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
   # returns only the type's name
@@ -565,7 +565,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
                     compileToCpp(m): "&" else: "*"
     var et = origTyp.skipTypes(abstractInst).lastSon
     var etB = et.skipTypes(abstractInst)
-    if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
+    if etB.kind in {tyArray, tyOpenArray, tyVarargs}:
       # this is correct! sets have no proper base type, so we treat
       # ``var set[char]`` in `getParamTypeDesc`
       et = elemType(etB)
@@ -742,7 +742,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
       of 1, 2, 4, 8: addf(m.s[cfsTypes], "typedef NU$2 $1;$n", [result, rope(s*8)])
       else: addf(m.s[cfsTypes], "typedef NU8 $1[$2];$n",
              [result, rope(getSize(t))])
-  of tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc:
+  of tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias:
     result = getTypeDescAux(m, lastSon(t), check)
   else:
     internalError("getTypeDescAux(" & $t.kind & ')')
@@ -1073,7 +1073,7 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
       let markerProc = genTraverseProc(m, origType, sig, tiNew)
       addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
   of tyPtr, tyRange: genTypeInfoAux(m, t, t, result)
-  of tyArrayConstr, tyArray: genArrayInfo(m, t, result)
+  of tyArray: genArrayInfo(m, t, result)
   of tySet: genSetInfo(m, t, result)
   of tyEnum: genEnumInfo(m, t, result)
   of tyObject: genObjectInfo(m, t, origType, result)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 716e8db1d..4d6ba858c 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -108,7 +108,7 @@ proc getUniqueType*(key: PType): PType =
     of tyDistinct:
       if key.deepCopy != nil: result = key
       else: result = getUniqueType(lastSon(key))
-    of tyGenericInst, tyOrdinal, tyStatic:
+    of tyGenericInst, tyOrdinal, tyStatic, tyAlias:
       result = getUniqueType(lastSon(key))
       #let obj = lastSon(key)
       #if obj.sym != nil and obj.sym.name.s == "TOption":
@@ -122,7 +122,7 @@ proc getUniqueType*(key: PType): PType =
         result = key
       else:
         result = slowSearch(key, k)
-    of tyArrayConstr, tyGenericInvocation, tyGenericBody,
+    of tyGenericInvocation, tyGenericBody,
        tyOpenArray, tyArray, tySet, tyRange, tyTuple,
        tySequence, tyForward, tyVarargs, tyProxy:
       # we have to do a slow linear search because types may need
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 522e41a12..89658279d 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -62,7 +62,7 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: Rope, s: TStorageLoc) =
 proc isSimpleConst(typ: PType): bool =
   let t = skipTypes(typ, abstractVar)
   result = t.kind notin
-      {tyTuple, tyObject, tyArray, tyArrayConstr, tySet, tySequence} and not
+      {tyTuple, tyObject, tyArray, tySet, tySequence} and not
       (t.kind == tyProc and t.callConv == ccClosure)
 
 proc useStringh(m: BModule) =
@@ -264,7 +264,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
 
 proc isComplexValueType(t: PType): bool {.inline.} =
   let t = t.skipTypes(abstractInst)
-  result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
+  result = t.kind in {tyArray, tySet, tyTuple, tyObject} or
     (t.kind == tyProc and t.callConv == ccClosure)
 
 proc resetLoc(p: BProc, loc: var TLoc) =
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 5f0d71cc6..eda80be30 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -61,8 +61,8 @@ proc sameMethodBucket(a, b: PSym): MethodResult =
     var aa = a.typ.sons[i]
     var bb = b.typ.sons[i]
     while true:
-      aa = skipTypes(aa, {tyGenericInst})
-      bb = skipTypes(bb, {tyGenericInst})
+      aa = skipTypes(aa, {tyGenericInst, tyAlias})
+      bb = skipTypes(bb, {tyGenericInst, tyAlias})
       if aa.kind == bb.kind and aa.kind in {tyVar, tyPtr, tyRef}:
         aa = aa.lastSon
         bb = bb.lastSon
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 75394c2f3..987cfaf42 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -45,7 +45,7 @@ var myerrno {.importc: "errno", header: "<errno.h>".}: cint ## error variable
 
 proc importcSymbol*(sym: PSym): PNode =
   let name = ropeToStr(sym.loc.r)
-  
+
   # the AST does not support untyped pointers directly, so we use an nkIntLit
   # that contains the address instead:
   result = newNodeIT(nkPtrLit, sym.info, sym.typ)
@@ -67,7 +67,7 @@ proc importcSymbol*(sym: PSym): PNode =
         let dllhandle = gDllCache.getDll(libcDll, sym.info)
         theAddr = dllhandle.symAddr(name)
     elif not lib.isNil:
-      let dllhandle = gDllCache.getDll(if lib.kind == libHeader: libcDll 
+      let dllhandle = gDllCache.getDll(if lib.kind == libHeader: libcDll
                                        else: lib.path.strVal, sym.info)
       theAddr = dllhandle.symAddr(name)
     if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s)
@@ -75,7 +75,7 @@ proc importcSymbol*(sym: PSym): PNode =
 
 proc mapType(t: ast.PType): ptr libffi.TType =
   if t == nil: return addr libffi.type_void
-  
+
   case t.kind
   of tyBool, tyEnum, tyChar, tyInt..tyInt64, tyUInt..tyUInt64, tySet:
     case t.getSize
@@ -87,9 +87,9 @@ proc mapType(t: ast.PType): ptr libffi.TType =
   of tyFloat, tyFloat64: result = addr libffi.type_double
   of tyFloat32: result = addr libffi.type_float
   of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
-     tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyStatic, tyNil:
+     tyStmt, tyTypeDesc, tyProc, tyArray, tyStatic, tyNil:
     result = addr libffi.type_pointer
-  of tyDistinct:
+  of tyDistinct, tyAlias:
     result = mapType(t.sons[0])
   else:
     result = nil
@@ -117,9 +117,9 @@ proc packSize(v: PNode, typ: PType): int =
       result = sizeof(pointer)
     else:
       result = sizeof(pointer) + packSize(v.sons[0], typ.lastSon)
-  of tyDistinct, tyGenericInst:
+  of tyDistinct, tyGenericInst, tyAlias:
     result = packSize(v, typ.sons[0])
-  of tyArray, tyArrayConstr:
+  of tyArray:
     # consider: ptr array[0..1000_000, int] which is common for interfacing;
     # we use the real length here instead
     if v.kind in {nkNilLit, nkPtrLit}:
@@ -136,7 +136,7 @@ proc getField(n: PNode; position: int): PSym =
   of nkRecList:
     for i in countup(0, sonsLen(n) - 1):
       result = getField(n.sons[i], position)
-      if result != nil: return 
+      if result != nil: return
   of nkRecCase:
     result = getField(n.sons[0], position)
     if result != nil: return
@@ -198,7 +198,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyFloat: awr(float, v.floatVal)
   of tyFloat32: awr(float32, v.floatVal)
   of tyFloat64: awr(float64, v.floatVal)
-  
+
   of tyPointer, tyProc,  tyCString, tyString:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
@@ -223,7 +223,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
       pack(v.sons[0], typ.lastSon, res +! sizeof(pointer))
       dec packRecCheck
       awr(pointer, res +! sizeof(pointer))
-  of tyArray, tyArrayConstr:
+  of tyArray:
     let baseSize = typ.sons[1].getSize
     for i in 0 .. <v.len:
       pack(v.sons[i], typ.sons[1], res +! i * baseSize)
@@ -231,7 +231,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     packObject(v, typ, res)
   of tyNil:
     discard
-  of tyDistinct, tyGenericInst:
+  of tyDistinct, tyGenericInst, tyAlias:
     pack(v, typ.sons[0], res)
   else:
     globalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
@@ -256,7 +256,7 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
 proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
   # compute the field's offsets:
   discard typ.getSize
-  
+
   # iterate over any actual field of 'n' ... if n is nil we need to create
   # the nkPar node:
   if n.isNil:
@@ -329,7 +329,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
   template awi(kind, v: expr) {.immediate, dirty.} = aw(kind, v, intVal)
   template awf(kind, v: expr) {.immediate, dirty.} = aw(kind, v, floatVal)
   template aws(kind, v: expr) {.immediate, dirty.} = aw(kind, v, strVal)
-  
+
   case typ.kind
   of tyBool: awi(nkIntLit, rd(bool, x).ord)
   of tyChar: awi(nkCharLit, rd(char, x).ord)
@@ -378,7 +378,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       globalError(n.info, "cannot map value from FFI " & typeToString(typ))
   of tyObject, tyTuple:
     result = unpackObject(x, typ, n)
-  of tyArray, tyArrayConstr:
+  of tyArray:
     result = unpackArray(x, typ, n)
   of tyCString, tyString:
     let p = rd(cstring, x)
@@ -388,15 +388,15 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       aws(nkStrLit, $p)
   of tyNil:
     setNil()
-  of tyDistinct, tyGenericInst:
-    result = unpack(x, typ.sons[0], n)
+  of tyDistinct, tyGenericInst, tyAlias:
+    result = unpack(x, typ.lastSon, n)
   else:
     # XXX what to do with 'array' here?
     globalError(n.info, "cannot map value from FFI " & typeToString(typ))
 
 proc fficast*(x: PNode, destTyp: PType): PNode =
-  if x.kind == nkPtrLit and x.typ.kind in {tyPtr, tyRef, tyVar, tyPointer, 
-                                           tyProc, tyCString, tyString, 
+  if x.kind == nkPtrLit and x.typ.kind in {tyPtr, tyRef, tyVar, tyPointer,
+                                           tyProc, tyCString, tyString,
                                            tySequence}:
     result = newNodeIT(x.kind, x.info, destTyp)
     result.intVal = x.intVal
@@ -416,7 +416,7 @@ proc fficast*(x: PNode, destTyp: PType): PNode =
 
 proc callForeignFunction*(call: PNode): PNode =
   internalAssert call.sons[0].kind == nkPtrLit
-  
+
   var cif: TCif
   var sig: TParamList
   # use the arguments' types for varargs support:
@@ -424,12 +424,12 @@ proc callForeignFunction*(call: PNode): PNode =
     sig[i-1] = mapType(call.sons[i].typ)
     if sig[i-1].isNil:
       globalError(call.info, "cannot map FFI type")
-  
+
   let typ = call.sons[0].typ
   if prep_cif(cif, mapCallConv(typ.callConv, call.info), cuint(call.len-1),
               mapType(typ.sons[0]), sig) != OK:
     globalError(call.info, "error in FFI call")
-  
+
   var args: TArgList
   let fn = cast[pointer](call.sons[0].intVal)
   for i in 1 .. call.len-1:
@@ -440,8 +440,8 @@ proc callForeignFunction*(call: PNode): PNode =
                else: alloc(typ.sons[0].getSize.int)
 
   libffi.call(cif, fn, retVal, args)
-  
-  if retVal.isNil: 
+
+  if retVal.isNil:
     result = emptyNode
   else:
     result = unpack(retVal, typ.sons[0], nil)
@@ -456,7 +456,7 @@ proc callForeignFunction*(fn: PNode, fntyp: PType,
                           args: var TNodeSeq, start, len: int,
                           info: TLineInfo): PNode =
   internalAssert fn.kind == nkPtrLit
-  
+
   var cif: TCif
   var sig: TParamList
   for i in 0..len-1:
@@ -467,11 +467,11 @@ proc callForeignFunction*(fn: PNode, fntyp: PType,
       args[i+start].typ = aTyp
     sig[i] = mapType(aTyp)
     if sig[i].isNil: globalError(info, "cannot map FFI type")
-  
+
   if prep_cif(cif, mapCallConv(fntyp.callConv, info), cuint(len),
               mapType(fntyp.sons[0]), sig) != OK:
     globalError(info, "error in FFI call")
-  
+
   var cargs: TArgList
   let fn = cast[pointer](fn.intVal)
   for i in 0 .. len-1:
@@ -482,8 +482,8 @@ proc callForeignFunction*(fn: PNode, fntyp: PType,
                else: alloc(fntyp.sons[0].getSize.int)
 
   libffi.call(cif, fn, retVal, cargs)
-  
-  if retVal.isNil: 
+
+  if retVal.isNil:
     result = emptyNode
   else:
     result = unpack(retVal, fntyp.sons[0], nil)
diff --git a/compiler/guards.nim b/compiler/guards.nim
index 4e887d3e3..b53365617 100644
--- a/compiler/guards.nim
+++ b/compiler/guards.nim
@@ -207,7 +207,7 @@ proc lowBound*(x: PNode): PNode =
 
 proc highBound*(x: PNode): PNode =
   let typ = x.typ.skipTypes(abstractInst)
-  result = if typ.kind in {tyArrayConstr, tyArray}:
+  result = if typ.kind == tyArray:
              nkIntLit.newIntNode(lastOrd(typ))
            elif typ.kind == tySequence and x.kind == nkSym and
                x.sym.kind == skConst:
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 028dd00f0..cf681d580 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -139,7 +139,7 @@ proc declareGlobal(p: PProc; id: int; r: Rope) =
     p.locals.addf("global $1;$n", [r])
 
 const
-  MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray,
+  MappedToObject = {tyObject, tyArray, tyTuple, tyOpenArray,
     tySet, tyVarargs}
 
 proc mapType(typ: PType): TJSTypeKind =
@@ -153,18 +153,19 @@ proc mapType(typ: PType): TJSTypeKind =
   of tyPointer:
     # treat a tyPointer like a typed pointer to an array of bytes
     result = etyBaseIndex
-  of tyRange, tyDistinct, tyOrdinal, tyProxy: result = mapType(t.sons[0])
+  of tyRange, tyDistinct, tyOrdinal, tyProxy:
+    result = mapType(t.sons[0])
   of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
   of tyBool: result = etyBool
   of tyFloat..tyFloat128: result = etyFloat
   of tySet: result = etyObject # map a set to a table
   of tyString, tySequence: result = etySeq
-  of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyVarargs:
+  of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs:
     result = etyObject
   of tyNil: result = etyNull
   of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
      tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
-     tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid:
+     tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid, tyAlias:
     result = etyNone
   of tyStatic:
     if t.n != nil: result = mapType(lastSon t)
@@ -796,8 +797,8 @@ proc generateHeader(p: PProc, typ: PType): Rope =
         add(result, name)
         add(result, "_Idx")
     elif not (i == 1 and param.name.s == "this"):
-      let k = param.typ.skipTypes({tyGenericInst}).kind
-      if k in { tyVar, tyRef, tyPtr, tyPointer }:
+      let k = param.typ.skipTypes({tyGenericInst, tyAlias}).kind
+      if k in {tyVar, tyRef, tyPtr, tyPointer}:
         add(result, "&")
       add(result, "$")
       add(result, name)
@@ -964,7 +965,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
   internalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex
   r.address = a.res
   var typ = skipTypes(m.sons[0].typ, abstractPtrs)
-  if typ.kind in {tyArray, tyArrayConstr}: first = firstOrd(typ.sons[0])
+  if typ.kind == tyArray: first = firstOrd(typ.sons[0])
   else: first = 0
   if optBoundsCheck in p.options and not isConstExpr(m.sons[1]):
     useMagic(p, "chckIndx")
@@ -985,8 +986,7 @@ proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) =
   var ty = skipTypes(n.sons[0].typ, abstractVarRange)
   if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
   case ty.kind
-  of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString,
-     tyVarargs:
+  of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs:
     genArrayAddr(p, n, r)
   of tyTuple:
     if p.target == targetPHP:
@@ -1066,8 +1066,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
     else:
       let kindOfIndexedExpr = skipTypes(n.sons[0].sons[0].typ, abstractVarRange).kind
       case kindOfIndexedExpr
-      of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString,
-          tyVarargs:
+      of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs:
         genArrayAddr(p, n.sons[0], r)
       of tyTuple:
         genFieldAddr(p, n.sons[0], r)
@@ -1387,13 +1386,13 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
     result = putToSeq("0", indirect)
   of tyFloat..tyFloat128:
     result = putToSeq("0.0", indirect)
-  of tyRange, tyGenericInst:
+  of tyRange, tyGenericInst, tyAlias:
     result = createVar(p, lastSon(typ), indirect)
   of tySet:
     result = putToSeq("{}" | "array()", indirect)
   of tyBool:
     result = putToSeq("false", indirect)
-  of tyArray, tyArrayConstr:
+  of tyArray:
     let length = int(lengthOrd(t))
     let e = elemType(t)
     let jsTyp = arrayTypeForElemType(e)
diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim
index 0aaf93579..b96a260b3 100644
--- a/compiler/jstypes.nim
+++ b/compiler/jstypes.nim
@@ -118,7 +118,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
          [name, genTypeInfo(p, typ.sons[0])])
 
 proc genEnumInfoPHP(p: PProc; t: PType): Rope =
-  let t = t.skipTypes({tyGenericInst, tyDistinct})
+  let t = t.skipTypes({tyGenericInst, tyDistinct, tyAlias})
   result = "$$NTI$1" % [rope(t.id)]
   p.declareGlobal(t.id, result)
   if containsOrIncl(p.g.typeInfoGenerated, t.id): return
@@ -137,7 +137,7 @@ proc genEnumInfoPHP(p: PProc; t: PType): Rope =
 proc genTypeInfo(p: PProc, typ: PType): Rope =
   if p.target == targetPHP:
     return makeJSString(typeToString(typ, preferModuleInfo))
-  let t = typ.skipTypes({tyGenericInst, tyDistinct})
+  let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias})
   result = "NTI$1" % [rope(t.id)]
   if containsOrIncl(p.g.typeInfoGenerated, t.id): return
   case t.kind
@@ -155,7 +155,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
     prepend(p.g.typeInfo, s)
     addf(p.g.typeInfo, "$1.base = $2;$n",
          [result, genTypeInfo(p, t.lastSon)])
-  of tyArrayConstr, tyArray:
+  of tyArray:
     var s =
       "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
               [result, rope(ord(t.kind))]
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 6a8eccb83..7da332335 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -441,7 +441,7 @@ proc newIntLit*(value: BiggestInt): PNode =
   result.typ = getSysType(tyInt)
 
 proc genHigh*(n: PNode): PNode =
-  if skipTypes(n.typ, abstractVar).kind in {tyArrayConstr, tyArray}:
+  if skipTypes(n.typ, abstractVar).kind == tyArray:
     result = newIntLit(lastOrd(skipTypes(n.typ, abstractVar)))
   else:
     result = newNodeI(nkCall, n.info, 2)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 926e67743..1602988dd 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -287,7 +287,8 @@ proc lsub(n: PNode): int
 proc litAux(n: PNode, x: BiggestInt, size: int): string =
   proc skip(t: PType): PType =
     result = t
-    while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal}:
+    while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct,
+                          tyOrdinal, tyAlias}:
       result = lastSon(result)
   if n.typ != nil and n.typ.skip.kind in {tyBool, tyEnum}:
     let enumfields = n.typ.skip.n
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 02c779ef0..7524d7388 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -102,8 +102,8 @@ proc commonType*(x, y: PType): PType =
   # if expressions, etc.:
   if x == nil: return x
   if y == nil: return y
-  var a = skipTypes(x, {tyGenericInst})
-  var b = skipTypes(y, {tyGenericInst})
+  var a = skipTypes(x, {tyGenericInst, tyAlias})
+  var b = skipTypes(y, {tyGenericInst, tyAlias})
   result = x
   if a.kind in {tyExpr, tyNil}: result = y
   elif b.kind in {tyExpr, tyNil}: result = x
@@ -115,10 +115,10 @@ proc commonType*(x, y: PType): PType =
     else:
       result = newType(tyTypeDesc, a.owner)
       rawAddSon(result, newType(tyNone, a.owner))
-  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
+  elif b.kind in {tyArray, tySet, tySequence} and
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
-    let idx = ord(b.kind in {tyArray, tyArrayConstr})
+    let idx = ord(b.kind == tyArray)
     if a.sons[idx].kind == tyEmpty: return y
   elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
     var nt: PType
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index c4116a814..c4dc13624 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -187,7 +187,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
   of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
       tyPtr, tyString, tyRef:
     defaultOp(c, t, body, x, y)
-  of tyArrayConstr, tyArray, tySequence:
+  of tyArray, tySequence:
     if tfHasAsgn in t.flags:
       if t.kind == tySequence:
         # XXX add 'nil' handling here
@@ -227,7 +227,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
      tyTypeDesc, tyGenericInvocation, tyForward:
     internalError(c.info, "assignment requested for type: " & typeToString(t))
   of tyOrdinal, tyRange,
-     tyGenericInst, tyFieldAccessor, tyStatic, tyVar:
+     tyGenericInst, tyFieldAccessor, tyStatic, tyVar, tyAlias:
     liftBodyAux(c, lastSon(t), body, x, y)
   of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("liftBodyAux")
 
@@ -276,7 +276,7 @@ proc liftBody(c: PContext; typ: PType; info: TLineInfo): PSym =
   #echo "Produced this ", n
 
 proc getAsgnOrLiftBody(c: PContext; typ: PType; info: TLineInfo): PSym =
-  let t = typ.skipTypes({tyGenericInst, tyVar})
+  let t = typ.skipTypes({tyGenericInst, tyVar, tyAlias})
   result = t.assignment
   if result.isNil:
     result = liftBody(c, t, info)
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index ca9b5effb..ae7bab89d 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -370,7 +370,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
 
 proc canDeref(n: PNode): bool {.inline.} =
   result = n.len >= 2 and (let t = n[1].typ;
-    t != nil and t.skipTypes({tyGenericInst}).kind in {tyPtr, tyRef})
+    t != nil and t.skipTypes({tyGenericInst, tyAlias}).kind in {tyPtr, tyRef})
 
 proc tryDeref(n: PNode): PNode =
   result = newNodeI(nkHiddenDeref, n.info)
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
index 85d106056..a8873bbe2 100644
--- a/compiler/semdestruct.nim
+++ b/compiler/semdestruct.nim
@@ -136,9 +136,9 @@ proc instantiateDestructor(c: PContext, typ: PType): PType =
     else:
       return nil
 
-  t = t.skipTypes({tyGenericInst})
+  t = t.skipTypes({tyGenericInst, tyAlias})
   case t.kind
-  of tySequence, tyArray, tyArrayConstr, tyOpenArray, tyVarargs:
+  of tySequence, tyArray, tyOpenArray, tyVarargs:
     t.destructor = analyzingDestructor
     if instantiateDestructor(c, t.sons[0]) != nil:
       t.destructor = getCompilerProc"nimDestroyRange"
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d3431de70..0a4e39878 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -238,7 +238,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
     case typ.kind
     of tySequence, tyString, tyCString, tyOpenArray, tyVarargs:
       n.typ = getSysType(tyInt)
-    of tyArrayConstr, tyArray:
+    of tyArray:
       n.typ = typ.sons[0] # indextype
     of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
       # do not skip the range!
@@ -373,7 +373,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
     for i in countup(0, sonsLen(n) - 1):
       changeType(n.sons[i], elemType(newType), check)
   of nkPar:
-    let tup = newType.skipTypes({tyGenericInst})
+    let tup = newType.skipTypes({tyGenericInst, tyAlias})
     if tup.kind != tyTuple:
       if tup.kind == tyObject: return
       globalError(n.info, "no tuple type for constructor")
@@ -416,7 +416,7 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
   if sonsLen(n) == 0:
     rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
   else:
-    var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
+    var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal, tyAlias})
     addSonSkipIntLit(typ, t)
   typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
   result = typ
@@ -522,7 +522,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
 
   # get the real type of the callee
   # it may be a proc var with a generic alias type, so we skip over them
-  var t = n.sons[0].typ.skipTypes({tyGenericInst})
+  var t = n.sons[0].typ.skipTypes({tyGenericInst, tyAlias})
 
   if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
     # BUGFIX: check for L-Value still needs to be done for the arguments!
@@ -888,18 +888,18 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
   else: illFormedAst(n)
 
 proc makeDeref(n: PNode): PNode =
-  var t = skipTypes(n.typ, {tyGenericInst})
+  var t = skipTypes(n.typ, {tyGenericInst, tyAlias})
   result = n
   if t.kind == tyVar:
     result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
     addSon(result, n)
-    t = skipTypes(t.sons[0], {tyGenericInst})
+    t = skipTypes(t.sons[0], {tyGenericInst, tyAlias})
   while t.kind in {tyPtr, tyRef}:
     var a = result
     let baseTyp = t.lastSon
     result = newNodeIT(nkHiddenDeref, n.info, baseTyp)
     addSon(result, a)
-    t = skipTypes(baseTyp, {tyGenericInst})
+    t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
 
 const
   tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
@@ -1013,7 +1013,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     while p != nil and p.selfSym == nil:
       p = p.next
     if p != nil and p.selfSym != nil:
-      var ty = skipTypes(p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
+      var ty = skipTypes(p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef,
+                                         tyAlias})
       while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
       var check: PNode = nil
       if ty.kind == tyObject:
@@ -1103,7 +1104,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
     ty = n.sons[0].typ
     return nil
-  ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
+  ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef, tyAlias})
   while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
   var check: PNode = nil
   if ty.kind == tyObject:
@@ -1171,7 +1172,7 @@ proc semDeref(c: PContext, n: PNode): PNode =
   checkSonsLen(n, 1)
   n.sons[0] = semExprWithType(c, n.sons[0])
   result = n
-  var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
+  var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyAlias})
   case t.kind
   of tyRef, tyPtr: n.typ = t.lastSon
   else: result = nil
@@ -1190,9 +1191,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # make sure we don't evaluate generic macros/templates
   n.sons[0] = semExprWithType(c, n.sons[0],
                               {efNoProcvarCheck, efNoEvaluateGeneric})
-  let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
+  let arr = skipTypes(n.sons[0].typ, {tyGenericInst,
+                                      tyVar, tyPtr, tyRef, tyAlias})
   case arr.kind
-  of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
+  of tyArray, tyOpenArray, tyVarargs, tySequence, tyString,
      tyCString:
     if n.len != 2: return nil
     n.sons[0] = makeDeref(n.sons[0])
@@ -1220,7 +1222,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     c.p.bracketExpr = n.sons[0]
     # [] operator for tuples requires constant expression:
     n.sons[1] = semConstExpr(c, n.sons[1])
-    if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal}).kind in
+    if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias}).kind in
         {tyInt..tyInt64}:
       var idx = getOrdValue(n.sons[1])
       if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
@@ -1364,7 +1366,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
   # a = b # both are vars, means: a[] = b[]
   # a = b # b no 'var T' means: a = addr(b)
   var le = a.typ
-  if (skipTypes(le, {tyGenericInst}).kind != tyVar and
+  if (skipTypes(le, {tyGenericInst, tyAlias}).kind != tyVar and
         isAssignable(c, a) == arNone) or
       skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs}:
     # Direct assignment to a discriminant is allowed!
@@ -1456,13 +1458,13 @@ proc semProcBody(c: PContext, n: PNode): PNode =
   closeScope(c)
 
 proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
-  var t = skipTypes(restype, {tyGenericInst})
+  var t = skipTypes(restype, {tyGenericInst, tyAlias})
   case t.kind
   of tyVar:
     n.sons[0] = takeImplicitAddr(c, n.sons[0])
   of tyTuple:
     for i in 0.. <t.sonsLen:
-      var e = skipTypes(t.sons[i], {tyGenericInst})
+      var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias})
       if e.kind == tyVar:
         if n.sons[0].kind == nkPar:
           n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
@@ -1904,17 +1906,17 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
         n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2])
         if typ == nil:
           typ = skipTypes(n.sons[i].sons[1].typ,
-                          {tyGenericInst, tyVar, tyOrdinal})
+                          {tyGenericInst, tyVar, tyOrdinal, tyAlias})
         n.sons[i].typ = n.sons[i].sons[2].typ # range node needs type too
       elif n.sons[i].kind == nkRange:
         # already semchecked
         if typ == nil:
           typ = skipTypes(n.sons[i].sons[0].typ,
-                          {tyGenericInst, tyVar, tyOrdinal})
+                          {tyGenericInst, tyVar, tyOrdinal, tyAlias})
       else:
         n.sons[i] = semExprWithType(c, n.sons[i])
         if typ == nil:
-          typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
+          typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal, tyAlias})
     if not isOrdinalType(typ):
       localError(n.info, errOrdinalTypeExpected)
       typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
@@ -2046,8 +2048,8 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n
   result.typ = t
   result.kind = nkObjConstr
-  t = skipTypes(t, {tyGenericInst})
-  if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst})
+  t = skipTypes(t, {tyGenericInst, tyAlias})
+  if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst, tyAlias})
   if t.kind != tyObject:
     localError(n.info, errGenerated, "object constructor needs an object type")
     return
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 42fa60781..0f1138e04 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -538,7 +538,8 @@ proc getArrayConstr(m: PSym, n: PNode): PNode =
 
 proc foldArrayAccess(m: PSym, n: PNode): PNode =
   var x = getConstExpr(m, n.sons[0])
-  if x == nil or x.typ.skipTypes({tyGenericInst}).kind == tyTypeDesc: return
+  if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias}).kind == tyTypeDesc:
+    return
 
   var y = getConstExpr(m, n.sons[1])
   if y == nil: return
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
index 6cd5c4a3c..a6024a42f 100644
--- a/compiler/semmacrosanity.nim
+++ b/compiler/semmacrosanity.nim
@@ -61,7 +61,7 @@ proc annotateType*(n: PNode, t: PType) =
     else:
       globalError(n.info, "() must have a tuple type")
   of nkBracket:
-    if x.kind in {tyArrayConstr, tyArray, tySequence, tyOpenArray}:
+    if x.kind in {tyArray, tySequence, tyOpenArray}:
       n.typ = t
       for m in n: annotateType(m, x.elemType)
     else:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 0c6f6848e..5f74e484a 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -471,7 +471,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     # this can only happen for errornous var statements:
     if typ == nil: continue
     typeAllowedCheck(a.info, typ, symkind)
-    var tup = skipTypes(typ, {tyGenericInst})
+    var tup = skipTypes(typ, {tyGenericInst, tyAlias})
     if a.kind == nkVarTuple:
       if tup.kind != tyTuple:
         localError(a.info, errXExpected, "tuple")
@@ -583,7 +583,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
   result = n
   var length = sonsLen(n)
   let iterBase = n.sons[length-2].typ
-  var iter = skipTypes(iterBase, {tyGenericInst})
+  var iter = skipTypes(iterBase, {tyGenericInst, tyAlias})
   # length == 3 means that there is one for loop variable
   # and thus no tuple unpacking:
   if iter.kind != tyTuple or length == 3:
@@ -777,7 +777,7 @@ proc checkForMetaFields(n: PNode) =
     let t = n.sym.typ
     case t.kind
     of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyPtr, tyRef,
-       tyProc, tyGenericInvocation, tyGenericInst:
+       tyProc, tyGenericInvocation, tyGenericInst, tyAlias:
       let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
       for i in start .. <t.sons.len:
         checkMeta(t.sons[i])
@@ -1366,7 +1366,9 @@ proc semMethod(c: PContext, n: PNode): PNode =
     for col in countup(1, sonsLen(tt)-1):
       let t = tt.sons[col]
       if t != nil and t.kind == tyGenericInvocation:
-        var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst, tyGenericInvocation, tyGenericBody})
+        var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst,
+                                      tyGenericInvocation, tyGenericBody,
+                                      tyAlias})
         if x.kind == tyObject and t.len-1 == result.sons[genericParamsPos].len:
           foundObj = true
           x.methods.safeAdd((col,s))
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5f47bca5c..9c84996eb 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -95,7 +95,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
   if sonsLen(n) == 2:
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
-    if base.kind == tyGenericInst: base = lastSon(base)
+    if base.kind in {tyGenericInst, tyAlias}: base = lastSon(base)
     if base.kind != tyGenericParam:
       if not isOrdinalType(base):
         localError(n.info, errOrdinalTypeExpected)
@@ -145,7 +145,8 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
         isNilable = true
       else:
         let region = semTypeNode(c, ni, nil)
-        if region.skipTypes({tyGenericInst}).kind notin {tyError, tyObject}:
+        if region.skipTypes({tyGenericInst, tyAlias}).kind notin {
+              tyError, tyObject}:
           message n[i].info, errGenerated, "region needs to be an object type"
         addSonSkipIntLit(result, region)
     addSonSkipIntLit(result, base)
@@ -266,7 +267,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     # 3 = length(array indx base)
     let indx = semArrayIndex(c, n[1])
     var indxB = indx
-    if indxB.kind == tyGenericInst: indxB = lastSon(indxB)
+    if indxB.kind in {tyGenericInst, tyAlias}: indxB = lastSon(indxB)
     if indxB.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
       if not isOrdinalType(indxB):
         localError(n.sons[1].info, errOrdinalTypeExpected)
@@ -647,7 +648,7 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
   result = t
   if result.kind == tyGenericInvocation:
     result = result.sons[0]
-  while result.kind in {tyGenericInst, tyGenericBody, tyRef, tyPtr}:
+  while result.kind in {tyGenericInst, tyGenericBody, tyRef, tyPtr, tyAlias}:
     result = lastSon(result)
 
 proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
@@ -950,7 +951,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
       if isType: localError(a.info, "':' expected")
       if kind in {skTemplate, skMacro}:
         typ = newTypeS(tyExpr, c)
-    elif skipTypes(typ, {tyGenericInst}).kind == tyVoid:
+    elif skipTypes(typ, {tyGenericInst, tyAlias}).kind == tyVoid:
       continue
     for j in countup(0, length-3):
       var arg = newSymG(skParam, a.sons[j], c)
@@ -982,7 +983,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
   if r != nil:
     # turn explicit 'void' return type into 'nil' because the rest of the
     # compiler only checks for 'nil':
-    if skipTypes(r, {tyGenericInst}).kind != tyVoid:
+    if skipTypes(r, {tyGenericInst, tyAlias}).kind != tyVoid:
       # 'auto' as a return type does not imply a generic:
       if r.kind == tyAnything:
         # 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
@@ -1180,7 +1181,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       result = semRangeAux(c, n, prev)
     elif n[0].kind == nkNilLit and n.len == 2:
       result = semTypeNode(c, n.sons[1], prev)
-      if result.skipTypes({tyGenericInst}).kind in NilableTypes+GenericTypes:
+      if result.skipTypes({tyGenericInst, tyAlias}).kind in NilableTypes+GenericTypes:
         if tfNotNil in result.flags:
           result = freshType(result, prev)
           result.flags.excl(tfNotNil)
@@ -1208,7 +1209,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         case n.len
         of 3:
           result = semTypeNode(c, n.sons[1], prev)
-          if result.skipTypes({tyGenericInst}).kind in NilableTypes+GenericTypes and
+          if result.skipTypes({tyGenericInst, tyAlias}).kind in NilableTypes+GenericTypes and
               n.sons[2].kind == nkNilLit:
             result = freshType(result, prev)
             result.flags.incl(tfNotNil)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index b42d58474..a2626ffe4 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -459,7 +459,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
           var r = replaceTypeVarsT(cl, result.sons[i])
           if result.kind == tyObject:
             # carefully coded to not skip the precious tyGenericInst:
-            let r2 = r.skipTypes({tyGenericInst})
+            let r2 = r.skipTypes({tyGenericInst, tyAlias})
             if r2.kind in {tyPtr, tyRef}:
               r = skipTypes(r2, {tyPtr, tyRef})
           result.sons[i] = r
diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim
index bb34ff3d2..7b76fe010 100644
--- a/compiler/sighashes.nim
+++ b/compiler/sighashes.nim
@@ -159,7 +159,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
       c.hashSym(t.sym)
     else:
       lowlevel(t.id)
-  of tyRef, tyPtr, tyGenericBody:
+  of tyRef, tyPtr, tyGenericBody, tyAlias:
     c.hashType t.lastSon, flags
   of tyUserTypeClass:
     if t.sym != nil and t.sym.owner != nil:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 15171874f..16358b1a8 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -158,7 +158,7 @@ proc sumGeneric(t: PType): int =
   var isvar = 1
   while true:
     case t.kind
-    of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyArrayConstr,
+    of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct,
         tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody:
       t = t.lastSon
       inc result
@@ -175,6 +175,7 @@ proc sumGeneric(t: PType): int =
       for i in 0 .. <t.len: result += t.sons[i].sumGeneric
       break
     of tyGenericParam, tyExpr, tyStatic, tyStmt: break
+    of tyAlias: t = t.lastSon
     of tyBool, tyChar, tyEnum, tyObject, tyPointer,
         tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
         tyUInt..tyUInt64:
@@ -273,11 +274,6 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
 proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
 proc concreteType(c: TCandidate, t: PType): PType =
   case t.kind
-  of tyArrayConstr:
-    # make it an array
-    result = newType(tyArray, t.owner)
-    addSonSkipIntLit(result, t.sons[0]) # XXX: t.owner is wrong for ID!
-    addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type?
   of tyNil:
     result = nil              # what should it be?
   of tyTypeDesc:
@@ -394,7 +390,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
       inc ptrs
       skipped = skippedPtr
       r = r.lastSon
-    of tyGenericBody, tyGenericInst:
+    of tyGenericBody, tyGenericInst, tyAlias:
       r = r.lastSon
     else:
       break
@@ -692,7 +688,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # for example, but unfortunately `prepareOperand` is not called in certain
   # situation when nkDotExpr are rotated to nkDotCalls
 
-  if a.kind == tyGenericInst and
+  if a.kind in {tyGenericInst, tyAlias} and
       skipTypes(f, {tyVar}).kind notin {
         tyGenericBody, tyGenericInvocation,
         tyGenericInst, tyGenericParam} + tyTypeClasses:
@@ -799,11 +795,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base)
     else: result = typeRel(c, f.base, aOrig)
     subtypeCheck()
-  of tyArray, tyArrayConstr:
-    # tyArrayConstr cannot happen really, but
-    # we wanna be safe here
+  of tyArray:
     case a.kind
-    of tyArray, tyArrayConstr:
+    of tyArray:
       var fRange = f.sons[0]
       if fRange.kind == tyGenericParam:
         var prev = PType(idTableGet(c.bindings, fRange))
@@ -848,7 +842,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyOpenArray, tyVarargs:
       result = typeRel(c, base(f), base(a))
       if result < isGeneric: result = isNone
-    of tyArray, tyArrayConstr:
+    of tyArray:
       if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
         result = isSubtype
       elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
@@ -984,7 +978,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyEmpty, tyVoid:
     if a.kind == f.kind: result = isEqual
 
-  of tyGenericInst:
+  of tyGenericInst, tyAlias:
     result = typeRel(c, lastSon(f), a)
 
   of tyGenericBody:
@@ -1090,7 +1084,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyBuiltInTypeClass:
     considerPreviousT:
       let targetKind = f.sons[0].kind
-      if targetKind == a.skipTypes({tyRange, tyGenericInst, tyBuiltInTypeClass}).kind or
+      if targetKind == a.skipTypes({tyRange, tyGenericInst, tyBuiltInTypeClass, tyAlias}).kind or
          (targetKind in {tyProc, tyPointer} and a.kind == tyNil):
         put(c, f, a)
         return isGeneric
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 39689099a..888e80085 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -201,7 +201,7 @@ proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
     let m = s.getModule()
     if m != nil and sfSystemModule in m.flags:
       if s.kind == skType: return
-      var exp = s.typ.sons[1].skipTypes({tyGenericInst, tyVar})
+      var exp = s.typ.sons[1].skipTypes({tyGenericInst, tyVar, tyAlias})
       if exp.kind == tyVarargs: exp = elemType(exp)
       if exp.kind in {tyExpr, tyStmt, tyGenericParam, tyAnything}: return
     result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg)
@@ -267,7 +267,7 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
       t = t.sons[0]
     suggestOperations(c, n, typ, outputs)
   else:
-    typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef})
+    typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef, tyAlias})
     if typ.kind == tyObject:
       var t = typ
       while true:
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 5cd5e298b..4b6bff197 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -95,7 +95,7 @@ proc getCurrOwner(c: PTransf): PSym =
 
 proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
   let r = newSym(skTemp, getIdent(genPrefix), getCurrOwner(c), info)
-  r.typ = typ #skipTypes(typ, {tyGenericInst})
+  r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias})
   incl(r.flags, sfFromGeneric)
   let owner = getCurrOwner(c)
   if owner.isIterator and not c.tooEarly:
@@ -326,7 +326,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
   # c.transCon.forStmt.len == 3 means that there is one for loop variable
   # and thus no tuple unpacking:
   if e.typ.isNil: return result # can happen in nimsuggest for unknown reasons
-  if skipTypes(e.typ, {tyGenericInst}).kind == tyTuple and
+  if skipTypes(e.typ, {tyGenericInst, tyAlias}).kind == tyTuple and
       c.transCon.forStmt.len != 3:
     e = skipConv(e)
     if e.kind == nkPar:
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 08a1a8c1f..7208f7d7b 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -101,7 +101,7 @@ proc isDeepConstExpr*(n: PNode): bool =
       if not isDeepConstExpr(n.sons[i]): return false
     if n.typ.isNil: result = true
     else:
-      let t = n.typ.skipTypes({tyGenericInst, tyDistinct})
+      let t = n.typ.skipTypes({tyGenericInst, tyDistinct, tyAlias})
       if t.kind in {tyRef, tyPtr}: return false
       if t.kind != tyObject or not isCaseObj(t.n):
         result = true
diff --git a/compiler/types.nim b/compiler/types.nim
index ebbc7ee69..7fc0af43e 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -54,14 +54,16 @@ const
   # TODO: Remove tyTypeDesc from each abstractX and (where necessary)
   # replace with typedescX
   abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
-                   tyTypeDesc}
-  abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc}
-  abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc}
+                   tyTypeDesc, tyAlias}
+  abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc,
+                  tyAlias}
+  abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc,
+                    tyAlias}
   abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
-                       tyTypeDesc}
-  abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc}
+                       tyTypeDesc, tyAlias}
+  abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias}
 
-  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc}
+  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias}
   # typedescX is used if we're sure tyTypeDesc should be included (or skipped)
   typedescPtrs* = abstractPtrs + {tyTypeDesc}
   typedescInst* = abstractInst + {tyTypeDesc}
@@ -115,7 +117,7 @@ proc isFloatLit*(t: PType): bool {.inline.} =
 proc isCompatibleToCString(a: PType): bool =
   if a.kind == tyArray:
     if (firstOrd(a.sons[0]) == 0) and
-        (skipTypes(a.sons[0], {tyRange, tyGenericInst}).kind in
+        (skipTypes(a.sons[0], {tyRange, tyGenericInst, tyAlias}).kind in
             {tyInt..tyInt64, tyUInt..tyUInt64}) and
         (a.sons[1].kind == tyChar):
       result = true
@@ -139,8 +141,8 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
 proc elemType*(t: PType): PType =
   assert(t != nil)
   case t.kind
-  of tyGenericInst, tyDistinct: result = elemType(lastSon(t))
-  of tyArray, tyArrayConstr: result = t.sons[1]
+  of tyGenericInst, tyDistinct, tyAlias: result = elemType(lastSon(t))
+  of tyArray: result = t.sons[1]
   else: result = t.lastSon
   assert(result != nil)
 
@@ -149,12 +151,12 @@ proc isOrdinalType(t: PType): bool =
   const
     # caution: uint, uint64 are no ordinal types!
     baseKinds = {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum}
-    parentKinds = {tyRange, tyOrdinal, tyGenericInst, tyDistinct}
+    parentKinds = {tyRange, tyOrdinal, tyGenericInst, tyAlias, tyDistinct}
   t.kind in baseKinds or (t.kind in parentKinds and isOrdinalType(t.sons[0]))
 
 proc enumHasHoles(t: PType): bool =
   var b = t
-  while b.kind in {tyRange, tyGenericInst}: b = b.sons[0]
+  while b.kind in {tyRange, tyGenericInst, tyAlias}: b = b.sons[0]
   result = b.kind == tyEnum and tfEnumHasHoles in b.flags
 
 proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
@@ -179,7 +181,7 @@ proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
   if result: return
   if not containsOrIncl(marker, t.id):
     case t.kind
-    of tyGenericInst, tyGenericBody:
+    of tyGenericInst, tyGenericBody, tyAlias:
       result = iterOverTypeAux(marker, lastSon(t), iter, closure)
     else:
       for i in countup(0, sonsLen(t) - 1):
@@ -229,9 +231,9 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
     if t.sons[0] != nil:
       result = searchTypeForAux(t.sons[0].skipTypes(skipPtrs), predicate, marker)
     if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
-  of tyGenericInst, tyDistinct:
+  of tyGenericInst, tyDistinct, tyAlias:
     result = searchTypeForAux(lastSon(t), predicate, marker)
-  of tyArray, tyArrayConstr, tySet, tyTuple:
+  of tyArray, tySet, tyTuple:
     for i in countup(0, sonsLen(t) - 1):
       result = searchTypeForAux(t.sons[i], predicate, marker)
       if result: return
@@ -272,9 +274,9 @@ proc analyseObjectWithTypeFieldAux(t: PType,
       if res == frHeader: result = frHeader
     if result == frNone:
       if isObjectWithTypeFieldPredicate(t): result = frHeader
-  of tyGenericInst, tyDistinct:
+  of tyGenericInst, tyDistinct, tyAlias:
     result = analyseObjectWithTypeFieldAux(lastSon(t), marker)
-  of tyArray, tyArrayConstr, tyTuple:
+  of tyArray, tyTuple:
     for i in countup(0, sonsLen(t) - 1):
       res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
       if res != frNone:
@@ -331,8 +333,7 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
   var t = skipTypes(typ, abstractInst-{tyTypeDesc})
   if tfAcyclic in t.flags: return
   case t.kind
-  of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
-     tyVarargs:
+  of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
     if not containsOrIncl(marker, t.id):
       for i in countup(0, sonsLen(t) - 1):
         result = canFormAcycleAux(marker, t.sons[i], startId)
@@ -499,9 +500,6 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     else:
       result = "array[" & typeToString(t.sons[0]) & ", " &
           typeToString(t.sons[1]) & ']'
-  of tyArrayConstr:
-    result = "Array constructor[" & rangeToStr(t.sons[0].n) & ", " &
-        typeToString(t.sons[1]) & ']'
   of tySequence:
     result = "seq[" & typeToString(t.sons[0]) & ']'
   of tyOrdinal:
@@ -580,7 +578,7 @@ proc firstOrd(t: PType): BiggestInt =
   of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
     result = 0
   of tySet, tyVar: result = firstOrd(t.sons[0])
-  of tyArray, tyArrayConstr: result = firstOrd(t.sons[0])
+  of tyArray: result = firstOrd(t.sons[0])
   of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
@@ -600,7 +598,7 @@ proc firstOrd(t: PType): BiggestInt =
     else:
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor:
+  of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor, tyAlias:
     result = firstOrd(lastSon(t))
   of tyOrdinal:
     if t.len > 0: result = firstOrd(lastSon(t))
@@ -614,7 +612,7 @@ proc lastOrd(t: PType): BiggestInt =
   of tyBool: result = 1
   of tyChar: result = 255
   of tySet, tyVar: result = lastOrd(t.sons[0])
-  of tyArray, tyArrayConstr: result = lastOrd(t.sons[0])
+  of tyArray: result = lastOrd(t.sons[0])
   of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
@@ -636,7 +634,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, tyTypeDesc, tyFieldAccessor:
+  of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor, tyAlias:
     result = lastOrd(lastSon(t))
   of tyProxy: result = 0
   of tyOrdinal:
@@ -778,8 +776,8 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
       var x = a.sons[i]
       var y = b.sons[i]
       if IgnoreTupleFields in c.flags:
-        x = skipTypes(x, {tyRange, tyGenericInst})
-        y = skipTypes(y, {tyRange, tyGenericInst})
+        x = skipTypes(x, {tyRange, tyGenericInst, tyAlias})
+        y = skipTypes(y, {tyRange, tyGenericInst, tyAlias})
 
       result = sameTypeAux(x, y, c)
       if not result: return
@@ -833,8 +831,8 @@ proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
     var x = a.typ
     var y = b.typ
     if IgnoreTupleFields in c.flags:
-      if x != nil: x = skipTypes(x, {tyRange, tyGenericInst})
-      if y != nil: y = skipTypes(y, {tyRange, tyGenericInst})
+      if x != nil: x = skipTypes(x, {tyRange, tyGenericInst, tyAlias})
+      if y != nil: y = skipTypes(y, {tyRange, tyGenericInst, tyAlias})
     if sameTypeOrNilAux(x, y, c):
       case a.kind
       of nkSym:
@@ -888,8 +886,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
 
   if x == y: return true
-  var a = skipTypes(x, {tyGenericInst})
-  var b = skipTypes(y, {tyGenericInst})
+  var a = skipTypes(x, {tyGenericInst, tyAlias})
+  var b = skipTypes(y, {tyGenericInst, tyAlias})
   assert(a != nil)
   assert(b != nil)
   if a.kind != b.kind:
@@ -957,7 +955,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     if result and ExactGenericParams in c.flags:
       result = a.sym.position == b.sym.position
   of tyGenericInvocation, tyGenericBody, tySequence,
-     tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
+     tyOpenArray, tySet, tyRef, tyPtr, tyVar,
      tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyFieldAccessor:
     cycleCheck()
     if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
@@ -970,7 +968,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
         sameValue(a.n.sons[0], b.n.sons[0]) and
         sameValue(a.n.sons[1], b.n.sons[1])
-  of tyGenericInst: discard
+  of tyGenericInst, tyAlias: discard
   of tyNone: result = false
   of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("sameFlags")
 
@@ -1117,7 +1115,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     result = nil
   of tyOrdinal:
     if kind != skParam: result = t
-  of tyGenericInst, tyDistinct:
+  of tyGenericInst, tyDistinct, tyAlias:
     result = typeAllowedAux(marker, lastSon(t), kind, flags)
   of tyRange:
     if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin
@@ -1136,7 +1134,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     else: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
   of tyPtr:
     result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
-  of tyArrayConstr, tySet:
+  of tySet:
     for i in countup(0, sonsLen(t) - 1):
       result = typeAllowedAux(marker, t.sons[i], kind, flags)
       if result != nil: break
@@ -1250,7 +1248,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
       result = szIllegalRecursion
     else: result = ptrSize
     a = result
-  of tyArray, tyArrayConstr:
+  of tyArray:
     let elemSize = computeSizeAux(typ.sons[1], a)
     if elemSize < 0: return elemSize
     result = lengthOrd(typ.sons[0]) * elemSize
@@ -1304,7 +1302,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     if result < 0: return
     if a < maxAlign: a = maxAlign
     result = align(result, a)
-  of tyGenericInst, tyDistinct, tyGenericBody:
+  of tyGenericInst, tyDistinct, tyGenericBody, tyAlias:
     result = computeSizeAux(lastSon(typ), a)
   of tyTypeDesc:
     result = computeSizeAux(typ.base, a)
@@ -1466,10 +1464,10 @@ proc skipConvTakeType*(n: PNode): PNode =
 proc isEmptyContainer*(t: PType): bool =
   case t.kind
   of tyExpr, tyNil: result = true
-  of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
+  of tyArray: result = t.sons[1].kind == tyEmpty
   of tySet, tySequence, tyOpenArray, tyVarargs:
     result = t.sons[0].kind == tyEmpty
-  of tyGenericInst: result = isEmptyContainer(t.lastSon)
+  of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon)
   else: result = false
 
 proc takeType*(formal, arg: PType): PType =
@@ -1480,8 +1478,8 @@ proc takeType*(formal, arg: PType): PType =
     result = formal
   elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and
       arg.isEmptyContainer:
-    let a = copyType(arg.skipTypes({tyGenericInst}), arg.owner, keepId=false)
-    a.sons[ord(arg.kind in {tyArray, tyArrayConstr})] = formal.sons[0]
+    let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), arg.owner, keepId=false)
+    a.sons[ord(arg.kind == tyArray)] = formal.sons[0]
     result = a
   elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind:
     result = formal
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index bd6908722..30b5c17a2 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -136,7 +136,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
   of tyStmt: result = atomicType("stmt", mStmt)
   of tyVoid: result = atomicType("void", mVoid)
   of tyEmpty: result = atomicType("empty", mNone)
-  of tyArrayConstr, tyArray:
+  of tyArray:
     result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
     result.add atomicType("array", mArray)
     if inst and t.sons[0].kind == tyRange:
@@ -159,7 +159,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
     result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
     for i in 0 .. < t.len:
       result.add mapTypeToAst(t.sons[i], info)
-  of tyGenericInst:
+  of tyGenericInst, tyAlias:
     if inst:
       if allowRecursion:
         result = mapTypeToAstR(t.lastSon, info)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index ed8f3f338..69249abfe 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1482,7 +1482,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
       getNullValueAux(skipTypes(base, skipPtrs).n, result)
       base = base.sons[0]
     getNullValueAux(t.n, result)
-  of tyArray, tyArrayConstr:
+  of tyArray:
     result = newNodeIT(nkBracket, info, t)
     for i in countup(0, int(lengthOrd(t)) - 1):
       addSon(result, getNullValue(elemType(t), info))
diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim
index c08c5d249..51301b931 100644
--- a/compiler/vmmarshal.nim
+++ b/compiler/vmmarshal.nim
@@ -102,7 +102,7 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
       else:
         storeAny(s, t.lastSon, a[i], stored)
     s.add("]")
-  of tyRange, tyGenericInst: storeAny(s, t.lastSon, a, stored)
+  of tyRange, tyGenericInst, tyAlias: storeAny(s, t.lastSon, a, stored)
   of tyEnum:
     # we need a slow linear search because of enums with holes:
     for e in items(t.n):
@@ -275,7 +275,7 @@ proc loadAny(p: var JsonParser, t: PType,
       next(p)
       return
     raiseParseErr(p, "float expected")
-  of tyRange, tyGenericInst: result = loadAny(p, t.lastSon, tab)
+  of tyRange, tyGenericInst, tyAlias: result = loadAny(p, t.lastSon, tab)
   else:
     internalError "cannot marshal at compile-time " & t.typeToString