summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--compiler/parser.nim38
-rw-r--r--compiler/semstmts.nim19
-rw-r--r--doc/grammar.txt2
-rw-r--r--doc/manual.md4
-rw-r--r--lib/pure/concurrency/atomics.nim2
-rw-r--r--lib/pure/pegs.nim2
-rw-r--r--testament/categories.nim7
-rw-r--r--testament/important_packages.nim8
-rw-r--r--tests/assign/tassign.nim2
-rw-r--r--tests/ast_pattern_matching.nim2
-rw-r--r--tests/bind/told_bind_expr.nim (renamed from tests/bind/tbind2.nim)7
-rw-r--r--tests/ccgbugs/targ_lefttoright.nim2
-rw-r--r--tests/ccgbugs/tccgen1.nim2
-rw-r--r--tests/ccgbugs/tmissingbracket.nim2
-rw-r--r--tests/cpp/tdont_init_instantiation.nim2
-rw-r--r--tests/cpp/temitlist.nim2
-rw-r--r--tests/cpp/tvector_iterator.nim4
-rw-r--r--tests/effects/teffects2.nim2
-rw-r--r--tests/effects/teffects3.nim2
-rw-r--r--tests/effects/teffects4.nim2
-rw-r--r--tests/errmsgs/tinvalidinout.nim2
-rw-r--r--tests/exception/tcpp_imported_exc.nim2
-rw-r--r--tests/generics/module_with_generics.nim2
-rw-r--r--tests/generics/tcan.nim2
-rw-r--r--tests/generics/tgeneric3.nim4
-rw-r--r--tests/generics/tinheritable_importcpp.nim10
-rw-r--r--tests/iter/titer2.nim2
-rw-r--r--tests/macros/tgettypeinst.nim4
-rw-r--r--tests/macros/tvtable.nim2
-rw-r--r--tests/method/tmethod_issues.nim2
-rw-r--r--tests/method/tmethod_various.nim4
-rw-r--r--tests/method/tmultim.nim6
-rw-r--r--tests/misc/tsimplesort.nim5
-rw-r--r--tests/objects/tobjconstr2.nim4
-rw-r--r--tests/objects/tobjects_various.nim2
-rw-r--r--tests/statictypes/tstaticimportcpp.nim6
-rw-r--r--tests/stdlib/tstrset.nim2
-rw-r--r--tests/typerel/tcommontype.nim2
-rw-r--r--tests/types/tfinalobj.nim2
-rw-r--r--tests/types/tinheritref.nim4
-rw-r--r--tests/types/told_pragma_syntax1.nim5
-rw-r--r--tests/types/told_pragma_syntax2.nim5
-rw-r--r--tools/grammar_nanny.nim3
44 files changed, 111 insertions, 86 deletions
diff --git a/changelog.md b/changelog.md
index d2a3544a4..a9170ffac 100644
--- a/changelog.md
+++ b/changelog.md
@@ -30,6 +30,8 @@
 
 - The `{.this.}` pragma, deprecated since 0.19, has been removed.
 - `nil` is no longer a valid value for distinct pointer types.
+- Removed two type pragma syntaxes deprecated since 0.20, namely
+  `type Foo = object {.final.}`, and `type Foo {.final.} [T] = object`.
 
 ## Standard library additions and changes
 
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 52466d9fa..8b0a9d1c6 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -20,6 +20,8 @@ when isMainModule:
   # Leave a note in grammar.txt that it is generated:
   #| # This file is generated by compiler/parser.nim.
   import pegs
+  when defined(nimPreviewSlimSystem):
+    import std/syncio
   var outp = open("doc/grammar.txt", fmWrite)
   for line in lines("compiler/parser.nim"):
     if line =~ peg" \s* '#| ' {.*}":
@@ -2031,15 +2033,10 @@ proc parseObjectPart(p: var Parser): PNode =
     result = p.emptyNode
 
 proc parseObject(p: var Parser): PNode =
-  #| objectDecl = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
+  #| objectDecl = 'object' ('of' typeDesc)? COMMENT? objectPart
   result = newNodeP(nkObjectTy, p)
   getTok(p)
-  if p.tok.tokType == tkCurlyDotLe and p.validInd:
-    # Deprecated since v0.20.0
-    parMessage(p, warnDeprecated, "type pragmas follow the type name; this form of writing pragmas is deprecated")
-    result.add(parsePragma(p))
-  else:
-    result.add(p.emptyNode)
+  result.add(p.emptyNode) # compatibility with old pragma node
   if p.tok.tokType == tkOf and p.tok.indent < 0:
     var a = newNodeP(nkOfInherit, p)
     getTok(p)
@@ -2117,39 +2114,24 @@ proc parseTypeClass(p: var Parser): PNode =
 
 proc parseTypeDef(p: var Parser): PNode =
   #|
-  #| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
-  #|             indAndComment? / identVisDot genericParamList? pragma '=' optInd typeDefAux
+  #| typeDef = identVisDot genericParamList? pragma '=' optInd typeDefAux
   #|             indAndComment?
   result = newNodeP(nkTypeDef, p)
   var identifier = identVis(p, allowDot=true)
   var identPragma = identifier
   var pragma: PNode
   var genericParam: PNode
-  var noPragmaYet = true
-
-  if p.tok.tokType == tkCurlyDotLe:
-    pragma = optPragmas(p)
-    identPragma = newNodeP(nkPragmaExpr, p)
-    identPragma.add(identifier)
-    identPragma.add(pragma)
-    noPragmaYet = false
 
   if p.tok.tokType == tkBracketLe and p.validInd:
-    if not noPragmaYet:
-      # Deprecated since v0.20.0
-      parMessage(p, warnDeprecated, "pragma before generic parameter list is deprecated")
     genericParam = parseGenericParamList(p)
   else:
     genericParam = p.emptyNode
 
-  if noPragmaYet:
-    pragma = optPragmas(p)
-    if pragma.kind != nkEmpty:
-      identPragma = newNodeP(nkPragmaExpr, p)
-      identPragma.add(identifier)
-      identPragma.add(pragma)
-  elif p.tok.tokType == tkCurlyDotLe:
-    parMessage(p, errGenerated, "pragma already present")
+  pragma = optPragmas(p)
+  if pragma.kind != nkEmpty:
+    identPragma = newNodeP(nkPragmaExpr, p)
+    identPragma.add(identifier)
+    identPragma.add(pragma)
 
   result.add(identPragma)
   result.add(genericParam)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 6ced487ce..64d56f812 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1327,6 +1327,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
     if s.magic == mNone and a[2].kind == nkEmpty:
       localError(c.config, a.info, errImplOfXexpected % s.name.s)
     if s.magic != mNone: processMagicType(c, s)
+    let oldFlags = s.typ.flags
     if a[1].kind != nkEmpty:
       # We have a generic type declaration here. In generic types,
       # symbol lookup needs to be done here.
@@ -1354,6 +1355,13 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       if body != nil:
         body.sym = s
         body.size = -1 # could not be computed properly
+        if body.kind == tyObject:
+          # add flags applied to generic type to object (nominal) type
+          incl(body.flags, oldFlags)
+          # {.inheritable, final.} is already disallowed, but
+          # object might have been assumed to be final
+          if tfInheritable in oldFlags and tfFinal in body.flags:
+            excl(body.flags, tfFinal)
         s.typ[^1] = body
         if tfCovariant in s.typ.flags:
           checkCovariantParamsUsages(c, s.typ)
@@ -1405,6 +1413,13 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       internalAssert c.config, st.kind in {tyPtr, tyRef}
       internalAssert c.config, st.lastSon.sym == nil
       incl st.flags, tfRefsAnonObj
+      let objTy = st.lastSon
+      # add flags for `ref object` etc to underlying `object`
+      incl(objTy.flags, oldFlags)
+      # {.inheritable, final.} is already disallowed, but
+      # object might have been assumed to be final
+      if tfInheritable in oldFlags and tfFinal in objTy.flags:
+        excl(objTy.flags, tfFinal)
       let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
                        nextSymId c.idgen, getCurrOwner(c), s.info)
       let symNode = newSymNode(obj)
@@ -1420,8 +1435,8 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       obj.ast[2] = a[2][0]
       if sfPure in s.flags:
         obj.flags.incl sfPure
-      obj.typ = st.lastSon
-      st.lastSon.sym = obj
+      obj.typ = objTy
+      objTy.sym = obj
 
 proc checkForMetaFields(c: PContext; n: PNode) =
   proc checkMeta(c: PContext; n: PNode; t: PType) =
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 1e41b9eeb..878a4e5e1 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -171,7 +171,7 @@ objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
             | IND{=} objectBranches)
 objectPart = IND{>} objectPart^+IND{=} DED
            / objectWhen / objectCase / 'nil' / 'discard' / declColonEquals
-objectDecl = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
+objectDecl = 'object' ('of' typeDesc)? COMMENT? objectPart
 conceptParam = ('var' | 'out')? symbol
 conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
               &IND{>} stmt
diff --git a/doc/manual.md b/doc/manual.md
index 2bb91f745..1cbfe6846 100644
--- a/doc/manual.md
+++ b/doc/manual.md
@@ -2893,7 +2893,7 @@ the variable has been initialized and does not rely on syntactic properties:
 
   ```nim
   type
-    MyObject = object {.requiresInit.}
+    MyObject {.requiresInit.} = object
 
   proc p() =
     # the following is valid:
@@ -7775,7 +7775,7 @@ Produces:
 
     ```nim
     type
-      VectorIterator {.importcpp: "std::vector<'0>::iterator".} [T] = object
+      VectorIterator[T] {.importcpp: "std::vector<'0>::iterator".} = object
 
     var x: VectorIterator[cint]
     ```
diff --git a/lib/pure/concurrency/atomics.nim b/lib/pure/concurrency/atomics.nim
index c0a122bf9..315f44f33 100644
--- a/lib/pure/concurrency/atomics.nim
+++ b/lib/pure/concurrency/atomics.nim
@@ -286,7 +286,7 @@ else:
         moSequentiallyConsistent
 
     type
-      # Atomic* {.importcpp: "_Atomic('0)".} [T] = object
+      # Atomic*[T] {.importcpp: "_Atomic('0)".} = object
 
       AtomicInt8 {.importc: "_Atomic NI8".} = int8
       AtomicInt16 {.importc: "_Atomic NI16".} = int16
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 78f03d308..6319be551 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -17,7 +17,7 @@
 
 include "system/inclrtl"
 when defined(nimPreviewSlimSystem):
-  import std/syncio
+  import std/[syncio, assertions]
 
 const
   useUnicode = true ## change this to deactivate proper UTF-8 support
diff --git a/testament/categories.nim b/testament/categories.nim
index 43ea9f0ee..612f5287f 100644
--- a/testament/categories.nim
+++ b/testament/categories.nim
@@ -13,7 +13,7 @@
 # included from testament.nim
 
 import important_packages
-import std/strformat
+import std/[strformat, strutils]
 from std/sequtils import filterIt
 
 const
@@ -448,7 +448,10 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
           let describeOutput = tryCommand("git describe --tags --abbrev=0")
           discard tryCommand("git checkout $#" % [describeOutput.strip.quoteShell])
         discard tryCommand("nimble install --depsOnly -y", maxRetries = 3)
-      discard tryCommand(pkg.cmd, reFailed = reBuildFailed)
+      let cmds = pkg.cmd.split(';')
+      for i in 0 ..< cmds.len - 1:
+        discard tryCommand(cmds[i], maxRetries = 3)
+      discard tryCommand(cmds[^1], reFailed = reBuildFailed)
       inc r.passed
       r.addResult(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
 
diff --git a/testament/important_packages.nim b/testament/important_packages.nim
index c8fb5ad3c..e9b06754d 100644
--- a/testament/important_packages.nim
+++ b/testament/important_packages.nim
@@ -98,18 +98,18 @@ pkg "nicy", "nim c -r src/nicy.nim"
 pkg "nigui", "nim c -o:niguii -r src/nigui.nim"
 pkg "nimcrypto", "nim r --path:. tests/testall.nim" # `--path:.` workaround needed, see D20210308T165435
 pkg "NimData", "nim c -o:nimdataa src/nimdata.nim"
-pkg "nimes", "nim c src/nimes.nim"
+pkg "nimes", "nimble install -y sdl2@#HEAD;nim c src/nimes.nim"
 pkg "nimfp", "nim c -o:nfp -r src/fp.nim"
 pkg "nimgame2", "nim c nimgame2/nimgame.nim"
   # XXX Doesn't work with deprecated 'randomize', will create a PR.
 pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim"
-pkg "nimlsp"
+pkg "nimlsp", allowFailure = true # dependency on ast_pattern_matching
 pkg "nimly", "nim c -r tests/test_readme_example.nim"
 pkg "nimongo", "nimble test_ci", allowFailure = true
 pkg "nimph", "nimble test", "https://github.com/disruptek/nimph", allowFailure = true
 pkg "nimpy", "nim c -r tests/nimfrompy.nim"
 pkg "nimquery"
-pkg "nimsl"
+pkg "nimsl", "nimble install -y variant@#HEAD;nimble test"
 pkg "nimsvg"
 pkg "nimterop", "nimble minitest"
 pkg "nimwc", "nim c nimwc.nim"
@@ -157,7 +157,7 @@ pkg "tiny_sqlite"
 pkg "unicodedb", "nim c -d:release -r tests/tests.nim"
 pkg "unicodeplus", "nim c -d:release -r tests/tests.nim"
 pkg "unpack"
-pkg "weave", "nimble test_gc_arc"
+pkg "weave", "nimble install -y cligen synthesis;nimble test_gc_arc"
 pkg "websocket", "nim c websocket.nim"
 pkg "winim", "nim c winim.nim"
 pkg "with"
diff --git a/tests/assign/tassign.nim b/tests/assign/tassign.nim
index da097ca83..fdec04d22 100644
--- a/tests/assign/tassign.nim
+++ b/tests/assign/tassign.nim
@@ -80,7 +80,7 @@ block tcopy:
 
 block tgenericassign:
   type
-    TAny = object {.pure.}
+    TAny {.pure.} = object
       value: pointer
       rawType: pointer
 
diff --git a/tests/ast_pattern_matching.nim b/tests/ast_pattern_matching.nim
index d209493b6..0ba0aa57a 100644
--- a/tests/ast_pattern_matching.nim
+++ b/tests/ast_pattern_matching.nim
@@ -561,7 +561,7 @@ when isMainModule:
         echo "got the ident m"
 
     testRecCase:
-      type Obj[T] = object {.inheritable.}
+      type Obj[T] {.inheritable.} = object
         name: string
         case isFat: bool
         of true:
diff --git a/tests/bind/tbind2.nim b/tests/bind/told_bind_expr.nim
index fc2eeda1a..56389eaf6 100644
--- a/tests/bind/tbind2.nim
+++ b/tests/bind/told_bind_expr.nim
@@ -1,9 +1,10 @@
 discard """
   errormsg: "ambiguous call"
-  file: "tbind2.nim"
-  line: 12
+  file: "told_bind_expr.nim"
+  line: 13
 """
-# Test the new ``bind`` keyword for templates
+
+# Pre-0.9 deprecated bind expression syntax
 
 proc p1(x: int8, y: int): int = return x + y
 proc p1(x: int, y: int8): int = return x - y
diff --git a/tests/ccgbugs/targ_lefttoright.nim b/tests/ccgbugs/targ_lefttoright.nim
index a49b87739..a0adce157 100644
--- a/tests/ccgbugs/targ_lefttoright.nim
+++ b/tests/ccgbugs/targ_lefttoright.nim
@@ -29,7 +29,7 @@ template test =
   var b = 1
   say (b += 1; b), (b += 1; b) #2,3
 
-  type C = object {.byRef.}
+  type C {.byRef.} = object
     i: int
 
   proc say(a, b: C) =
diff --git a/tests/ccgbugs/tccgen1.nim b/tests/ccgbugs/tccgen1.nim
index 4917c9848..be571de08 100644
--- a/tests/ccgbugs/tccgen1.nim
+++ b/tests/ccgbugs/tccgen1.nim
@@ -7,7 +7,7 @@ type
     Features: seq[Feature] # Read-Only
 
   PNode* = ref Node
-  Node = object {.inheritable.}
+  Node {.inheritable.} = object
     attributes*: seq[PAttr]
     childNodes*: seq[PNode]
     FLocalName: string # Read-only
diff --git a/tests/ccgbugs/tmissingbracket.nim b/tests/ccgbugs/tmissingbracket.nim
index 468e13366..2919efe0e 100644
--- a/tests/ccgbugs/tmissingbracket.nim
+++ b/tests/ccgbugs/tmissingbracket.nim
@@ -11,7 +11,7 @@ type
     className* : string
   TClassOfTobj = object of TClassOfTCustomObject
     nil
-  TCustomObject = ref object {.inheritable.}
+  TCustomObject {.inheritable.} = ref object
     class* : ptr TClassOfTCustomObject
   TObj = ref object of TCustomObject
     data: int
diff --git a/tests/cpp/tdont_init_instantiation.nim b/tests/cpp/tdont_init_instantiation.nim
index fe487fba0..a13a3f6b4 100644
--- a/tests/cpp/tdont_init_instantiation.nim
+++ b/tests/cpp/tdont_init_instantiation.nim
@@ -20,7 +20,7 @@ template <typename X> class C {
 };
 """.}
 
-type C{.importcpp, header: "<stdio.h>", nodecl.} [X] = object
+type C[X] {.importcpp, header: "<stdio.h>", nodecl.} = object
 proc mkC[X]: C[X] {.importcpp: "C<'*0>()", constructor, nodecl.}
 
 proc foo(): C[int] =
diff --git a/tests/cpp/temitlist.nim b/tests/cpp/temitlist.nim
index d446176fa..9170be079 100644
--- a/tests/cpp/temitlist.nim
+++ b/tests/cpp/temitlist.nim
@@ -8,7 +8,7 @@ disabled: "windows" # pending bug #18011
 
 # bug #4730
 
-type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
+type Vector*[T] {.importcpp: "std::vector", header: "<vector>".} = object
 
 template `[]=`*[T](v: var Vector[T], key: int, val: T) =
   {.emit: [v, "[", key, "] = ", val, ";"].}
diff --git a/tests/cpp/tvector_iterator.nim b/tests/cpp/tvector_iterator.nim
index 4d686955f..c3886c547 100644
--- a/tests/cpp/tvector_iterator.nim
+++ b/tests/cpp/tvector_iterator.nim
@@ -12,8 +12,8 @@ struct Vector {
 """.}
 
 type
-  Vector {.importcpp: "Vector".} [T] = object
-  VectorIterator {.importcpp: "Vector<'0>::Iterator".} [T] = object
+  Vector[T] {.importcpp: "Vector".} = object
+  VectorIterator[T] {.importcpp: "Vector<'0>::Iterator".} = object
 
 var x: VectorIterator[void]
 
diff --git a/tests/effects/teffects2.nim b/tests/effects/teffects2.nim
index ec3c0a887..777a4cebc 100644
--- a/tests/effects/teffects2.nim
+++ b/tests/effects/teffects2.nim
@@ -4,7 +4,7 @@ discard """
 """
 {.push warningAsError[Effect]: on.}
 type
-  TObj = object {.pure, inheritable.}
+  TObj {.pure, inheritable.} = object
   TObjB = object of TObj
     a, b, c: string
 
diff --git a/tests/effects/teffects3.nim b/tests/effects/teffects3.nim
index ee5470c47..4c050510a 100644
--- a/tests/effects/teffects3.nim
+++ b/tests/effects/teffects3.nim
@@ -4,7 +4,7 @@ discard """
 """
 
 type
-  TObj = object {.pure, inheritable.}
+  TObj {.pure, inheritable.} = object
   TObjB = object of TObj
     a, b, c: string
     fn: proc (): int {.tags: [].}
diff --git a/tests/effects/teffects4.nim b/tests/effects/teffects4.nim
index 88cc0efa9..b875754b6 100644
--- a/tests/effects/teffects4.nim
+++ b/tests/effects/teffects4.nim
@@ -4,7 +4,7 @@ discard """
 """
 
 type
-  TObj = object {.pure, inheritable.}
+  TObj {.pure, inheritable.} = object
   TObjB = object of TObj
     a, b, c: string
     fn: proc (): int {.tags: [ReadIOEffect].}
diff --git a/tests/errmsgs/tinvalidinout.nim b/tests/errmsgs/tinvalidinout.nim
index 1fa3805ee..268bcf4d5 100644
--- a/tests/errmsgs/tinvalidinout.nim
+++ b/tests/errmsgs/tinvalidinout.nim
@@ -9,7 +9,7 @@ tinvalidinout.nim(18, 9) Error: the 'in' modifier can be used only with imported
 """
 
 type
-  Foo {.header: "foo.h", importcpp.} [in T] = object
+  Foo[in T] {.header: "foo.h", importcpp.} = object
 
   Bar[out X] = object
     x: int
diff --git a/tests/exception/tcpp_imported_exc.nim b/tests/exception/tcpp_imported_exc.nim
index 5195b48e7..8ab7b8780 100644
--- a/tests/exception/tcpp_imported_exc.nim
+++ b/tests/exception/tcpp_imported_exc.nim
@@ -76,7 +76,7 @@ doAssert(getCurrentException() == nil)
 # raise by pointer and also generic type
 
 type
-  std_vector {.importcpp"std::vector", header"<vector>".} [T] = object
+  std_vector[T] {.importcpp"std::vector", header"<vector>".} = object
 
 proc newVector[T](len: int): ptr std_vector[T] {.importcpp: "new std::vector<'1>(@)".}
 proc deleteVector[T](v: ptr std_vector[T]) {.importcpp: "delete @; @ = NIM_NIL;".}
diff --git a/tests/generics/module_with_generics.nim b/tests/generics/module_with_generics.nim
index e801a4790..960a694d7 100644
--- a/tests/generics/module_with_generics.nim
+++ b/tests/generics/module_with_generics.nim
@@ -1,5 +1,5 @@
 type
-  Base[T] = ref object {.inheritable.}
+  Base[T] {.inheritable.} = ref object
     value*: T
 
   Derived[T] = ref object of Base[T]
diff --git a/tests/generics/tcan.nim b/tests/generics/tcan.nim
index eea69cdb7..bbefa7233 100644
--- a/tests/generics/tcan.nim
+++ b/tests/generics/tcan.nim
@@ -31,7 +31,7 @@ block tinherit:
 
 block tspecialise:
   type
-    TGen[T] = object {.inheritable.}
+    TGen[T] {.inheritable.} = object
     TSpef = object of TGen[string]
 
 
diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim
index 4cb12f91b..78183c7ca 100644
--- a/tests/generics/tgeneric3.nim
+++ b/tests/generics/tgeneric3.nim
@@ -12,7 +12,7 @@ import strutils
 
 type
   PNode[T,D] = ref TNode[T,D]
-  TItem {.acyclic, pure, final, shallow.} [T,D] = object
+  TItem[T,D] {.acyclic, pure, final, shallow.} = object
         key: T
         value: D
         node: PNode[T,D]
@@ -20,7 +20,7 @@ type
           val_set: bool
 
   TItems[T,D] = seq[ref TItem[T,D]]
-  TNode {.acyclic, pure, final, shallow.} [T,D] = object
+  TNode[T,D] {.acyclic, pure, final, shallow.} = object
         slots: TItems[T,D]
         left: PNode[T,D]
         count: int32
diff --git a/tests/generics/tinheritable_importcpp.nim b/tests/generics/tinheritable_importcpp.nim
new file mode 100644
index 000000000..8ee18b70b
--- /dev/null
+++ b/tests/generics/tinheritable_importcpp.nim
@@ -0,0 +1,10 @@
+discard """
+  targets: "cpp"
+  action: compile
+"""
+
+# #4651
+type
+  Vector[T] {.importcpp: "std::vector<'0 >", header: "vector", inheritable.} = object
+  VectorDerived {.importcpp: "SomeVectorDerived", nodecl.} = object of Vector[int]
+  # Error: inheritance only works with non-final objects
diff --git a/tests/iter/titer2.nim b/tests/iter/titer2.nim
index f60aed73a..975cc786c 100644
--- a/tests/iter/titer2.nim
+++ b/tests/iter/titer2.nim
@@ -17,7 +17,7 @@ type
   TSlotEnum = enum seEmpty, seFilled, seDeleted
   TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
   TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
-  TTable* {.final.}[A, B] = object
+  TTable*[A, B] {.final.} = object
     data: TKeyValuePairSeq[A, B]
     counter: int
 
diff --git a/tests/macros/tgettypeinst.nim b/tests/macros/tgettypeinst.nim
index 2f9557160..e722f14aa 100644
--- a/tests/macros/tgettypeinst.nim
+++ b/tests/macros/tgettypeinst.nim
@@ -191,14 +191,14 @@ template myAttr3() {.pragma.}
 template serializationKey(key: string) {.pragma.}
 
 type
-  MyObj = object {.packed,myAttr,serializationKey: "one".}
+  MyObj {.packed,myAttr,serializationKey: "one".} = object
     myField {.myAttr2,serializationKey: "two".}: int
     myField2 {.myAttr3,serializationKey: "three".}: float
 
 # field pragmas not currently supported
 test(MyObj):
   type
-    _ = object {.packed,myAttr,serializationKey: "one".}
+    _ {.packed,myAttr,serializationKey: "one".} = object
       myField: int
       myField2: float
 
diff --git a/tests/macros/tvtable.nim b/tests/macros/tvtable.nim
index dc07a726b..0f322b7d5 100644
--- a/tests/macros/tvtable.nim
+++ b/tests/macros/tvtable.nim
@@ -18,7 +18,7 @@ type
   # it's also possible to use a strongly typed tuple here
   VTable = array[0..1, pointer]
 
-  TBase = object {.inheritable.}
+  TBase {.inheritable.} = object
     vtbl: ptr VTable
 
   TUserObject1 = object of TBase
diff --git a/tests/method/tmethod_issues.nim b/tests/method/tmethod_issues.nim
index 13467f2b3..07d4635f6 100644
--- a/tests/method/tmethod_issues.nim
+++ b/tests/method/tmethod_issues.nim
@@ -10,7 +10,7 @@ type B
 
 
 # bug #1659
-type Animal = ref object {.inheritable.}
+type Animal {.inheritable.} = ref object
 type Dog = ref object of Animal
 
 method say(a: Animal): auto {.base.} = "wat!"
diff --git a/tests/method/tmethod_various.nim b/tests/method/tmethod_various.nim
index f9d067a72..c41d04983 100644
--- a/tests/method/tmethod_various.nim
+++ b/tests/method/tmethod_various.nim
@@ -12,7 +12,7 @@ method somethin(obj: RootObj) {.base.} =
   echo "do nothing"
 
 type
-  TNode* = object {.inheritable.}
+  TNode* {.inheritable.} = object
   PNode* = ref TNode
 
   PNodeFoo* = ref object of TNode
@@ -30,7 +30,7 @@ o.somethin()
 
 # tmproto
 type
-  Obj1 = ref object {.inheritable.}
+  Obj1 {.inheritable.} = ref object
   Obj2 = ref object of Obj1
 
 method beta(x: Obj1): int {.base.}
diff --git a/tests/method/tmultim.nim b/tests/method/tmultim.nim
index b6fed024e..126eb7526 100644
--- a/tests/method/tmultim.nim
+++ b/tests/method/tmultim.nim
@@ -16,7 +16,7 @@ do nothing
 
 # tmultim2
 type
-  TThing = object {.inheritable.}
+  TThing {.inheritable.} = object
   TUnit = object of TThing
     x: int
   TParticle = object of TThing
@@ -49,7 +49,7 @@ staticCollide(a, b)
 
 # tmultim6
 type
-  Thing = object {.inheritable.}
+  Thing {.inheritable.} = object
   Unit[T] = object of Thing
     x: T
   Particle = object of Thing
@@ -81,7 +81,7 @@ method somethin(obj: RootObj) {.base.} =
   echo "do nothing"
 
 type
-  TNode* = object {.inheritable.}
+  TNode* {.inheritable.} = object
   PNode* = ref TNode
 
   PNodeFoo* = ref object of TNode
diff --git a/tests/misc/tsimplesort.nim b/tests/misc/tsimplesort.nim
index 4793c63df..395db55e6 100644
--- a/tests/misc/tsimplesort.nim
+++ b/tests/misc/tsimplesort.nim
@@ -10,7 +10,7 @@ type
   TSlotEnum = enum seEmpty, seFilled, seDeleted
   TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
   TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
-  TTable* {.final, myShallow.}[A, B] = object
+  TTable*[A, B] {.final, myShallow.} = object
     data: TKeyValuePairSeq[A, B]
     counter: int
 
@@ -137,8 +137,7 @@ proc `$`*[A, B](t: TTable[A, B]): string =
 # ------------------------------ count tables -------------------------------
 
 type
-  TCountTable* {.final, myShallow.}[
-      A] = object ## table that counts the number of each key
+  TCountTable*[A] {.final, myShallow.} = object ## table that counts the number of each key
     data: seq[tuple[key: A, val: int]]
     counter: int
 
diff --git a/tests/objects/tobjconstr2.nim b/tests/objects/tobjconstr2.nim
index 6253edab0..cf4a694b4 100644
--- a/tests/objects/tobjconstr2.nim
+++ b/tests/objects/tobjconstr2.nim
@@ -15,8 +15,8 @@ echo s[0].x
 
 # bug #563
 type
-  Foo =
-    object {.inheritable.}
+  Foo {.inheritable.} =
+    object
       x: int
 
   Bar =
diff --git a/tests/objects/tobjects_various.nim b/tests/objects/tobjects_various.nim
index 315193de9..8ec090f42 100644
--- a/tests/objects/tobjects_various.nim
+++ b/tests/objects/tobjects_various.nim
@@ -31,7 +31,7 @@ block tobject2:
 
 block tofopr:
   type
-    TMyType = object {.inheritable.}
+    TMyType {.inheritable.} = object
       len: int
       data: string
 
diff --git a/tests/statictypes/tstaticimportcpp.nim b/tests/statictypes/tstaticimportcpp.nim
index 125dcb98d..ec4696379 100644
--- a/tests/statictypes/tstaticimportcpp.nim
+++ b/tests/statictypes/tstaticimportcpp.nim
@@ -23,12 +23,12 @@ struct SimpleStruct {
 """ .}
 
 type
-  GenericIntType {.importcpp: "GenericIntType<'0, '1>".} [N: static[int]; T] = object
+  GenericIntType[N: static[int]; T] {.importcpp: "GenericIntType<'0, '1>".} = object
     data: array[N, T]
 
-  GenericIntTypeAlt {.importcpp: "GenericIntType".} [N: static[int]; T] = object
+  GenericIntTypeAlt[N: static[int]; T] {.importcpp: "GenericIntType".} = object
 
-  GenericTType {.importcpp: "GenericTType<'0>".} [T] = object
+  GenericTType[T] {.importcpp: "GenericTType<'0>".} = object
     field: T
 
   GenInt4 = GenericIntType[4, int]
diff --git a/tests/stdlib/tstrset.nim b/tests/stdlib/tstrset.nim
index 71a5520c2..feae66ff7 100644
--- a/tests/stdlib/tstrset.nim
+++ b/tests/stdlib/tstrset.nim
@@ -3,7 +3,7 @@
 type
   TRadixNodeKind = enum rnLinear, rnFull, rnLeaf
   PRadixNode = ref TRadixNode
-  TRadixNode = object {.inheritable.}
+  TRadixNode {.inheritable.} = object
     kind: TRadixNodeKind
   TRadixNodeLinear = object of TRadixNode
     len: int8
diff --git a/tests/typerel/tcommontype.nim b/tests/typerel/tcommontype.nim
index 488047fd1..f32228177 100644
--- a/tests/typerel/tcommontype.nim
+++ b/tests/typerel/tcommontype.nim
@@ -1,5 +1,5 @@
 type
-  TAnimal=object {.inheritable.}
+  TAnimal{.inheritable.}=object
   PAnimal=ref TAnimal
 
   TDog=object of TAnimal
diff --git a/tests/types/tfinalobj.nim b/tests/types/tfinalobj.nim
index 94f2e4f0e..ad3085132 100644
--- a/tests/types/tfinalobj.nim
+++ b/tests/types/tfinalobj.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 type
-  TA = object {.pure, final.}
+  TA {.pure, final.} = object
     x: string
 
 var
diff --git a/tests/types/tinheritref.nim b/tests/types/tinheritref.nim
index 01f2307c0..b79926356 100644
--- a/tests/types/tinheritref.nim
+++ b/tests/types/tinheritref.nim
@@ -11,11 +11,11 @@ ob = T[int](elem: 23)
 doAssert ob.elem == 23
 
 type
-  TTreeIteratorA* = ref object {.inheritable.}
+  TTreeIteratorA* {.inheritable.} = ref object
 
   TKeysIteratorA* = ref object of TTreeIteratorA  #compiles
 
-  TTreeIterator* [T,D] = ref object {.inheritable.}
+  TTreeIterator* [T,D] {.inheritable.} = ref object
 
   TKeysIterator* [T,D] = ref object of TTreeIterator[T,D]  #this not
 
diff --git a/tests/types/told_pragma_syntax1.nim b/tests/types/told_pragma_syntax1.nim
new file mode 100644
index 000000000..49823662d
--- /dev/null
+++ b/tests/types/told_pragma_syntax1.nim
@@ -0,0 +1,5 @@
+discard """
+  errormsg: "invalid indentation"
+"""
+
+type Foo = object {.final.}
diff --git a/tests/types/told_pragma_syntax2.nim b/tests/types/told_pragma_syntax2.nim
new file mode 100644
index 000000000..eea185725
--- /dev/null
+++ b/tests/types/told_pragma_syntax2.nim
@@ -0,0 +1,5 @@
+discard """
+  errormsg: "invalid indentation"
+"""
+
+type Bar {.final.} [T] = object
diff --git a/tools/grammar_nanny.nim b/tools/grammar_nanny.nim
index 502412c3c..bcb3a044f 100644
--- a/tools/grammar_nanny.nim
+++ b/tools/grammar_nanny.nim
@@ -3,6 +3,9 @@
 
 import std / [strutils, sets]
 
+when defined(nimPreviewSlimSystem):
+  import std/syncio
+
 import ".." / compiler / [
   llstream, lexer, options, msgs, idents,
   lineinfos, pathutils]