range/case fixes (#11264)

This commit is contained in:
Jasper Jenkins 2019-05-16 07:36:40 -07:00 • committed by Andreas Rumpf
commit 90ed904c4d
4 changed files with 28 additions and 6 deletions

View file

@ -878,9 +878,13 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
var covered: BiggestInt = 0 var covered: BiggestInt = 0
var typ = commonTypeBegin var typ = commonTypeBegin
var hasElse = false var hasElse = false
let caseTyp = skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}) let caseTyp = skipTypes(n.sons[0].typ, abstractVar-{tyTypeDesc})
const shouldChckCovered = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool}
case caseTyp.kind case caseTyp.kind
of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool: of shouldChckCovered:
chckCovered = true
of tyRange:
if skipTypes(caseTyp.sons[0], abstractInst).kind in shouldChckCovered:
chckCovered = true chckCovered = true
of tyFloat..tyFloat128, tyString, tyError: of tyFloat..tyFloat128, tyString, tyError:
discard discard
@ -889,7 +893,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = handleCaseStmtMacro(c, n) result = handleCaseStmtMacro(c, n)
if result != nil: return result if result != nil: return result
localError(c.config, n.info, errSelectorMustBeOfCertainTypes) localError(c.config, n.sons[0].info, errSelectorMustBeOfCertainTypes)
return return
for i in 1 ..< sonsLen(n): for i in 1 ..< sonsLen(n):
var x = n.sons[i] var x = n.sons[i]

View file

@ -223,7 +223,8 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
if not hasUnknownTypes: if not hasUnknownTypes:
if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})): if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})):
localError(c.config, n.info, "type mismatch") localError(c.config, n.info, "type mismatch")
elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128: elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128 or
rangeT[0].kind == tyBool:
localError(c.config, n.info, "ordinal or float type expected") localError(c.config, n.info, "ordinal or float type expected")
elif enumHasHoles(rangeT[0]): elif enumHasHoles(rangeT[0]):
localError(c.config, n.info, "enum '$1' has holes" % typeToString(rangeT[0])) localError(c.config, n.info, "enum '$1' has holes" % typeToString(rangeT[0]))
@ -605,11 +606,15 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
var covered: BiggestInt = 0 var covered: BiggestInt = 0
var chckCovered = false var chckCovered = false
var typ = skipTypes(a.sons[0].typ, abstractVar-{tyTypeDesc}) var typ = skipTypes(a.sons[0].typ, abstractVar-{tyTypeDesc})
const shouldChckCovered = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool}
case typ.kind case typ.kind
of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool, tyRange: of shouldChckCovered:
chckCovered = true chckCovered = true
of tyFloat..tyFloat128, tyString, tyError: of tyFloat..tyFloat128, tyString, tyError:
discard discard
of tyRange:
if skipTypes(typ.sons[0], abstractInst).kind in shouldChckCovered:
chckCovered = true
of tyForward: of tyForward:
errorUndeclaredIdentifier(c, n.sons[0].info, typ.sym.name.s) errorUndeclaredIdentifier(c, n.sons[0].info, typ.sym.name.s)
elif not isOrdinalType(typ): elif not isOrdinalType(typ):

View file

@ -0,0 +1,13 @@
discard """
output: '''(kind: 2.0, twoStr: "TWO STR")
(kind: 1.0)
'''
"""
type
FloatRange = range[1.0..3.0]
VariantObj = object
case kind: FloatRange
of 2.0: twoStr: string
echo VariantObj(kind: 2.0, twoStr: "TWO STR")
echo VariantObj(kind: 1.0)