summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim8
-rw-r--r--compiler/astalgo.nim5
-rw-r--r--compiler/canonicalizer.nim3
-rw-r--r--compiler/jsgen.nim6
-rw-r--r--compiler/lexer.nim3
-rw-r--r--compiler/parser.nim19
-rw-r--r--compiler/pragmas.nim18
-rw-r--r--compiler/renderer.nim8
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semcall.nim42
-rw-r--r--compiler/semdata.nim16
-rw-r--r--compiler/semexprs.nim210
-rw-r--r--compiler/seminst.nim44
-rw-r--r--compiler/semstmts.nim55
-rw-r--r--compiler/semtypes.nim36
-rw-r--r--compiler/semtypinst.nim13
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/transf.nim2
-rw-r--r--compiler/types.nim1
-rw-r--r--compiler/wordrecg.nim3
-rw-r--r--doc/grammar.txt4
-rw-r--r--doc/manual/stmts.txt59
-rw-r--r--lib/core/macros.nim7
-rw-r--r--lib/impure/nre.nim4
-rw-r--r--lib/pure/json.nim62
-rw-r--r--lib/pure/net.nim2
-rw-r--r--lib/pure/parsecfg.nim6
-rw-r--r--lib/pure/poly.nim2
-rw-r--r--lib/pure/securehash.nim2
-rw-r--r--lib/pure/streams.nim2
-rw-r--r--lib/pure/times.nim2
-rw-r--r--lib/system.nim5
-rw-r--r--lib/system/ansi_c.nim4
-rw-r--r--lib/system/excpt.nim8
-rw-r--r--lib/system/gc_common.nim4
-rw-r--r--lib/system/nimscript.nim4
-rw-r--r--tests/casestmt/tcaseexpr1.nim2
-rw-r--r--tests/generics/tbadgenericlambda.nim2
-rw-r--r--tests/generics/tgeneric0.nim2
-rw-r--r--tests/generics/tgenericlambda.nim6
-rw-r--r--tests/macros/tclosuremacro.nim2
-rw-r--r--tests/misc/tupcomingfeatures.nim39
-rw-r--r--tests/stdlib/nre/init.nim2
-rw-r--r--tests/template/tit.nim2
-rw-r--r--tests/testament/categories.nim2
-rw-r--r--tests/tuples/tuple_with_nil.nim4
-rw-r--r--tests/typerel/trettypeinference.nim6
-rw-r--r--todo.txt3
-rw-r--r--web/news.txt18
49 files changed, 446 insertions, 319 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 2ce0afcc3..fecbefd7e 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -298,6 +298,7 @@ const
   sfWrittenTo* = sfBorrow             # param is assigned to
   sfEscapes* = sfProcvar              # param escapes
   sfBase* = sfDiscriminant
+  sfIsSelf* = sfOverriden             # param is 'self'
 
 const
   # getting ready for the future expr/stmt merge
@@ -458,11 +459,11 @@ type
     tfByCopy,         # pass object/tuple by copy (C backend)
     tfByRef,          # pass object/tuple by reference (C backend)
     tfIterator,       # type is really an iterator, not a tyProc
-    tfShared,         # type is 'shared'
+    tfPartial,        # type is declared as 'partial'
     tfNotNil,         # type cannot be 'nil'
 
     tfNeedsInit,      # type constains a "not nil" constraint somewhere or some
-                      # other type so that it requires initalization
+                      # other type so that it requires initialization
     tfVarIsPtr,       # 'var' type is translated like 'ptr' even in C++ mode
     tfHasMeta,        # type contains "wildcard" sub-types such as generic params
                       # or other type classes
@@ -533,7 +534,7 @@ const
   skError* = skUnknown
 
   # type flags that are essential for type equality:
-  eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr}
+  eqTypeFlags* = {tfIterator, tfNotNil, tfVarIsPtr}
 
 type
   TMagic* = enum # symbols that require compiler magic:
@@ -753,7 +754,6 @@ type
   TScope* = object
     depthLevel*: int
     symbols*: TStrTable
-    usingSyms*: seq[PNode]
     parent*: PScope
 
   PScope* = ref TScope
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 1a70875d4..4772009b4 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -635,7 +635,7 @@ proc reallySameIdent(a, b: string): bool {.inline.} =
   else:
     result = true
 
-proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
+proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.discardable.} =
   # returns true if n is already in the string table:
   # It is essential that `n` is written nevertheless!
   # This way the newest redefinition is picked by the semantic analyses!
@@ -654,7 +654,8 @@ proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
       replaceSlot = h
     h = nextTry(h, high(t.data))
   if replaceSlot >= 0:
-    t.data[replaceSlot] = n # overwrite it with newer definition!
+    if not onConflictKeepOld:
+      t.data[replaceSlot] = n # overwrite it with newer definition!
     return true             # found it
   elif mustRehash(len(t.data), t.counter):
     strTableEnlarge(t)
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
index 9afe4ab10..089bce302 100644
--- a/compiler/canonicalizer.nim
+++ b/compiler/canonicalizer.nim
@@ -158,7 +158,6 @@ proc hashType(c: var MD5Context, t: PType) =
     if tfThread in t.flags: c &= ".thread"
   else:
     for i in 0.. <t.len: c.hashType(t.sons[i])
-  if tfShared in t.flags: c &= "shared"
   if tfNotNil in t.flags: c &= "not nil"
 
 proc canonConst(n: PNode): TUid =
@@ -276,7 +275,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
     return
   # we need no surrounding [] here because the type is in a line of its own
   if t.kind == tyForward: internalError("encodeType: tyForward")
-  # for the new rodfile viewer we use a preceeding [ so that the data section
+  # for the new rodfile viewer we use a preceding [ so that the data section
   # can easily be disambiguated:
   add(result, '[')
   encodeVInt(ord(t.kind), result)
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 8f1f8a832..d6b546d8b 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -192,7 +192,7 @@ proc mangleName(s: PSym; target: TTarget): Rope =
           x.add("HEX" & toHex(ord(c), 2))
         inc i
       result = rope(x)
-    if s.name.s != "this":
+    if s.name.s != "this" and s.kind != skField:
       add(result, "_")
       add(result, rope(s.id))
     s.loc.r = result
@@ -891,10 +891,12 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
         r.res = "$1['$2']" % [r.res, f.loc.r]
   r.kind = resExpr
 
+proc genAddr(p: PProc, n: PNode, r: var TCompRes)
+
 proc genCheckedFieldAddr(p: PProc, n: PNode, r: var TCompRes) =
   let m = if n.kind == nkHiddenAddr: n.sons[0] else: n
   internalAssert m.kind == nkCheckedFieldExpr
-  genFieldAddr(p, m.sons[0], r) # XXX
+  genAddr(p, m, r) # XXX
 
 proc genCheckedFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
   genFieldAccess(p, n.sons[0], r) # XXX
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index fc43f8d6a..69a0fea2a 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -44,7 +44,8 @@ type
     tkLet,
     tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
     tkObject, tkOf, tkOr, tkOut,
-    tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkStatic,
+    tkProc, tkPtr, tkRaise, tkRef, tkReturn,
+    tkShl, tkShr, tkStatic,
     tkTemplate,
     tkTry, tkTuple, tkType, tkUsing,
     tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
diff --git a/compiler/parser.nim b/compiler/parser.nim
index c4681a5cd..f22177ac1 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -804,20 +804,24 @@ proc parsePragma(p: var TParser): PNode =
   else: parMessage(p, errTokenExpected, ".}")
   dec p.inPragma
 
-proc identVis(p: var TParser): PNode =
+proc identVis(p: var TParser; allowDot=false): PNode =
   #| identVis = symbol opr?  # postfix position
+  #| identVisDot = symbol '.' optInd symbol opr?
   var a = parseSymbol(p)
   if p.tok.tokType == tkOpr:
     result = newNodeP(nkPostfix, p)
     addSon(result, newIdentNodeP(p.tok.ident, p))
     addSon(result, a)
     getTok(p)
+  elif p.tok.tokType == tkDot and allowDot:
+    result = dotExpr(p, a)
   else:
     result = a
 
-proc identWithPragma(p: var TParser): PNode =
+proc identWithPragma(p: var TParser; allowDot=false): PNode =
   #| identWithPragma = identVis pragma?
-  var a = identVis(p)
+  #| identWithPragmaDot = identVisDot pragma?
+  var a = identVis(p, allowDot)
   if p.tok.tokType == tkCurlyDotLe:
     result = newNodeP(nkPragmaExpr, p)
     addSon(result, a)
@@ -1803,10 +1807,11 @@ proc parseTypeClass(p: var TParser): PNode =
     addSon(result, parseStmt(p))
 
 proc parseTypeDef(p: var TParser): PNode =
-  #| typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
+  #|
+  #| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
   #|             indAndComment?
   result = newNodeP(nkTypeDef, p)
-  addSon(result, identWithPragma(p))
+  addSon(result, identWithPragma(p, allowDot=true))
   if p.tok.tokType == tkBracketLe and p.validInd:
     addSon(result, parseGenericParamList(p))
   else:
@@ -1903,7 +1908,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   #|                     | 'converter' routine
   #|                     | 'type' section(typeDef)
   #|                     | 'const' section(constant)
-  #|                     | ('let' | 'var') section(variable)
+  #|                     | ('let' | 'var' | 'using') section(variable)
   #|                     | bindStmt | mixinStmt)
   #|                     / simpleStmt
   case p.tok.tokType
@@ -1940,7 +1945,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
   of tkVar: result = parseSection(p, nkVarSection, parseVariable)
   of tkBind: result = parseBind(p, nkBindStmt)
   of tkMixin: result = parseBind(p, nkMixinStmt)
-  of tkUsing: result = parseBind(p, nkUsingStmt)
+  of tkUsing: result = parseSection(p, nkUsingStmt, parseVariable)
   else: result = simpleStmt(p)
 
 proc parseStmt(p: var TParser): PNode =
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index f10d552a1..2280ef712 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -46,7 +46,7 @@ const
     wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
     wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
     wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
-    wInjectStmt, wDeprecated, wExperimental}
+    wInjectStmt, wDeprecated, wExperimental, wThis}
   lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
     wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
     wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
@@ -55,7 +55,7 @@ const
     wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
     wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
-    wBorrow, wGcSafe, wExportNims}
+    wBorrow, wGcSafe, wExportNims, wPartial}
   fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
     wImportCpp, wImportObjC, wError, wGuard, wBitsize}
   varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@@ -835,6 +835,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         noVal(it)
         if sym.kind != skType or sym.typ == nil: invalidPragma(it)
         else: incl(sym.typ.flags, tfByCopy)
+      of wPartial:
+        noVal(it)
+        if sym.kind != skType or sym.typ == nil: invalidPragma(it)
+        else:
+          incl(sym.typ.flags, tfPartial)
+          # .partial types can only work with dead code elimination
+          # to prevent the codegen from doing anything before we compiled
+          # the whole program:
+          incl gGlobalOptions, optDeadCodeElim
       of wInject, wGensym:
         # We check for errors, but do nothing with these pragmas otherwise
         # as they are handled directly in 'evalTemplate'.
@@ -875,6 +884,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           c.module.flags.incl sfExperimental
         else:
           localError(it.info, "'experimental' pragma only valid as toplevel statement")
+      of wThis:
+        if it.kind == nkExprColonExpr:
+          c.selfName = considerQuotedIdent(it[1])
+        else:
+          c.selfName = getIdent("self")
       of wNoRewrite:
         noVal(it)
       of wBase:
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index d63cba4be..12852ba3d 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -463,6 +463,9 @@ proc lsub(n: PNode): int =
   of nkVarSection, nkLetSection:
     if sonsLen(n) > 1: result = MaxLineLen + 1
     else: result = lsons(n) + len("var_")
+  of nkUsingStmt:
+    if sonsLen(n) > 1: result = MaxLineLen + 1
+    else: result = lsons(n) + len("using_")
   of nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
   of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_")
   of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_")
@@ -1173,11 +1176,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     initContext(a)
     incl(a.flags, rfInConstExpr)
     gsection(g, n, a, tkConst, "const")
-  of nkVarSection, nkLetSection:
+  of nkVarSection, nkLetSection, nkUsingStmt:
     var L = sonsLen(n)
     if L == 0: return
     if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
-    else: putWithSpace(g, tkLet, "let")
+    elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
+    else: putWithSpace(g, tkUsing, "using")
     if L > 1:
       gcoms(g)
       indentNL(g)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index cddd763ce..e09d49f88 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -191,7 +191,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
                  allowed: TSymFlags): PSym
-  # identifier with visability
+  # identifier with visibility
 proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym
 proc semStmtScope(c: PContext, n: PNode): PNode
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index eba1059ef..916d897c9 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -50,7 +50,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
 
   var syms: seq[tuple[a: PSym, b: int]] = @[]
   while symx != nil:
-    if symx.kind in filter: syms.add((symx, o.lastOverloadScope))
+    if symx.kind in filter:
+      syms.add((symx, o.lastOverloadScope))
     symx = nextOverloadIter(o, c, headSymbol)
   if syms.len == 0: return
 
@@ -63,7 +64,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
     let sym = syms[i][0]
     determineType(c, sym)
     initCandidate(c, z, sym, initialBinding, syms[i][1])
-    z.calleeSym = sym
 
     #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
     #  gDebug = true
@@ -138,11 +138,6 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
   else:
     localError(n.info, errGenerated, result)
 
-proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
-  for scope in walkScopes(c.currentScope):
-    if scope.usingSyms != nil:
-      for s in scope.usingSyms: usedSyms.safeAdd(s)
-
 proc resolveOverloads(c: PContext, n, orig: PNode,
                       filter: TSymKinds;
                       errors: var CandidateErrors): TCandidate =
@@ -156,31 +151,30 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
   else:
     initialBinding = nil
 
-  var usedSyms: seq[PNode]
-
-  template pickBest(headSymbol: expr) =
+  template pickBest(headSymbol) =
     pickBestCandidate(c, headSymbol, n, orig, initialBinding,
                       filter, result, alt, errors)
 
-  gatherUsedSyms(c, usedSyms)
-  if usedSyms != nil:
-    var hiddenArg = if usedSyms.len > 1: newNode(nkClosedSymChoice, n.info, usedSyms)
-                    else: usedSyms[0]
-
-    n.sons.insert(hiddenArg, 1)
-    orig.sons.insert(hiddenArg, 1)
-
-    pickBest(f)
-
-    if result.state != csMatch:
-      n.sons.delete(1)
-      orig.sons.delete(1)
-    else: return
 
   pickBest(f)
 
   let overloadsState = result.state
   if overloadsState != csMatch:
+    if c.p != nil and c.p.selfSym != nil:
+      # we need to enforce semchecking of selfSym again because it
+      # might need auto-deref:
+      var hiddenArg = newSymNode(c.p.selfSym)
+      hiddenArg.typ = nil
+      n.sons.insert(hiddenArg, 1)
+      orig.sons.insert(hiddenArg, 1)
+
+      pickBest(f)
+
+      if result.state != csMatch:
+        n.sons.delete(1)
+        orig.sons.delete(1)
+      else: return
+
     if nfDotField in n.flags:
       internalAssert f.kind == nkIdent and n.sonsLen >= 2
       let calleeName = newStrNode(nkStrLit, f.ident.s).withInfo(n.info)
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 656bfc449..a13f2c232 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -30,6 +30,7 @@ type
                               # statements
     owner*: PSym              # the symbol this context belongs to
     resultSym*: PSym          # the result symbol (if we are in a proc)
+    selfSym*: PSym            # the 'self' symbol (if available)
     nestedLoopCounter*: int   # whether we are in a loop or not
     nestedBlockCounter*: int  # whether we are in a block or not
     inTryStmt*: int           # whether we are in a try statement; works also
@@ -103,7 +104,8 @@ type
     inParallelStmt*: int
     instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
                             op: TTypeAttachedOp): PSym {.nimcall.}
-
+    selfName*: PIdent
+    signatures*: TStrTable
 
 proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
   result.genericSym = s
@@ -154,16 +156,6 @@ proc popOwner() =
 proc lastOptionEntry(c: PContext): POptionEntry =
   result = POptionEntry(c.optionStack.tail)
 
-proc pushProcCon*(c: PContext, owner: PSym) {.inline.} =
-  if owner == nil:
-    internalError("owner is nil")
-    return
-  var x: PProcCon
-  new(x)
-  x.owner = owner
-  x.next = c.p
-  c.p = x
-
 proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
 
 proc newOptionEntry(): POptionEntry =
@@ -187,6 +179,8 @@ proc newContext(module: PSym): PContext =
   initStrTable(result.userPragmas)
   result.generics = @[]
   result.unknownIdents = initIntSet()
+  initStrTable(result.signatures)
+
 
 proc inclSym(sq: var TSymSeq, s: PSym) =
   var L = len(sq)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 87d7764a2..16b4ee479 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -77,88 +77,6 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
   result.typ = s.typ
   result.info = n.info
 
-proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
-  case s.kind
-  of skConst:
-    markUsed(n.info, s)
-    styleCheckUse(n.info, s)
-    case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
-    of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
-        tyTuple, tySet, tyUInt..tyUInt64:
-      if s.magic == mNone: result = inlineConst(n, s)
-      else: result = newSymNode(s, n.info)
-    of tyArrayConstr, tySequence:
-      # Consider::
-      #     const x = []
-      #     proc p(a: openarray[int])
-      #     proc q(a: openarray[char])
-      #     p(x)
-      #     q(x)
-      #
-      # It is clear that ``[]`` means two totally different things. Thus, we
-      # copy `x`'s AST into each context, so that the type fixup phase can
-      # deal with two different ``[]``.
-      if s.ast.len == 0: result = inlineConst(n, s)
-      else: result = newSymNode(s, n.info)
-    else:
-      result = newSymNode(s, n.info)
-  of skMacro: result = semMacroExpr(c, n, n, s, flags)
-  of skTemplate: result = semTemplateExpr(c, n, s, flags)
-  of skParam:
-    markUsed(n.info, s)
-    styleCheckUse(n.info, s)
-    if s.typ.kind == tyStatic and s.typ.n != nil:
-      # XXX see the hack in sigmatch.nim ...
-      return s.typ.n
-    elif sfGenSym in s.flags:
-      if c.p.wasForwarded:
-        # gensym'ed parameters that nevertheless have been forward declared
-        # need a special fixup:
-        let realParam = c.p.owner.typ.n[s.position+1]
-        internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam
-        return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
-      elif c.p.owner.kind == skMacro:
-        # gensym'ed macro parameters need a similar hack (see bug #1944):
-        var u = searchInScopes(c, s.name)
-        internalAssert u != nil and u.kind == skParam and u.owner == s.owner
-        return newSymNode(u, n.info)
-    result = newSymNode(s, n.info)
-  of skVar, skLet, skResult, skForVar:
-    if s.magic == mNimvm:
-      localError(n.info, "illegal context for 'nimvm' magic")
-
-    markUsed(n.info, s)
-    styleCheckUse(n.info, s)
-    # if a proc accesses a global variable, it is not side effect free:
-    if sfGlobal in s.flags:
-      incl(c.p.owner.flags, sfSideEffect)
-    result = newSymNode(s, n.info)
-    # We cannot check for access to outer vars for example because it's still
-    # not sure the symbol really ends up being used:
-    # var len = 0 # but won't be called
-    # genericThatUsesLen(x) # marked as taking a closure?
-  of skGenericParam:
-    styleCheckUse(n.info, s)
-    if s.typ.kind == tyStatic:
-      result = newSymNode(s, n.info)
-      result.typ = s.typ
-    elif s.ast != nil:
-      result = semExpr(c, s.ast)
-    else:
-      n.typ = s.typ
-      return n
-  of skType:
-    markUsed(n.info, s)
-    styleCheckUse(n.info, s)
-    if s.typ.kind == tyStatic and s.typ.n != nil:
-      return s.typ.n
-    result = newSymNode(s, n.info)
-    result.typ = makeTypeDesc(c, s.typ)
-  else:
-    markUsed(n.info, s)
-    styleCheckUse(n.info, s)
-    result = newSymNode(s, n.info)
-
 type
   TConvStatus = enum
     convOK,
@@ -1015,6 +933,116 @@ proc readTypeParameter(c: PContext, typ: PType,
         return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
   #echo "came here: returned nil"
 
+proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
+  case s.kind
+  of skConst:
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
+    of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
+        tyTuple, tySet, tyUInt..tyUInt64:
+      if s.magic == mNone: result = inlineConst(n, s)
+      else: result = newSymNode(s, n.info)
+    of tyArrayConstr, tySequence:
+      # Consider::
+      #     const x = []
+      #     proc p(a: openarray[int])
+      #     proc q(a: openarray[char])
+      #     p(x)
+      #     q(x)
+      #
+      # It is clear that ``[]`` means two totally different things. Thus, we
+      # copy `x`'s AST into each context, so that the type fixup phase can
+      # deal with two different ``[]``.
+      if s.ast.len == 0: result = inlineConst(n, s)
+      else: result = newSymNode(s, n.info)
+    else:
+      result = newSymNode(s, n.info)
+  of skMacro: result = semMacroExpr(c, n, n, s, flags)
+  of skTemplate: result = semTemplateExpr(c, n, s, flags)
+  of skParam:
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    if s.typ.kind == tyStatic and s.typ.n != nil:
+      # XXX see the hack in sigmatch.nim ...
+      return s.typ.n
+    elif sfGenSym in s.flags:
+      if c.p.wasForwarded:
+        # gensym'ed parameters that nevertheless have been forward declared
+        # need a special fixup:
+        let realParam = c.p.owner.typ.n[s.position+1]
+        internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam
+        return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
+      elif c.p.owner.kind == skMacro:
+        # gensym'ed macro parameters need a similar hack (see bug #1944):
+        var u = searchInScopes(c, s.name)
+        internalAssert u != nil and u.kind == skParam and u.owner == s.owner
+        return newSymNode(u, n.info)
+    result = newSymNode(s, n.info)
+  of skVar, skLet, skResult, skForVar:
+    if s.magic == mNimvm:
+      localError(n.info, "illegal context for 'nimvm' magic")
+
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    # if a proc accesses a global variable, it is not side effect free:
+    if sfGlobal in s.flags:
+      incl(c.p.owner.flags, sfSideEffect)
+    result = newSymNode(s, n.info)
+    # We cannot check for access to outer vars for example because it's still
+    # not sure the symbol really ends up being used:
+    # var len = 0 # but won't be called
+    # genericThatUsesLen(x) # marked as taking a closure?
+  of skGenericParam:
+    styleCheckUse(n.info, s)
+    if s.typ.kind == tyStatic:
+      result = newSymNode(s, n.info)
+      result.typ = s.typ
+    elif s.ast != nil:
+      result = semExpr(c, s.ast)
+    else:
+      n.typ = s.typ
+      return n
+  of skType:
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    if s.typ.kind == tyStatic and s.typ.n != nil:
+      return s.typ.n
+    result = newSymNode(s, n.info)
+    result.typ = makeTypeDesc(c, s.typ)
+  of skField:
+    if c.p != nil and c.p.selfSym != nil:
+      var ty = skipTypes(c.p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
+      while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
+      var check: PNode = nil
+      if ty.kind == tyObject:
+        while true:
+          check = nil
+          let f = lookupInRecordAndBuildCheck(c, n, ty.n, s.name, check)
+          if f != nil and fieldVisible(c, f):
+            # is the access to a public field or in the same module or in a friend?
+            doAssert f == s
+            markUsed(n.info, f)
+            styleCheckUse(n.info, f)
+            result = newNodeIT(nkDotExpr, n.info, f.typ)
+            result.add makeDeref(newSymNode(c.p.selfSym))
+            result.add newSymNode(f) # we now have the correct field
+            if check != nil:
+              check.sons[0] = result
+              check.typ = result.typ
+              result = check
+            return result
+          if ty.sons[0] == nil: break
+          ty = skipTypes(ty.sons[0], {tyGenericInst})
+    # old code, not sure if it's live code:
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    result = newSymNode(s, n.info)
+  else:
+    markUsed(n.info, s)
+    styleCheckUse(n.info, s)
+    result = newSymNode(s, n.info)
+
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
   checkSonsLen(n, 2)
@@ -1528,24 +1556,6 @@ proc newAnonSym(kind: TSymKind, info: TLineInfo,
   result = newSym(kind, idAnon, owner, info)
   result.flags = {sfGenSym}
 
-proc semUsing(c: PContext, n: PNode): PNode =
-  result = newNodeI(nkEmpty, n.info)
-  if not experimentalMode(c):
-    localError(n.info, "use the {.experimental.} pragma to enable 'using'")
-  for e in n.sons:
-    let usedSym = semExpr(c, e)
-    if usedSym.kind == nkSym:
-      case usedSym.sym.kind
-      of skLocalVars + {skConst}:
-        c.currentScope.usingSyms.safeAdd(usedSym)
-        continue
-      of skProcKinds:
-        addDeclAt(c.currentScope, usedSym.sym)
-        continue
-      else: discard
-
-    localError(e.info, errUsingNoSymbol, e.renderTree)
-
 proc semExpandToAst(c: PContext, n: PNode): PNode =
   var macroCall = n[1]
   var expandedSym = expectMacroOrTemplateCall(c, macroCall)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 2c767ffc6..4a45dee9d 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -10,6 +10,47 @@
 # This module implements the instantiation of generic procs.
 # included from sem.nim
 
+proc addObjFieldsToLocalScope(c: PContext; n: PNode) =
+  template rec(n) = addObjFieldsToLocalScope(c, n)
+  case n.kind
+  of nkRecList:
+    for i in countup(0, len(n)-1):
+      rec n[i]
+  of nkRecCase:
+    if n.len > 0: rec n.sons[0]
+    for i in countup(1, len(n)-1):
+      if n[i].kind in {nkOfBranch, nkElse}: rec lastSon(n[i])
+  of nkSym:
+    let f = n.sym
+    if f.kind == skField and fieldVisible(c, f):
+      c.currentScope.symbols.strTableIncl(f, onConflictKeepOld=true)
+      incl(f.flags, sfUsed)
+      # it is not an error to shadow fields via parameters
+  else: discard
+
+proc rawPushProcCon(c: PContext, owner: PSym) =
+  var x: PProcCon
+  new(x)
+  x.owner = owner
+  x.next = c.p
+  c.p = x
+
+proc rawHandleSelf(c: PContext; owner: PSym) =
+  if c.selfName != nil and owner.kind in {skProc, skMethod, skConverter, skIterator, skMacro} and owner.typ != nil:
+    let params = owner.typ.n
+    if params.len > 1:
+      let arg = params[1].sym
+      if arg.name.id == c.selfName.id:
+        c.p.selfSym = arg
+        arg.flags.incl sfIsSelf
+        let t = c.p.selfSym.typ.skipTypes(abstractPtrs)
+        if t.kind == tyObject:
+          addObjFieldsToLocalScope(c, t.n)
+
+proc pushProcCon*(c: PContext; owner: PSym) =
+  rawPushProcCon(c, owner)
+  rawHandleSelf(c, owner)
+
 iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
   internalAssert n.kind == nkGenericParams
   for i, a in n.pairs:
@@ -248,7 +289,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     addDecl(c, s)
     entry.concreteTypes[i] = s.typ
     inc i
-  pushProcCon(c, result)
+  rawPushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
   for j in 1 .. result.typ.len-1:
     entry.concreteTypes[i] = result.typ.sons[j]
@@ -263,6 +304,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     # a ``compiles`` context but this is the lesser evil. See
     # bug #1055 (tevilcompiles).
     #if c.compilesContextId == 0:
+    rawHandleSelf(c, result)
     entry.compilesId = c.compilesContextId
     fn.procInstCache.safeAdd(entry)
     c.generics.add(makeInstPair(fn, entry))
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index edcf079fa..5d16f2fba 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -386,6 +386,30 @@ proc isDiscardUnderscore(v: PSym): bool =
     v.flags.incl(sfGenSym)
     result = true
 
+proc semUsing(c: PContext; n: PNode): PNode =
+  result = ast.emptyNode
+  if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "using")
+  if not experimentalMode(c):
+    localError(n.info, "use the {.experimental.} pragma to enable 'using'")
+  for i in countup(0, sonsLen(n)-1):
+    var a = n.sons[i]
+    if gCmd == cmdIdeTools: suggestStmt(c, a)
+    if a.kind == nkCommentStmt: continue
+    if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a)
+    checkMinSonsLen(a, 3)
+    var length = sonsLen(a)
+    if a.sons[length-2].kind != nkEmpty:
+      let typ = semTypeNode(c, a.sons[length-2], nil)
+      for j in countup(0, length-3):
+        let v = semIdentDef(c, a.sons[j], skParam)
+        v.typ = typ
+        strTableIncl(c.signatures, v)
+    else:
+      localError(a.info, "'using' section must have a type")
+    var def: PNode
+    if a.sons[length-1].kind != nkEmpty:
+      localError(a.info, "'using' sections cannot contain assignments")
+
 proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
   var b: PNode
   result = copyNode(n)
@@ -640,13 +664,20 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
     if a.kind == nkCommentStmt: continue
     if a.kind != nkTypeDef: illFormedAst(a)
     checkSonsLen(a, 3)
-    var s = semIdentDef(c, a.sons[0], skType)
-    s.typ = newTypeS(tyForward, c)
-    s.typ.sym = s             # process pragmas:
-    if a.sons[0].kind == nkPragmaExpr:
-      pragma(c, s, a.sons[0].sons[1], typePragmas)
-    # add it here, so that recursive types are possible:
-    if sfGenSym notin s.flags: addInterfaceDecl(c, s)
+    let name = a.sons[0]
+    var s: PSym
+    if name.kind == nkDotExpr:
+      s = qualifiedLookUp(c, name)
+      if s.kind != skType or s.typ.skipTypes(abstractPtrs).kind != tyObject or tfPartial notin s.typ.skipTypes(abstractPtrs).flags:
+        localError(name.info, "only .partial objects can be extended")
+    else:
+      s = semIdentDef(c, name, skType)
+      s.typ = newTypeS(tyForward, c)
+      s.typ.sym = s             # process pragmas:
+      if name.kind == nkPragmaExpr:
+        pragma(c, s, name.sons[1], typePragmas)
+      # add it here, so that recursive types are possible:
+      if sfGenSym notin s.flags: addInterfaceDecl(c, s)
     a.sons[0] = newSymNode(s)
 
 proc typeSectionRightSidePass(c: PContext, n: PNode) =
@@ -655,8 +686,9 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
     if a.kind == nkCommentStmt: continue
     if (a.kind != nkTypeDef): illFormedAst(a)
     checkSonsLen(a, 3)
-    if (a.sons[0].kind != nkSym): illFormedAst(a)
-    var s = a.sons[0].sym
+    let name = a.sons[0]
+    if (name.kind != nkSym): illFormedAst(a)
+    var s = name.sym
     if s.magic == mNone and a.sons[2].kind == nkEmpty:
       localError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
@@ -1206,9 +1238,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     # Macros and Templates can have generic parameters, but they are
     # only used for overload resolution (there is no instantiation of
     # the symbol, so we must process the body now)
+    pushProcCon(c, s)
     if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
       if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
-      pushProcCon(c, s)
+
       c.p.wasForwarded = proto != nil
       maybeAddResult(c, s, n)
       if sfImportc notin s.flags:
@@ -1217,7 +1250,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         # unfortunately we cannot skip this step when in 'system.compiles'
         # context as it may even be evaluated in 'system.compiles':
         n.sons[bodyPos] = transformBody(c.module, semBody, s)
-      popProcCon(c)
     else:
       if s.typ.sons[0] != nil and kind != skIterator:
         addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
@@ -1228,6 +1260,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     if sfImportc in s.flags:
       # so we just ignore the body after semantic checking for importc:
       n.sons[bodyPos] = ast.emptyNode
+    popProcCon(c)
   else:
     if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
     if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index ac425ba15..62d02fe10 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -673,7 +673,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
   result = newOrPrevType(tyObject, prev, c)
   rawAddSon(result, base)
-  result.n = newNodeI(nkRecList, n.info)
+  if result.n.isNil:
+    result.n = newNodeI(nkRecList, n.info)
+  else:
+    # partial object so add things to the check
+    addInheritedFields(c, check, pos, result)
   semRecordNodeAux(c, n.sons[2], check, pos, result.n, result)
   if n.sons[0].kind != nkEmpty:
     # dummy symbol for `pragma`:
@@ -934,14 +938,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
           def = fitNode(c, typ, def)
     if not hasType and not hasDefault:
       if isType: localError(a.info, "':' expected")
-      let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything
-      if tdef == tyAnything:
-        message(a.info, warnTypelessParam, renderTree(n))
-      typ = newTypeS(tdef, c)
-
-    if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
+      if kind in {skTemplate, skMacro}:
+        typ = newTypeS(tyExpr, c)
+    elif skipTypes(typ, {tyGenericInst}).kind == tyEmpty:
+      continue
     for j in countup(0, length-3):
       var arg = newSymG(skParam, a.sons[j], c)
+      if not hasType and not hasDefault and kind notin {skTemplate, skMacro}:
+        let param = strTableGet(c.signatures, arg.name)
+        if param != nil: typ = param.typ
+        else:
+          localError(a.info, "typeless parameters are obsolete")
+          typ = errorType(c)
       let lifted = liftParamType(c, kind, genericParams, typ,
                                  arg.name.s, arg.info)
       let finalType = if lifted != nil: lifted else: typ.skipIntLit
@@ -1307,11 +1315,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkType: result = n.typ
   of nkStmtListType: result = semStmtListType(c, n, prev)
   of nkBlockType: result = semBlockType(c, n, prev)
-  of nkSharedTy:
-    checkSonsLen(n, 1)
-    result = semTypeNode(c, n.sons[0], prev)
-    result = freshType(result, prev)
-    result.flags.incl(tfShared)
   else:
     localError(n.info, errTypeExpected)
     result = newOrPrevType(tyError, prev, c)
@@ -1387,15 +1390,6 @@ proc processMagicType(c: PContext, m: PSym) =
     rawAddSon(m.typ, newTypeS(tyNone, c))
   of mPNimrodNode:
     incl m.typ.flags, tfTriggersCompileTime
-  of mShared:
-    setMagicType(m, tyObject, 0)
-    m.typ.n = newNodeI(nkRecList, m.info)
-    incl m.typ.flags, tfShared
-  of mGuarded:
-    setMagicType(m, tyObject, 0)
-    m.typ.n = newNodeI(nkRecList, m.info)
-    incl m.typ.flags, tfShared
-    rawAddSon(m.typ, sysTypeFromName"shared")
   else: localError(m.info, errTypeExpected)
 
 proc semGenericConstraints(c: PContext, x: PType): PType =
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index a7f28feec..d20704a2a 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -14,22 +14,11 @@ import ast, astalgo, msgs, types, magicsys, semdata, renderer
 const
   tfInstClearedFlags = {tfHasMeta}
 
-proc sharedPtrCheck(info: TLineInfo, t: PType) =
-  if t.kind == tyPtr and t.len > 1:
-    if t.sons[0].sym.magic == mShared:
-      incl(t.flags, tfShared)
-      #if t.sons[0].sym.magic == mGuarded: incl(t.flags, tfGuarded)
-      if tfHasGCedMem in t.flags or t.isGCedMem:
-        localError(info, errGenerated,
-                   "shared memory may not refer to GC'ed thread local memory")
-
 proc checkPartialConstructedType(info: TLineInfo, t: PType) =
   if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
     localError(info, errInvalidPragmaX, "acyclic")
   elif t.kind == tyVar and t.sons[0].kind == tyVar:
     localError(info, errVarVarTypeNotAllowed)
-  else:
-    sharedPtrCheck(info, t)
 
 proc checkConstructedType*(info: TLineInfo, typ: PType) =
   var t = typ.skipTypes({tyDistinct})
@@ -40,8 +29,6 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) =
     localError(info, errVarVarTypeNotAllowed)
   elif computeSize(t) == szIllegalRecursion:
     localError(info, errIllegalRecursionInTypeX, typeToString(t))
-  else:
-    sharedPtrCheck(info, t)
   when false:
     if t.kind == tyObject and t.sons[0] != nil:
       if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 96df0c5c6..ceadc2fea 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -37,6 +37,7 @@ type
                              # is this a top-level symbol or a nested proc?
     call*: PNode             # modified call
     bindings*: TIdTable      # maps types to types
+    magic*: TMagic           # magic of operation
     baseTypeMatch: bool      # needed for conversions from T to openarray[T]
                              # for example
     fauxMatch*: TTypeKind    # the match was successful only due to the use
@@ -114,6 +115,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
       c.calleeScope = 1
   else:
     c.calleeScope = calleeScope
+  c.magic = c.calleeSym.magic
   initIdTable(c.bindings)
   c.errors = nil
   if binding != nil and callee.kind in routineKinds:
@@ -1691,7 +1693,7 @@ proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   matchesAux(c, n, nOrig, m, marker)
 
 proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
-  if m.calleeSym != nil and m.calleeSym.magic in {mArrGet, mArrPut}:
+  if m.magic in {mArrGet, mArrPut}:
     m.state = csMatch
     m.call = n
     return
diff --git a/compiler/transf.nim b/compiler/transf.nim
index b2bbdcec3..a4a15ea4a 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -12,7 +12,7 @@
 #
 # * inlines iterators
 # * inlines constants
-# * performes constant folding
+# * performs constant folding
 # * converts "continue" to "break"; disambiguates "break"
 # * introduces method dispatchers
 # * performs lambda lifting for closure support
diff --git a/compiler/types.nim b/compiler/types.nim
index 71ab84022..9aa991086 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -412,7 +412,6 @@ const
 const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
 
 proc addTypeFlags(name: var string, typ: PType) {.inline.} =
-  if tfShared in typ.flags: name = "shared " & name
   if tfNotNil in typ.flags: name.add(" not nil")
 
 proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 0a0534118..3e0e05a94 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -66,6 +66,7 @@ type
     wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
     wAsmNoStackFrame,
     wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
+    wPartial,
 
     wAuto, wBool, wCatch, wChar, wClass,
     wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@@ -151,7 +152,7 @@ const
     "computedgoto", "injectstmt", "experimental",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
     "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
-    "guard", "locks",
+    "guard", "locks", "partial",
 
     "auto", "bool", "catch", "char", "class",
     "const_cast", "default", "delete", "double",
diff --git a/doc/grammar.txt b/doc/grammar.txt
index d967bf938..47f739174 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -67,7 +67,9 @@ ifExpr = 'if' condExpr
 whenExpr = 'when' condExpr
 pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
 identVis = symbol opr?  # postfix position
+identVisDot = symbol '.' optInd symbol opr?
 identWithPragma = identVis pragma?
+identWithPragmaDot = identVisDot pragma?
 declColonEquals = identWithPragma (comma identWithPragma)* comma?
                   (':' optInd typeDesc)? ('=' optInd expr)?
 identColonEquals = ident (comma ident)* comma?
@@ -171,7 +173,7 @@ object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
 typeClassParam = ('var' | 'out')? symbol
 typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
               &IND{>} stmt
-typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
+typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
             indAndComment?
 varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
 variable = (varTuple / identColonEquals) indAndComment
diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt
index 83852b1ff..4f8d6e935 100644
--- a/doc/manual/stmts.txt
+++ b/doc/manual/stmts.txt
@@ -547,55 +547,36 @@ Instead of:
 Using statement
 ---------------
 
-**Warning**: The ``using`` statement is highly experimental and has to be
+**Warning**: The ``using`` statement is experimental and has to be
 explicitly enabled with the `experimental`:idx: pragma or command line option!
 
-The using statement provides syntactic convenience for procs that
-heavily use a single contextual parameter. When applied to a variable or a
-constant, it will instruct Nim to automatically consider the used symbol as
-a hidden leading parameter for any procedure calls, following the using
-statement in the current scope. Thus, it behaves much like the hidden `this`
-parameter available in some object-oriented programming languages.
+The using statement provides syntactic convenience in modules where
+the same parameter names and types are used over and over. Instead of:
 
 .. code-block:: nim
+  proc foo(c: Context; n: Node) = ...
+  proc bar(c: Context; n: Node, counter: int) = ...
+  proc baz(c: Context; n: Node) = ...
 
-  var s = socket()
-  using s
-
-  connect(host, port)
-  send(data)
-
-  while true:
-    let line = readLine(timeout)
-    ...
-
-
-When applied to a callable symbol, it brings the designated symbol in the
-current scope. Thus, it can be used to disambiguate between imported symbols
-from different modules having the same name.
+One can tell the compiler about the convention that a parameter of
+name ``c`` should default to type ``Context``, ``n`` should default to
+``Node`` etc.:
 
 .. code-block:: nim
-  import windows, sdl
-  using sdl.SetTimer
+  {.experimental.}
+  using
+    c: Context
+    n: Node
+    counter: int
 
-Note that ``using`` only *adds* to the current context, it doesn't remove or
-replace, **neither** does it create a new scope. What this means is that if one
-applies this to multiple variables the compiler will find conflicts in what
-variable to use:
+  proc foo(c, n) = ...
+  proc bar(c, n, counter) = ...
+  proc baz(c, n) = ...
 
-.. code-block:: nim
-  var a, b = "kill it"
-  using a
-  add(" with fire")
-  using b
-  add(" with water")
-  echo a
-  echo b
 
-When the compiler reaches the second ``add`` call, both ``a`` and ``b`` could
-be used with the proc, so one gets ``Error: expression '(a|b)' has no type (or
-is ambiguous)``. To solve this one would need to nest ``using`` with a
-``block`` statement so as to control the reach of the ``using`` statement.
+The ``using`` section uses the same indentation based grouping syntax as
+a ``var`` or ``let``` section.
+
 
 If expression
 -------------
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index eda793620..4522e0fc6 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -71,7 +71,12 @@ type
     nnkEnumTy,
     nnkEnumFieldDef,
     nnkArglist, nnkPattern
-    nnkReturnToken
+    nnkReturnToken,
+    nnkClosure,
+    nnkGotoState,
+    nnkState,
+    nnkBreakState
+
   NimNodeKinds* = set[NimNodeKind]
   NimTypeKind* = enum
     ntyNone, ntyBool, ntyChar, ntyEmpty,
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 10700b59b..c8f690461 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -1,6 +1,6 @@
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2015 Nim Contributers
+#        (c) Copyright 2015 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -508,7 +508,7 @@ iterator findIter*(str: string, pattern: Regex, start = 0, endpos = int.high): R
   ## Variants:
   ##
   ## -  ``proc findAll(...)`` returns a ``seq[string]``
-  # see pcredemo for explaination
+  # see pcredemo for explanation
   let matchesCrLf = pattern.matchesCrLf()
   let unicode = uint32(getinfo[culong](pattern, pcre.INFO_OPTIONS) and
     pcre.UTF8) > 0u32
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 2da14c363..c5b1a21e9 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1123,9 +1123,9 @@ else:
 
   proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".}
 
-  proc getVarType(x): JsonNodeKind =
+  proc getVarType(x: JSObject): JsonNodeKind =
     result = JNull
-    proc getProtoName(y): cstring
+    proc getProtoName(y: JSObject): cstring
       {.importc: "Object.prototype.toString.call".}
     case $getProtoName(x) # TODO: Implicit returns fail here.
     of "[object Array]": return JArray
@@ -1216,23 +1216,27 @@ when false:
 # To get that we shall use, obj["json"]
 
 when isMainModule:
-  var parsed = parseFile("tests/testdata/jsontest.json")
-  var parsed2 = parseFile("tests/testdata/jsontest2.json")
+  when not defined(js):
+    var parsed = parseFile("tests/testdata/jsontest.json")
 
-  try:
-    discard parsed["key2"][12123]
-    assert(false)
-  except IndexError: assert(true)
+    try:
+      discard parsed["key2"][12123]
+      doAssert(false)
+    except IndexError: doAssert(true)
+
+    var parsed2 = parseFile("tests/testdata/jsontest2.json")
+    doAssert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
 
   let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd", "c": "\ud83c\udf83", "d": "\u00E6"}"""
   # nil passthrough
-  assert(testJson{"doesnt_exist"}{"anything"}.isNil)
+  doAssert(testJson{"doesnt_exist"}{"anything"}.isNil)
   testJson{["e", "f"]} = %true
-  assert(testJson["e"]["f"].bval)
+  doAssert(testJson["e"]["f"].bval)
 
   # make sure UTF-16 decoding works.
-  assert(testJson["c"].str == "🎃")
-  assert(testJson["d"].str == "æ")
+  when not defined(js): # TODO: The following line asserts in JS
+    doAssert(testJson["c"].str == "🎃")
+  doAssert(testJson["d"].str == "æ")
 
   # make sure no memory leek when parsing invalid string
   let startMemory = getOccupiedMem()
@@ -1242,41 +1246,43 @@ when isMainModule:
     except:
       discard
   # memory diff should less than 2M
-  assert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024)
+  doAssert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024)
 
 
   # test `$`
   let stringified = $testJson
   let parsedAgain = parseJson(stringified)
-  assert(parsedAgain["b"].str == "asd")
+  doAssert(parsedAgain["b"].str == "asd")
+
+  parsedAgain["abc"] = %5
+  doAssert parsedAgain["abc"].num == 5
 
   # Bounds checking
   try:
     let a = testJson["a"][9]
-    assert(false, "EInvalidIndex not thrown")
+    doAssert(false, "EInvalidIndex not thrown")
   except IndexError:
     discard
   try:
     let a = testJson["a"][-1]
-    assert(false, "EInvalidIndex not thrown")
+    doAssert(false, "EInvalidIndex not thrown")
   except IndexError:
     discard
   try:
-    assert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
+    doAssert(testJson["a"][0].num == 1, "Index doesn't correspond to its value")
   except:
-    assert(false, "EInvalidIndex thrown for valid index")
+    doAssert(false, "EInvalidIndex thrown for valid index")
 
-  assert(testJson{"b"}.str=="asd", "Couldn't fetch a singly nested key with {}")
-  assert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
-  assert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
-  assert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
-  assert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
-  assert(testJson{"a"}==parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
-  assert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
+  doAssert(testJson{"b"}.str=="asd", "Couldn't fetch a singly nested key with {}")
+  doAssert(isNil(testJson{"nonexistent"}), "Non-existent keys should return nil")
+  doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
+  doAssert(isNil(testJson{"a", "b"}), "Indexing through a list should return nil")
+  doAssert(testJson{"a"}==parseJson"[1, 2, 3, 4]", "Didn't return a non-JObject when there was one to be found")
+  doAssert(isNil(parseJson("[1, 2, 3]"){"foo"}), "Indexing directly into a list should return nil")
 
   # Generator:
   var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}]
-  assert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
+  doAssert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
 
   var j2 = %*
     [
@@ -1289,7 +1295,7 @@ when isMainModule:
         "age": 31
       }
     ]
-  assert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
+  doAssert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
 
   var name = "John"
   let herAge = 30
@@ -1303,4 +1309,4 @@ when isMainModule:
       , "age": hisAge
       }
     ]
-  assert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
+  doAssert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 346b656a0..dbb78c4de 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -616,7 +616,7 @@ proc readIntoBuf(socket: Socket, flags: int32): int =
   else:
     result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
   if result < 0:
-    # Save it in case it gets reset (the Nim codegen occassionally may call
+    # Save it in case it gets reset (the Nim codegen occasionally may call
     # Win API functions which reset it).
     socket.lastError = osLastError()
   if result <= 0:
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index f680d4fef..9bcac0a50 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -288,19 +288,19 @@ proc rawGetTok(c: var CfgParser, tok: var Token) =
   else: getSymbol(c, tok)
 
 proc errorStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} =
-  ## returns a properly formated error message containing current line and
+  ## returns a properly formatted error message containing current line and
   ## column information.
   result = `%`("$1($2, $3) Error: $4",
                [c.filename, $getLine(c), $getColumn(c), msg])
 
 proc warningStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} =
-  ## returns a properly formated warning message containing current line and
+  ## returns a properly formatted warning message containing current line and
   ## column information.
   result = `%`("$1($2, $3) Warning: $4",
                [c.filename, $getLine(c), $getColumn(c), msg])
 
 proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} =
-  ## returns a properly formated warning message containing that
+  ## returns a properly formatted warning message containing that
   ## an entry is ignored.
   case e.kind
   of cfgSectionStart: result = c.warningStr("section ignored: " & e.section)
diff --git a/lib/pure/poly.nim b/lib/pure/poly.nim
index b20e9f9d0..e286c5d17 100644
--- a/lib/pure/poly.nim
+++ b/lib/pure/poly.nim
@@ -344,7 +344,7 @@ proc roots*(p:Poly,tol=1.0e-9,zerotol=1.0e-6,mergetol=1.0e-12,maxiter=1000):seq[
   ## `tol` is the tolerance used to break searching for each root when reached.
   ## `zerotol` is the tolerance, which is 'close enough' to zero to be considered a root
   ## and is used to find roots for curves that only 'touch' the x-axis.
-  ## `mergetol` is the tolerance, of which two x-values are considered beeing the same root.
+  ## `mergetol` is the tolerance, of which two x-values are considered being the same root.
   ## `maxiter` can be used to limit the number of iterations for each root.
   ## Returns a (possibly empty) sorted sequence with the solutions.
   var deg=p.degree
diff --git a/lib/pure/securehash.nim b/lib/pure/securehash.nim
index 657782889..a30fad92a 100644
--- a/lib/pure/securehash.nim
+++ b/lib/pure/securehash.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nim Compiler
-#        (c) Copyright 2015 Nim Contributers
+#        (c) Copyright 2015 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index bb6175a12..c606b4680 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -189,7 +189,7 @@ proc readBool*(s: Stream): bool =
   read(s, result)
 
 proc peekBool*(s: Stream): bool =
-  ## peeks a bool from the stream `s`. Raises `EIO` if an error occured.
+  ## peeks a bool from the stream `s`. Raises `EIO` if an error occurred.
   peek(s, result)
 
 proc readInt8*(s: Stream): int8 =
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index e39756696..29ae52d47 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -1245,7 +1245,7 @@ proc getDayOfWeek*(day, month, year: int): WeekDay =
   result = (d-1).WeekDay
 
 proc getDayOfWeekJulian*(day, month, year: int): WeekDay =
-  ## Returns the day of the week enum from day, month and year, according to the Julian calender.
+  ## Returns the day of the week enum from day, month and year, according to the Julian calendar.
   # Day & month start from one.
   let
     a = (14 - month) div 12
diff --git a/lib/system.nim b/lib/system.nim
index 3ef9c1b31..904791a46 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -279,11 +279,6 @@ when not defined(niminheritable):
 when not defined(nimunion):
   {.pragma: unchecked.}
 
-when defined(nimNewShared):
-  type
-    `shared`* {.magic: "Shared".}
-    guarded* {.magic: "Guarded".}
-
 # comparison operators:
 proc `==` *[Enum: enum](x, y: Enum): bool {.magic: "EqEnum", noSideEffect.}
   ## Checks whether values within the *same enum* have the same underlying value
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 1bbd89fe7..1abd8466d 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -103,9 +103,9 @@ else:
   proc c_setjmp(jmpb: C_JmpBuf): cint {.
     header: "<setjmp.h>", importc: "setjmp".}
 
-proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
+proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}) {.
   importc: "signal", header: "<signal.h>".}
-proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".}
+proc c_raise(sign: cint) {.importc: "raise", header: "<signal.h>".}
 
 proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs",
   header: "<stdio.h>".}
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 8d1e04b8d..948f87410 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -316,7 +316,7 @@ when defined(endb):
     dbgAborting: bool # whether the debugger wants to abort
 
 when not defined(noSignalHandler):
-  proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
+  proc signalHandler(sign: cint) {.exportc: "signalHandler", noconv.} =
     template processSignal(s, action: expr) {.immediate,  dirty.} =
       if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
       elif s == SIGSEGV:
@@ -342,13 +342,13 @@ when not defined(noSignalHandler):
       GC_disable()
       var buf = newStringOfCap(2000)
       rawWriteStackTrace(buf)
-      processSignal(sig, buf.add) # nice hu? currying a la Nim :-)
+      processSignal(sign, buf.add) # nice hu? currying a la Nim :-)
       showErrorMessage(buf)
       GC_enable()
     else:
       var msg: cstring
       template asgn(y: expr) = msg = y
-      processSignal(sig, asgn)
+      processSignal(sign, asgn)
       showErrorMessage(msg)
     when defined(endb): dbgAborting = true
     quit(1) # always quit when SIGABRT
@@ -367,6 +367,6 @@ when not defined(noSignalHandler):
 
 proc setControlCHook(hook: proc () {.noconv.} not nil) =
   # ugly cast, but should work on all architectures:
-  type SignalHandler = proc (sig: cint) {.noconv, benign.}
+  type SignalHandler = proc (sign: cint) {.noconv, benign.}
   {.deprecated: [TSignalHandler: SignalHandler].}
   c_signal(SIGINT, cast[SignalHandler](hook))
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 013dc55f8..a4676d26e 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -91,7 +91,7 @@ when allowForeignThreadGc:
     ## this thread will only be initialized once per thread, no matter how often
     ## it is called.
     ##
-    ## This function is availble only when ``--threads:on`` and ``--tlsEmulation:off``
+    ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
     ## switches are used
     if not localGcInitialized:
       localGcInitialized = true
@@ -100,7 +100,7 @@ when allowForeignThreadGc:
       initGC()
 else:
   template setupForeignThreadGc*(): stmt =
-    {.error: "setupForeignThreadGc is availble only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
+    {.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
 
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index 772d25343..d587d772f 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -74,7 +74,7 @@ proc getEnv*(key: string): string {.tags: [ReadIOEffect].} =
   builtin
 
 proc existsEnv*(key: string): bool {.tags: [ReadIOEffect].} =
-  ## Checks for the existance of an environment variable named `key`.
+  ## Checks for the existence of an environment variable named `key`.
   builtin
 
 proc fileExists*(filename: string): bool {.tags: [ReadIOEffect].} =
@@ -189,7 +189,7 @@ proc get*(key: string): string =
   builtin
 
 proc exists*(key: string): bool =
-  ## Checks for the existance of a configuration 'key'
+  ## Checks for the existence of a configuration 'key'
   ## like 'gcc.options.always'.
   builtin
 
diff --git a/tests/casestmt/tcaseexpr1.nim b/tests/casestmt/tcaseexpr1.nim
index e5e08e25e..56acbbc8a 100644
--- a/tests/casestmt/tcaseexpr1.nim
+++ b/tests/casestmt/tcaseexpr1.nim
@@ -11,7 +11,7 @@ discard """
 type
   E = enum A, B, C
 
-proc foo(x): auto =
+proc foo(x: int): auto =
   return case x
     of 1..9: "digit"
     else: "number"
diff --git a/tests/generics/tbadgenericlambda.nim b/tests/generics/tbadgenericlambda.nim
index 2ab8e724d..9fac150c1 100644
--- a/tests/generics/tbadgenericlambda.nim
+++ b/tests/generics/tbadgenericlambda.nim
@@ -3,5 +3,5 @@ discard """
   line: 6
 """
 
-let x = proc (x, y): auto = x + y
+let x = proc (x, y: auto): auto = x + y
 
diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim
index 45450ccca..a045b32f8 100644
--- a/tests/generics/tgeneric0.nim
+++ b/tests/generics/tgeneric0.nim
@@ -18,7 +18,7 @@ proc foo[T](p: TType[T, range[0..2]]) =
 
 #bug #1366
 
-proc reversed(x) =
+proc reversed(x: auto) =
   for i in countdown(x.low, x.high):
     echo i
 
diff --git a/tests/generics/tgenericlambda.nim b/tests/generics/tgenericlambda.nim
index eb6ada3e5..41ee74557 100644
--- a/tests/generics/tgenericlambda.nim
+++ b/tests/generics/tgenericlambda.nim
@@ -5,15 +5,15 @@ discard """
 proc test(x: proc (a, b: int): int) =
   echo x(5, 5)
 
-test(proc (a, b): auto = a + b)
+test(proc (a, b: auto): auto = a + b)
 
-test do (a, b) -> auto: a + b
+test do (a, b: auto) -> auto: a + b
 
 proc foreach[T](s: seq[T], body: proc(x: T)) =
   for e in s:
     body(e)
 
-foreach(@[1,2,3]) do (x):
+foreach(@[1,2,3]) do (x: auto):
   echo x
 
 proc foo =
diff --git a/tests/macros/tclosuremacro.nim b/tests/macros/tclosuremacro.nim
index cf51949ed..c29fbe1c8 100644
--- a/tests/macros/tclosuremacro.nim
+++ b/tests/macros/tclosuremacro.nim
@@ -26,7 +26,7 @@ proc noReturn(x: () -> void) =
 proc doWithOneAndTwo(f: (int, int) -> int): int =
   f(1,2)
 
-echo twoParams(proc (a, b): auto = a + b)
+echo twoParams(proc (a, b: auto): auto = a + b)
 echo twoParams((x, y) => x + y)
 
 echo oneParam(x => x+5)
diff --git a/tests/misc/tupcomingfeatures.nim b/tests/misc/tupcomingfeatures.nim
new file mode 100644
index 000000000..cf07b06df
--- /dev/null
+++ b/tests/misc/tupcomingfeatures.nim
@@ -0,0 +1,39 @@
+discard """
+  output: '''0 -2 0
+0 -2'''
+"""
+
+{.this: self.}
+
+type
+  Foo {.partial.} = object
+    a, b: int
+
+type
+  tupcomingfeatures.Foo = object
+    x: int
+
+proc yay(self: Foo) =
+  echo a, " ", b, " ", x
+
+proc footest[T](self: var Foo, a: T) =
+  b = 1+a
+  yay()
+
+proc nongeneric(self: Foo) =
+  echo a, " ", b
+
+var ff: Foo
+footest(ff, -3)
+ff.nongeneric
+
+{.experimental.}
+using
+  c: Foo
+  x, y: int
+
+proc usesSig(c) =
+  echo "yummy"
+
+proc foobar(c, y) =
+  echo "yay"
diff --git a/tests/stdlib/nre/init.nim b/tests/stdlib/nre/init.nim
index 1a1470842..26e668104 100644
--- a/tests/stdlib/nre/init.nim
+++ b/tests/stdlib/nre/init.nim
@@ -2,7 +2,7 @@ import unittest
 include nre
 
 suite "Test NRE initialization":
-  test "correct intialization":
+  test "correct initialization":
     check(re("[0-9]+") != nil)
     check(re("(?i)[0-9]+") != nil)
 
diff --git a/tests/template/tit.nim b/tests/template/tit.nim
index 9866711de..cf50d2f6f 100644
--- a/tests/template/tit.nim
+++ b/tests/template/tit.nim
@@ -5,7 +5,7 @@ template someIt(a, pred: expr): expr =
   var it {.inject.} = 0
   pred
 
-proc aProc(n) =
+proc aProc(n: auto) =
   n.someIt(echo(it))
 
 aProc(89)
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index ff83379b8..150c55edc 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -223,7 +223,7 @@ proc jsTests(r: var TResults, cat: Category, options: string) =
                    "varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
     test "tests/" & testfile & ".nim"
 
-  for testfile in ["pure/strutils"]:
+  for testfile in ["pure/strutils", "pure/json"]:
     test "lib/" & testfile & ".nim"
 
 # ------------------------- manyloc -------------------------------------------
diff --git a/tests/tuples/tuple_with_nil.nim b/tests/tuples/tuple_with_nil.nim
index 26e4ae85e..442fbab92 100644
--- a/tests/tuples/tuple_with_nil.nim
+++ b/tests/tuples/tuple_with_nil.nim
@@ -345,7 +345,7 @@ proc writeformat(o: var Writer; p: pointer; fmt: Format) =
   ## Write pointer `i` according to format `fmt` using output object
   ## `o` and output function `add`.
   ##
-  ## Pointers are casted to unsigned int and formated as hexadecimal
+  ## Pointers are casted to unsigned int and formatted as hexadecimal
   ## with prefix unless specified otherwise.
   var f = fmt
   if f.typ == 0.char:
@@ -584,7 +584,7 @@ proc splitfmt(s: string): seq[Part] {.compiletime, nosideeffect.} =
   ## Each part is either a literal string or a format specification. A
   ## format specification is a substring of the form
   ## "{[arg][:format]}" where `arg` is either empty or a number
-  ## refering to the arg-th argument and an additional field or array
+  ## referring to the arg-th argument and an additional field or array
   ## index. The format string is a string accepted by `parse`.
   let subpeg = sequence(capture(digits()),
                           capture(?sequence(charSet({'.'}), *pegs.identStartChars(), *identChars())),
diff --git a/tests/typerel/trettypeinference.nim b/tests/typerel/trettypeinference.nim
index 41b4aa5ef..fa4e89cc8 100644
--- a/tests/typerel/trettypeinference.nim
+++ b/tests/typerel/trettypeinference.nim
@@ -5,8 +5,8 @@ discard """
 
 import typetraits
 
-proc plus(a, b): auto = a + b
-proc makePair(a, b): auto = (first: a, second: b)
+proc plus(a, b: auto): auto = a + b
+proc makePair(a, b: auto): auto = (first: a, second: b)
 
 proc `+`(a, b: string): seq[string] = @[a, b]
 
@@ -19,7 +19,7 @@ static: assert p[0].type is string
 echo i.type.name
 echo s.type.name
 
-proc inst(a): auto =
+proc inst(a: auto): auto =
   static: echo "instantiated for ", a.type.name
   result = a
 
diff --git a/todo.txt b/todo.txt
index 703139c9c..db3604283 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,9 @@
 
 nim c --gc:v2 -r -d:useSysAssert -d:useGcAssert -d:smokeCycles -d:useRealtimeGc tests/gc/gcbench
 
+- document ``this`` pragma
+- document and stress test ``.partial`` object declarations
+
 essential for 1.0
 =================
 
diff --git a/web/news.txt b/web/news.txt
index f27398ee1..46a1c5162 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -16,20 +16,34 @@ Changes affecting backwards compatibility
   ``table.mpairs`` iterator only the returned values can be modified, no
   longer the keys.
 - The deprecated Nim shebang notation ``#!`` was removed from the language. Use ``#?`` instead.
+- The ``using`` statement now means something completely different. You can use the
+  new experimental ``this`` pragma to achieve a similar effect to what the old ``using`` statement tried to achieve.
+- Typeless parameters have been removed from the language since it would
+  clash with ``using``.
 
 
 Library Additions
 -----------------
 
 - The rlocks module has been added providing reentrant lock synchronization
-  primitive
+  primitive.
 
 Compiler Additions
 ------------------
 
 - Added a new ``--noCppExceptions`` switch that allows to use default exception
   handling (no ``throw`` or ``try``/``catch`` generated) when compiling to C++
-  code
+  code.
+
+Language Additions
+------------------
+
+- Nim now supports a ``.this`` pragma for more notational convenience.
+- Nim now supports a different ``using`` statement for more convenience.
+- Nim now supports ``partial`` object declarations to mitigate the problems
+  that arise when types are mutually dependent and yet should be kept in
+  different modules.
+
 
 2016-01-27 Nim in Action is now available!
 ==========================================