From b0a98cc01e14a33d75866c10c290f63031dc2112 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 17 Apr 2023 21:55:22 +0300 Subject: warn on set types bigger than max size, default to 0..255 for int literals (#21659) * test implicitly huge set types refs https://github.com/nim-lang/RFCs/issues/298 * oh my god * boot at least * don't error, fix remaining issues, no 2 len arrays * fix runnable example * test assuming 0..255 for int literal * test refactor, add changelog, test --- compiler/ccgstmts.nim | 2 +- compiler/commands.nim | 2 +- compiler/lineinfos.nim | 2 ++ compiler/lowerings.nim | 3 ++- compiler/nversion.nim | 2 ++ compiler/semexprs.nim | 33 +++++++++++++++++++-------------- compiler/semtypes.nim | 2 +- compiler/suggest.nim | 2 +- compiler/vmgen.nim | 3 ++- 9 files changed, 31 insertions(+), 20 deletions(-) (limited to 'compiler') diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index db86af3b0..63fb17527 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -653,7 +653,7 @@ proc genParForStmt(p: BProc, t: PNode) = #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack) #discard mangleName(forLoopVar) let call = t[1] - assert(call.len in {4, 5}) + assert(call.len == 4 or call.len == 5) initLocExpr(p, call[1], rangeA) initLocExpr(p, call[2], rangeB) diff --git a/compiler/commands.nim b/compiler/commands.nim index 4ed21d282..c31476b45 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -876,7 +876,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "verbosity": expectArg(conf, switch, arg, pass, info) let verbosity = parseInt(arg) - if verbosity notin {0..3}: + if verbosity notin 0..3: localError(conf, info, "invalid verbosity level: '$1'" % arg) conf.verbosity = verbosity var verb = NotesVerbosity[conf.verbosity] diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 532478e4b..44e9cb716 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -84,6 +84,7 @@ type warnPtrToCstringConv = "PtrToCstringConv", warnEffect = "Effect", warnCastSizes = "CastSizes" + warnAboveMaxSizeSet = "AboveMaxSizeSet", warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition", warnUnnamedBreak = "UnnamedBreak", warnStmtListLambda = "StmtListLambda", @@ -186,6 +187,7 @@ const warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; this will become a compile time error in the future", warnEffect: "$1", warnCastSizes: "$1", + warnAboveMaxSizeSet: "$1", warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma", warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead", warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead", diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index fc66fc9fa..54a59c80a 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -347,7 +347,8 @@ proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = proc callCodegenProc*(g: ModuleGraph; name: string; info: TLineInfo = unknownLineInfo; - arg1, arg2, arg3, optionalArgs: PNode = nil): PNode = + arg1: PNode = nil, arg2: PNode = nil, + arg3: PNode = nil, optionalArgs: PNode = nil): PNode = result = newNodeI(nkCall, info) let sym = magicsys.getCompilerProc(g, name) if sym == nil: diff --git a/compiler/nversion.nim b/compiler/nversion.nim index 2da39b138..811008989 100644 --- a/compiler/nversion.nim +++ b/compiler/nversion.nim @@ -12,6 +12,8 @@ const MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? + DefaultSetElements* = 1 shl 8 + ## assumed set element count when using int literals VersionAsString* = system.NimVersion RodFileVersion* = "1223" # modify this if the rod-format changes! diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 848874810..e5d5498a8 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2563,34 +2563,39 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode = # only semantic checking for all elements, later type checking: var typ: PType = nil for i in 0.. MaxSetElements: - typ = makeRangeType(c, 0, MaxSetElements-1, n.info) + if doSetType: + if not isOrdinalType(typ, allowEnumWithHoles=true): + localError(c.config, n.info, errOrdinalTypeExpected % typeToString(typ, preferDesc)) + typ = makeRangeType(c, 0, MaxSetElements-1, n.info) + elif isIntLit(typ): + # set of int literal, use a default range smaller than the max range + typ = makeRangeType(c, 0, DefaultSetElements-1, n.info) + elif lengthOrd(c.config, typ) > MaxSetElements: + message(c.config, n.info, warnAboveMaxSizeSet, "type '" & + typeToString(typ, preferDesc) & "' is too big to be a `set` element, " & + "assuming a range of 0.." & $(MaxSetElements - 1) & + ", explicitly write this range to get rid of warning") + typ = makeRangeType(c, 0, MaxSetElements-1, n.info) + if expectedElementType == nil: + expectedElementType = typ addSonSkipIntLit(result.typ, typ, c.idgen) for i in 0..