Fix int literals and range interaction (#11197)

* Fix int literals and range interaction

* Fix test

* remove float range fix; update changelog
This commit is contained in:
Oscar Nihlgård
2019-08-31 19:34:08 +02:00
committed by Andreas Rumpf
parent 6e01be34ef
commit 35268c500f
5 changed files with 29 additions and 17 deletions

View File

@@ -34,6 +34,8 @@ type
### Breaking changes in the compiler
- A bug allowing `int` to be implicitly converted to range types of smaller size (e.g `range[0'i8..10'i8]`) has been fixed.
## Library additions

View File

@@ -401,18 +401,20 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
else: result = isNone
proc isConvertibleToRange(f, a: PType): bool =
# be less picky for tyRange, as that it is used for array indexing:
if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
case f.kind
of tyInt, tyInt64: result = true
of tyInt8: result = a.kind in {tyInt8, tyInt}
of tyInt16: result = a.kind in {tyInt8, tyInt16, tyInt}
of tyInt32: result = a.kind in {tyInt8, tyInt16, tyInt32, tyInt}
of tyUInt, tyUInt64: result = true
of tyUInt8: result = a.kind in {tyUInt8, tyUInt}
of tyUInt16: result = a.kind in {tyUInt8, tyUInt16, tyUInt}
of tyUInt32: result = a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
of tyInt8: result = isIntLit(a) or a.kind in {tyInt8}
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
# This is wrong, but seems like there's a lot of code that relies on it :(
of tyInt: result = true
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
else: result = false
elif f.kind in {tyFloat..tyFloat128}:
# `isIntLit` is correct and should be used above as well, see PR:

View File

@@ -2282,9 +2282,11 @@ algorithm returns true:
proc isImplicitlyConvertible(a, b: PType): bool =
if isSubtype(a, b) or isCovariant(a, b):
return true
if isIntLiteral(a):
return b in {int8, int16, int32, int64, int, uint, uint8, uint16,
uint32, uint64, float32, float64}
case a.kind
of int: result = b in {int8, int16, int32, int64, uint, uint8, uint16,
uint32, uint64, float, float32, float64}
of int: result = b in {int32, int64}
of int8: result = b in {int16, int32, int64, int}
of int16: result = b in {int32, int64, int}
of int32: result = b in {int64, int}
@@ -2292,9 +2294,8 @@ algorithm returns true:
of uint8: result = b in {uint16, uint32, uint64}
of uint16: result = b in {uint32, uint64}
of uint32: result = b in {uint64}
of float: result = b in {float32, float64}
of float32: result = b in {float64, float}
of float64: result = b in {float32, float}
of float32: result = b in {float64}
of float64: result = b in {float32}
of seq:
result = b == openArray and typeEquals(a.baseType, b.baseType)
of array:

View File

@@ -142,5 +142,5 @@ block tsubrange:
var level: n16 = 1
let maxLevel: n16 = 1
level = min(level + 2, maxLevel)
level = min(level + 2, maxLevel).n16
doAssert level == 1

View File

@@ -122,10 +122,17 @@ block:
block:
var x1: range[0'f..1'f] = 1
const x2: range[0'f..1'f] = 1
var x3: range[0'u8..1'u8] = 1
const x4: range[0'u8..1'u8] = 1
var x5: range[0'f32..1'f32] = 1'f64
const x6: range[0'f32..1'f32] = 1'f64
reject:
const x: range[0'f..1'f] = 2'f
var x09: range[0'i8..1'i8] = 1.int
reject:
const x: range[0'f..1'f] = 2
var x10: range[0'i64..1'i64] = 1'u64
const x11: range[0'f..1'f] = 2'f
reject:
const x12: range[0'f..1'f] = 2