summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorNeelesh Chandola <neelesh.chandola@outlook.com>2020-05-29 15:18:15 +0530
committerGitHub <noreply@github.com>2020-05-29 11:48:15 +0200
commit4c08e64e9868dabca4a1a82979b74bda5c7d0329 (patch)
treeeb666279521d0934bd35ff5609ee2e5be6f452df
parent579456d52073229bfe362d3794fae22a479dda38 (diff)
downloadNim-4c08e64e9868dabca4a1a82979b74bda5c7d0329.tar.gz
disallow typedesc in arrays & move existing checks to `types.typeAllowedAux` (#13261)
* disallow typedesc in arrays and move previous checks to types.typeAllowedAux
-rw-r--r--compiler/sem.nim12
-rw-r--r--compiler/semstmts.nim45
-rw-r--r--compiler/types.nim32
-rw-r--r--tests/array/t9932.nim11
-rw-r--r--tests/errmsgs/t10489_a.nim2
-rw-r--r--tests/errmsgs/t10489_b.nim2
-rw-r--r--tests/errmsgs/t12844.nim6
-rw-r--r--tests/errmsgs/t5870.nim2
-rw-r--r--tests/errmsgs/t8610.nim2
-rw-r--r--tests/errmsgs/ttypeAllowed.nim2
-rw-r--r--tests/metatype/typedesc_as_value.nim2
-rw-r--r--tests/typerel/typedescs2.nim2
12 files changed, 70 insertions, 50 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 62e3ca8db..683c67254 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -233,13 +233,15 @@ proc typeAllowedCheck(conf: ConfigRef; info: TLineInfo; typ: PType; kind: TSymKi
                       flags: TTypeAllowedFlags = {}) =
   let t = typeAllowed(typ, kind, flags)
   if t != nil:
+    var err: string
     if t == typ:
-      localError(conf, info, "invalid type: '" & typeToString(typ) &
-        "' for " & substr($kind, 2).toLowerAscii)
+      err = "invalid type: '$1' for $2" % [typeToString(typ), toHumanStr(kind)]
+      if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
+        err &= ". Did you mean to call the $1 with '()'?" % [toHumanStr(typ.owner.kind)]
     else:
-      localError(conf, info, "invalid type: '" & typeToString(t) &
-        "' in this context: '" & typeToString(typ) &
-        "' for " & substr($kind, 2).toLowerAscii)
+      err = "invalid type: '$1' in this context: '$2' for $3" % [typeToString(t),
+              typeToString(typ), toHumanStr(kind)]
+    localError(conf, info, err)
 
 proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
   typeAllowedCheck(c.config, typ.n.info, typ, skProc)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 3faa32808..a4b4c9362 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -36,8 +36,6 @@ const
   errRecursiveDependencyX = "recursive dependency: '$1'"
   errRecursiveDependencyIteratorX = "recursion is not supported in iterators: '$1'"
   errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1"
-  errCannotAssignMacroSymbol = "cannot assign $1 '$2' to '$3'. Did you mean to call the $1 with '()'?"
-  errInvalidTypeDescAssign = "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
 
 proc semDiscard(c: PContext, n: PNode): PNode =
   result = n
@@ -491,19 +489,16 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     if a[^2].kind != nkEmpty:
       typ = semTypeNode(c, a[^2], nil)
 
+    var typFlags: TTypeAllowedFlags
+
     var def: PNode = c.graph.emptyNode
     if a[^1].kind != nkEmpty:
       def = semExprWithType(c, a[^1], {efAllowDestructor})
-      if def.typ.kind == tyProc and def.kind == nkSym:
-        if def.sym.kind in {skMacro, skTemplate}:
-          localError(c.config, def.info, errCannotAssignMacroSymbol % [
-                          if def.sym.kind == skMacro: "macro" else: "template",
-                          def.sym.name.s, a[0].ident.s])
-          def.typ = errorType(c)
+
+      if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
+        typFlags.incl taIsTemplateOrMacro
       elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
-        # prevent the all too common 'var x = int' bug:
-        localError(c.config, def.info, errInvalidTypeDescAssign)
-        def.typ = errorType(c)
+        typFlags.incl taProcContextIsNotMacro
 
       if typ != nil:
         if typ.isMetaType:
@@ -534,7 +529,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
 
     # this can only happen for errornous var statements:
     if typ == nil: continue
-    typeAllowedCheck(c.config, a.info, typ, symkind, if c.matchedConcept != nil: {taConcept} else: {})
+
+    if c.matchedConcept != nil:
+      typFlags.incl taConcept
+    typeAllowedCheck(c.config, a.info, typ, symkind, typFlags)
+
     when false: liftTypeBoundOps(c, typ, a.info)
     instAllTypeBoundOp(c, a.info)
     var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
@@ -642,18 +641,15 @@ proc semConst(c: PContext, n: PNode): PNode =
     if a[^2].kind != nkEmpty:
       typ = semTypeNode(c, a[^2], nil)
 
+    var typFlags: TTypeAllowedFlags
+
     # don't evaluate here since the type compatibility check below may add a converter
     var def = semExprWithType(c, a[^1])
-    if def.typ.kind == tyProc and def.kind == nkSym:
-      if def.sym.kind in {skMacro, skTemplate}:
-        localError(c.config, def.info, errCannotAssignMacroSymbol % [
-          if def.sym.kind == skMacro: "macro" else: "template",
-          def.sym.name.s, a[0].ident.s])
-        def.typ = errorType(c)
+
+    if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
+      typFlags.incl taIsTemplateOrMacro
     elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
-      # prevent the all too common 'const x = int' bug:
-      localError(c.config, def.info, errInvalidTypeDescAssign)
-      def.typ = errorType(c)
+      typFlags.incl taProcContextIsNotMacro
 
     # check type compatibility between def.typ and typ:
     if typ != nil:
@@ -670,9 +666,10 @@ proc semConst(c: PContext, n: PNode): PNode =
     if def == nil:
       localError(c.config, a[^1].info, errConstExprExpected)
       continue
-    if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit:
-      localError(c.config, a.info, "invalid type for const: " & typeToString(typ))
-      continue
+    if def.kind != nkNilLit:
+      if c.matchedConcept != nil:
+        typFlags.incl taConcept
+      typeAllowedCheck(c.config, a.info, typ, skConst, typFlags)
 
     var b: PNode
     if a.kind == nkVarTuple:
diff --git a/compiler/types.nim b/compiler/types.nim
index 709e5bb2e..e1b283f87 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1246,6 +1246,8 @@ type
     taConcept,
     taIsOpenArray,
     taNoUntyped
+    taIsTemplateOrMacro
+    taProcContextIsNotMacro
 
   TTypeAllowedFlags* = set[TTypeAllowedFlag]
 
@@ -1307,18 +1309,24 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
         if kind notin {skParam, skResult}: result = t
         else: result = typeAllowedAux(marker, t2, kind, flags)
   of tyProc:
-    if isInlineIterator(typ) and kind in {skVar, skLet, skConst, skParam, skResult}:
-      # only closure iterators my be assigned to anything.
+    if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
       result = t
-    let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags
-    for i in 1..<t.len:
-      if result != nil: break
-      result = typeAllowedAux(marker, t[i], skParam, f-{taIsOpenArray})
-    if result.isNil and t[0] != nil:
-      result = typeAllowedAux(marker, t[0], skResult, flags)
+    else:
+      if isInlineIterator(typ) and kind in {skVar, skLet, skConst, skParam, skResult}:
+        # only closure iterators may be assigned to anything.
+        result = t
+      let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags
+      for i in 1..<t.len:
+        if result != nil: break
+        result = typeAllowedAux(marker, t[i], skParam, f-{taIsOpenArray})
+      if result.isNil and t[0] != nil:
+        result = typeAllowedAux(marker, t[0], skResult, flags)
   of tyTypeDesc:
-    # XXX: This is still a horrible idea...
-    result = nil
+    if kind in {skVar, skLet, skConst} and taProcContextIsNotMacro in flags:
+      result = t
+    else:
+      # XXX: This is still a horrible idea...
+      result = nil
   of tyUntyped, tyTyped:
     if kind notin {skParam, skResult} or taNoUntyped in flags: result = t
   of tyStatic:
@@ -1363,7 +1371,9 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     elif kind in {skVar, skLet}:
       result = t[0]
   of tyArray:
-    if t[1].kind != tyEmpty:
+    if t[1].kind == tyTypeDesc:
+      result = t[1]
+    elif t[1].kind != tyEmpty:
       result = typeAllowedAux(marker, t[1], kind, flags)
     elif kind in {skVar, skLet}:
       result = t[1]
diff --git a/tests/array/t9932.nim b/tests/array/t9932.nim
new file mode 100644
index 000000000..1e09c487b
--- /dev/null
+++ b/tests/array/t9932.nim
@@ -0,0 +1,11 @@
+discard """
+cmd: "nim check $file"
+errormsg: "invalid type: 'type int' in this context: 'array[0..0, type int]' for var"
+nimout: '''
+t9932.nim(10, 5) Error: invalid type: 'type' in this context: 'array[0..0, type]' for var
+t9932.nim(11, 5) Error: invalid type: 'type int' in this context: 'array[0..0, type int]' for var
+'''
+"""
+
+var y: array[1,type]
+var x = [int]
diff --git a/tests/errmsgs/t10489_a.nim b/tests/errmsgs/t10489_a.nim
index 86659f7ac..71a6cc3c4 100644
--- a/tests/errmsgs/t10489_a.nim
+++ b/tests/errmsgs/t10489_a.nim
@@ -1,5 +1,5 @@
 discard """
-errormsg: "cannot assign macro 'm' to 'x1'. Did you mean to call the macro with '()'?"
+errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for let. Did you mean to call the macro with '()'?"
 line: 9
 """
 
diff --git a/tests/errmsgs/t10489_b.nim b/tests/errmsgs/t10489_b.nim
index 1182b4512..4b0b876e5 100644
--- a/tests/errmsgs/t10489_b.nim
+++ b/tests/errmsgs/t10489_b.nim
@@ -1,5 +1,5 @@
 discard """
-errormsg: "cannot assign macro 'm' to 'x2'. Did you mean to call the macro with '()'?"
+errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for const. Did you mean to call the macro with '()'?"
 line: 9
 """
 
diff --git a/tests/errmsgs/t12844.nim b/tests/errmsgs/t12844.nim
index 999d26255..a274b72b4 100644
--- a/tests/errmsgs/t12844.nim
+++ b/tests/errmsgs/t12844.nim
@@ -1,9 +1,9 @@
 discard """
 cmd: "nim check $file"
-errormsg: "cannot assign template 'z' to 'y'. Did you mean to call the template with '()'?"
+errormsg: "invalid type: 'template (args: varargs[string])' for var. Did you mean to call the template with '()'?"
 nimout: '''
-t12844.nim(11, 11) Error: cannot assign template 'z' to 'x'. Did you mean to call the template with '()'?
-t12844.nim(12, 9) Error: cannot assign template 'z' to 'y'. Did you mean to call the template with '()'?'''
+t12844.nim(11, 7) Error: invalid type: 'template (args: varargs[string])' for const. Did you mean to call the template with '()'?
+t12844.nim(12, 5) Error: invalid type: 'template (args: varargs[string])' for var. Did you mean to call the template with '()'?'''
 """
 
 template z*(args: varargs[string, `$`]) =
diff --git a/tests/errmsgs/t5870.nim b/tests/errmsgs/t5870.nim
index bcbc9cca9..96966bcd7 100644
--- a/tests/errmsgs/t5870.nim
+++ b/tests/errmsgs/t5870.nim
@@ -1,5 +1,5 @@
 discard """
-errormsg: "invalid type for const: seq[SomeRefObj]"
+errormsg: "invalid type: 'SomeRefObj' in this context: 'seq[SomeRefObj]' for const"
 line: 14
 """
 
diff --git a/tests/errmsgs/t8610.nim b/tests/errmsgs/t8610.nim
index dd1a3ed29..6a253f7ab 100644
--- a/tests/errmsgs/t8610.nim
+++ b/tests/errmsgs/t8610.nim
@@ -1,5 +1,5 @@
 discard """
-  errmsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
+  errmsg: "invalid type: 'type int' for const"
 """
 ## issue #8610
 const Foo = int
diff --git a/tests/errmsgs/ttypeAllowed.nim b/tests/errmsgs/ttypeAllowed.nim
index a5b335faa..9efbc6ead 100644
--- a/tests/errmsgs/ttypeAllowed.nim
+++ b/tests/errmsgs/ttypeAllowed.nim
@@ -3,7 +3,7 @@ cmd: "nim check $file"
 errmsg: ""
 nimout: '''
 ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for let
-ttypeAllowed.nim(17, 7) Error: invalid type for const: iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}
+ttypeAllowed.nim(17, 7) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for const
 ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for var
 ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for result
 '''
diff --git a/tests/metatype/typedesc_as_value.nim b/tests/metatype/typedesc_as_value.nim
index f6e526987..69eaf8a5c 100644
--- a/tests/metatype/typedesc_as_value.nim
+++ b/tests/metatype/typedesc_as_value.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
+  errormsg: "invalid type: 'type int' for var"
 """
 
 
diff --git a/tests/typerel/typedescs2.nim b/tests/typerel/typedescs2.nim
index 43cd48ca6..0b0b12986 100644
--- a/tests/typerel/typedescs2.nim
+++ b/tests/typerel/typedescs2.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
+  errormsg: "invalid type: 'type Table' for const"
   file: "typedescs2.nim"
   line: 16
 """