From 35268c500f2143e757a71846b246a1ecb31c72f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Sat, 31 Aug 2019 19:34:08 +0200 Subject: [PATCH] Fix int literals and range interaction (#11197) * Fix int literals and range interaction * Fix test * remove float range fix; update changelog --- changelog.md | 2 ++ compiler/sigmatch.nim | 20 +++++++++++--------- doc/manual.rst | 11 ++++++----- tests/arithm/tarithm.nim | 2 +- tests/range/trange.nim | 11 +++++++++-- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/changelog.md b/changelog.md index 38bb412d09..35395afd39 100644 --- a/changelog.md +++ b/changelog.md @@ -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 diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index cec3ecb287..d307039439 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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: diff --git a/doc/manual.rst b/doc/manual.rst index 1f8f23310b..a8326d94d5 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -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: diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim index 1150af951b..a79f897a75 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/arithm/tarithm.nim @@ -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 diff --git a/tests/range/trange.nim b/tests/range/trange.nim index 9df0e6975c..aac9677771 100644 --- a/tests/range/trange.nim +++ b/tests/range/trange.nim @@ -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