proper error message for out-of-range enum sets (#24027)

fixes #17848
This commit is contained in:
metagn
2024-08-29 17:13:06 +03:00
committed by GitHub
parent d7e77b330f
commit b7b1313d21
3 changed files with 74 additions and 3 deletions

View File

@@ -648,7 +648,14 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
case n.kind
of nkCurly, nkBracket:
of nkCurly:
for i in 0..<n.len:
if n[i].kind == nkRange:
changeType(c, n[i][0], elemType(newType), check)
changeType(c, n[i][1], elemType(newType), check)
else:
changeType(c, n[i], elemType(newType), check)
of nkBracket:
for i in 0..<n.len:
changeType(c, n[i], elemType(newType), check)
of nkPar, nkTupleConstr:
@@ -685,10 +692,16 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
let value = n.intVal
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
localError(c.config, n.info, "cannot convert " & $value &
" to " & typeToString(newType))
" to " & typeNameAndDesc(newType))
of nkFloatLit..nkFloat64Lit:
if check and not floatRangeCheck(n.floatVal, newType):
localError(c.config, n.info, errFloatToString % [$n.floatVal, typeToString(newType)])
localError(c.config, n.info, errFloatToString % [$n.floatVal, typeNameAndDesc(newType)])
of nkSym:
if check and n.sym.kind == skEnumField and not sameTypeOrNil(n.sym.typ, newType):
let value = n.sym.position
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
localError(c.config, n.info, "cannot convert '" & n.sym.name.s &
"' to '" & typeNameAndDesc(newType) & "'")
else: discard
n.typ = newType

View File

@@ -1739,6 +1739,13 @@ proc processPragmaAndCallConvMismatch(msg: var string, formal, actual: PType, co
of efTagsIllegal:
msg.add "\n.notTag catched an illegal effect"
proc typeNameAndDesc*(t: PType): string =
result = typeToString(t)
let desc = typeToString(t, preferDesc)
if result != desc:
result.add(" = ")
result.add(desc)
proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType, n: PNode) =
if formal.kind != tyError and actual.kind != tyError:
let actualStr = typeToString(actual)

View File

@@ -0,0 +1,51 @@
discard """
cmd: "nim check --hints:off $file"
"""
# issue #17848
block:
# generate with:
# var a = ""
# for i in 0..<80: a.add "k" & $i & ", "
# echo a
type
TMsgKind = enum
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k60, k61, k62, k63, k64, k65, k66, k67, k68, k69, k70, k71, k72, k73, k74, k75, k76, k77, k78, k79
type
TNoteKind = range[k10..k79]
Conf = ref object
notes: set[TNoteKind]
proc bad(conf: Conf, noteSet: set[TMsgKind]) =
conf.notes = noteSet #[tt.Error
^ type mismatch: got <set[TMsgKind]> but expected 'set[TNoteKind]']#
var conf = Conf()
bad(conf, {k10..k60})
block:
type
TMsgKind = enum k0, k1, k2, k3
TNoteKind = range[k1..k2]
TNoteKinds = set[TNoteKind]
type Conf = ref object
notes: TNoteKinds
proc fn(conf: Conf, b: set[TMsgKind]) =
conf.notes = b #[tt.Error
^ type mismatch: got <set[TMsgKind]> but expected 'TNoteKinds = set[TNoteKind]']#
var conf = Conf()
conf.fn({k0..k3}) # BUG: this should give error
echo conf.notes # {k1, k2}
block:
#[
compiler/bitsets.nim(43, 9) `elem >= 0` [AssertionDefect]
]#
type
TMsgKind = enum k0, k1, k2, k3
TNoteKind = range[k1..k2]
var notes: set[TNoteKind]
notes = {k0} #[tt.Error
^ cannot convert 'k0' to 'TNoteKind = range 1..2(TMsgKind)]#
notes = {k0..k3} #[tt.Error
^ cannot convert 'k0' to 'TNoteKind = range 1..2(TMsgKind)'; tt.Error
^ cannot convert 'k3' to 'TNoteKind = range 1..2(TMsgKind)']#