From b5ee289ce63f5b0a173fca9767468e2b3e68f86f Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 16 Dec 2024 12:52:53 +0300 Subject: [PATCH] proper error for const defines with unsupported types [backport:2.0] fixes #24539 --- compiler/semfold.nim | 2 +- compiler/semstmts.nim | 23 +++++++++++++++++++++++ tests/errmsgs/twrongdefinetype.nim | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/errmsgs/twrongdefinetype.nim diff --git a/compiler/semfold.nim b/compiler/semfold.nim index eb5db88fc9fd6..00b40f57276ea 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 f305b3a8295ae..9f6e87f9d47d4 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -612,11 +612,34 @@ 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") + if t.skipTypes(abstractVarRange-{tyDistinct}).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 0000000000000..17e528bd4a4a6 --- /dev/null +++ b/tests/errmsgs/twrongdefinetype.nim @@ -0,0 +1,4 @@ +type Foo = object +const foo {.define.} = Foo() #[tt.Error + ^ unsupported type for constant 'foo' with .define pragma: Foo]# +echo repr(foo)