summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-04-26 22:05:03 +0800
committerGitHub <noreply@github.com>2024-04-26 16:05:03 +0200
commitf682dabf71f35833e934a79007906f94d8d32c92 (patch)
treefcf6ecd98957bbc83d0d51665468537ed5d2c44a
parent0b0f185bd1db2500079aefd888078b6bd1094270 (diff)
downloadNim-f682dabf71f35833e934a79007906f94d8d32c92.tar.gz
fixes #23531; fixes invalid meta type accepted in the object fields (#23532)
fixes #23531
fixes #19546
fixes #6982
-rw-r--r--compiler/semstmts.nim26
-rw-r--r--tests/errmsgs/tmetaobjectfields.nim61
2 files changed, 78 insertions, 9 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 7ccc29d7e..a29b07d92 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1589,21 +1589,27 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
   for sk in c.skipTypes:
     discard semTypeNode(c, sk, nil)
   c.skipTypes = @[]
-proc checkForMetaFields(c: PContext; n: PNode) =
-  proc checkMeta(c: PContext; n: PNode; t: PType) =
-    if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
+
+proc checkForMetaFields(c: PContext; n: PNode; hasError: var bool) =
+  proc checkMeta(c: PContext; n: PNode; t: PType; hasError: var bool; parent: PType) =
+    if t != nil and (t.isMetaType or t.kind == tyNone) and tfGenericTypeParam notin t.flags:
       if t.kind == tyBuiltInTypeClass and t.len == 1 and t.elementType.kind == tyProc:
         localError(c.config, n.info, ("'$1' is not a concrete type; " &
           "for a callback without parameters use 'proc()'") % t.typeToString)
+      elif t.kind == tyNone and parent != nil:
+        # TODO: openarray has the `tfGenericTypeParam` flag & generics
+        # TODO: handle special cases (sink etc.) and views
+        localError(c.config, n.info, errTIsNotAConcreteType % parent.typeToString)
       else:
         localError(c.config, n.info, errTIsNotAConcreteType % t.typeToString)
+      hasError = true
 
   if n.isNil: return
   case n.kind
   of nkRecList, nkRecCase:
-    for s in n: checkForMetaFields(c, s)
+    for s in n: checkForMetaFields(c, s, hasError)
   of nkOfBranch, nkElse:
-    checkForMetaFields(c, n.lastSon)
+    checkForMetaFields(c, n.lastSon, hasError)
   of nkSym:
     let t = n.sym.typ
     case t.kind
@@ -1611,9 +1617,9 @@ proc checkForMetaFields(c: PContext; n: PNode) =
        tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink, tyOwned:
       let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
       for i in start..<t.len:
-        checkMeta(c, n, t[i])
+        checkMeta(c, n, t[i], hasError, t)
     else:
-      checkMeta(c, n, t)
+      checkMeta(c, n, t, hasError, nil)
   else:
     internalAssert c.config, false
 
@@ -1648,9 +1654,11 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
               assert s.typ != nil
               assignType(s.typ, t)
               s.typ.itemId = t.itemId     # same id
-        checkConstructedType(c.config, s.info, s.typ)
+        var hasError = false
         if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
-          checkForMetaFields(c, s.typ.n)
+          checkForMetaFields(c, s.typ.n, hasError)
+        if not hasError:
+          checkConstructedType(c.config, s.info, s.typ)
 
         # fix bug #5170, bug #17162, bug #15526: ensure locally scoped types get a unique name:
         if s.typ.kind in {tyEnum, tyRef, tyObject} and not isTopLevel(c):
diff --git a/tests/errmsgs/tmetaobjectfields.nim b/tests/errmsgs/tmetaobjectfields.nim
new file mode 100644
index 000000000..837041512
--- /dev/null
+++ b/tests/errmsgs/tmetaobjectfields.nim
@@ -0,0 +1,61 @@
+discard """
+  cmd: "nim check --hints:off $file"
+  action: "reject"
+  nimout: '''
+tmetaobjectfields.nim(24, 5) Error: 'array' is not a concrete type
+tmetaobjectfields.nim(28, 5) Error: 'seq' is not a concrete type
+tmetaobjectfields.nim(32, 5) Error: 'set' is not a concrete type
+tmetaobjectfields.nim(35, 3) Error: 'sink' is not a concrete type
+tmetaobjectfields.nim(37, 3) Error: 'lent' is not a concrete type
+tmetaobjectfields.nim(54, 16) Error: 'seq' is not a concrete type
+tmetaobjectfields.nim(58, 5) Error: 'ptr' is not a concrete type
+tmetaobjectfields.nim(59, 5) Error: 'ref' is not a concrete type
+tmetaobjectfields.nim(60, 5) Error: 'auto' is not a concrete type
+tmetaobjectfields.nim(61, 5) Error: 'UncheckedArray' is not a concrete type
+'''
+"""
+
+
+# bug #6982
+# bug #19546
+# bug #23531
+type
+  ExampleObj1 = object
+    arr: array
+
+type
+  ExampleObj2 = object
+    arr: seq
+
+type
+  ExampleObj3 = object
+    arr: set
+
+type A = object
+  b: sink
+  # a: openarray
+  c: lent
+
+type PropertyKind = enum
+  tInt,
+  tFloat,
+  tBool,
+  tString,
+  tArray
+
+type
+  Property = ref PropertyObj
+  PropertyObj = object
+    case kind: PropertyKind
+    of tInt: intValue: int
+    of tFloat: floatValue: float
+    of tBool: boolValue: bool
+    of tString: stringValue: string
+    of tArray: arrayValue: seq
+
+type
+  RegressionTest = object
+    a: ptr
+    b: ref
+    c: auto
+    d: UncheckedArray