Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disallow typedesc in arrays & move existing checks to types.typeAllowedAux #13261

Merged
merged 2 commits into from
May 29, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
45 changes: 21 additions & 24 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down
32 changes: 21 additions & 11 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,8 @@ type
taConcept,
taIsOpenArray,
taNoUntyped
taIsTemplateOrMacro
taProcContextIsNotMacro

TTypeAllowedFlags* = set[TTypeAllowedFlag]

Expand Down Expand Up @@ -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 my be assigned to anything.
nc-x marked this conversation as resolved.
Show resolved Hide resolved
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can it still happen now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was existing code, so i don't know anything about this.
While reviewing, use the settings icon to Hide Whitespace Changes in order to see which code this PR changes.

of tyUntyped, tyTyped:
if kind notin {skParam, skResult} or taNoUntyped in flags: result = t
of tyStatic:
Expand Down Expand Up @@ -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]
Expand Down
11 changes: 11 additions & 0 deletions tests/array/t9932.nim
Original file line number Diff line number Diff line change
@@ -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]
2 changes: 1 addition & 1 deletion tests/errmsgs/t10489_a.nim
Original file line number Diff line number Diff line change
@@ -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
"""

Expand Down
2 changes: 1 addition & 1 deletion tests/errmsgs/t10489_b.nim
Original file line number Diff line number Diff line change
@@ -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
"""

Expand Down
6 changes: 3 additions & 3 deletions tests/errmsgs/t12844.nim
Original file line number Diff line number Diff line change
@@ -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, `$`]) =
Expand Down
2 changes: 1 addition & 1 deletion tests/errmsgs/t5870.nim
Original file line number Diff line number Diff line change
@@ -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
"""

Expand Down
2 changes: 1 addition & 1 deletion tests/errmsgs/t8610.nim
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/errmsgs/ttypeAllowed.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
'''
Expand Down
2 changes: 1 addition & 1 deletion tests/metatype/typedesc_as_value.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
discard """
errormsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
errormsg: "invalid type: 'type int' for var"
"""


Expand Down
2 changes: 1 addition & 1 deletion tests/typerel/typedescs2.nim
Original file line number Diff line number Diff line change
@@ -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
"""
Expand Down