From faa9ae08b04cf4c6571121b62cebb8d8afaf5d12 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 16 Dec 2024 14:22:10 +0300 Subject: [PATCH] proper error for const defines with unsupported types (#24540) fixes #24539 (cherry picked from commit b9c593404cf6e37c03bcba2a165d5ba6f19c0739) --- compiler/semfold.nim | 2 +- compiler/semstmts.nim | 27 +++++++++++++++++++++++++++ tests/errmsgs/twrongdefinetype.nim | 6 ++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/errmsgs/twrongdefinetype.nim diff --git a/compiler/semfold.nim b/compiler/semfold.nim index eb5db88fc9..00b40f5727 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -589,7 +589,7 @@ proc foldDefine(m, s: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode raise newException(ValueError, "invalid enum value: " & str) else: localError(g.config, s.info, "unsupported type $1 for define '$2'" % - [name, typeToString(rawTyp)]) + [typeToString(rawTyp), name]) except ValueError as e: localError(g.config, s.info, "could not process define '$1' of type $2; $3" % diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index e327d2d526..75b327afb4 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -612,11 +612,38 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) = else: localError(c.config, n.info, "nkDotNode requires 2 children") +proc checkDefineType(c: PContext; v: PSym; t: PType) = + # see semfold.foldDefine for acceptable types + let typeKinds = + case v.magic + of mStrDefine: {tyString, tyCstring} + # this used to be not typechecked, so anything that accepts int nodes for compatbility: + of mIntDefine: {tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyChar, tyEnum} + of mBoolDefine: {tyBool} + of mGenericDefine: {tyString, tyCstring, tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyEnum} + else: raiseAssert("unreachable") + var skipped = abstractVarRange + if v.magic == mGenericDefine: + # no distinct types for generic define + skipped.excl tyDistinct + if t.skipTypes(skipped).kind notin typeKinds: + let name = + case v.magic + of mStrDefine: "strdefine" + of mIntDefine: "intdefine" + of mBoolDefine: "booldefine" + of mGenericDefine: "define" + else: raiseAssert("unreachable") + localError(c.config, v.info, "unsupported type for constant '" & v.name.s & + "' with ." & name & " pragma: " & typeToString(t)) + proc setVarType(c: PContext; v: PSym, typ: PType) = if v.typ != nil and not sameTypeOrNil(v.typ, typ): localError(c.config, v.info, "inconsistent typing for reintroduced symbol '" & v.name.s & "': previous type was: " & typeToString(v.typ, preferDesc) & "; new type is: " & typeToString(typ, preferDesc)) + if v.kind == skConst and v.magic in {mGenericDefine, mIntDefine, mStrDefine, mBoolDefine}: + checkDefineType(c, v, typ) v.typ = typ proc isPossibleMacroPragma(c: PContext, it: PNode, key: PNode): bool = diff --git a/tests/errmsgs/twrongdefinetype.nim b/tests/errmsgs/twrongdefinetype.nim new file mode 100644 index 0000000000..302deb4c88 --- /dev/null +++ b/tests/errmsgs/twrongdefinetype.nim @@ -0,0 +1,6 @@ +# issue #24539 + +type Foo = object +const foo {.define.} = Foo() #[tt.Error + ^ unsupported type for constant 'foo' with .define pragma: Foo]# +echo repr(foo)