summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-08-27 10:58:05 +0300
committerGitHub <noreply@github.com>2024-08-27 09:58:05 +0200
commitf09c549d42f477866bfa72a902d6b43f85959e8f (patch)
treec37b40beb8fc71449b600949a2d99a3b9b406ca2
parent7e88091de3f067675f20f36052a1b9c7c603e47a (diff)
downloadNim-f09c549d42f477866bfa72a902d6b43f85959e8f.tar.gz
make int literals with range type match their base type better than other int types (#24017)
This is a very niche case encountered in #24012, where an int literal
got a `range` type as a result of a generic instantiation (in
`tgenericcomputedrange`), I can't think of another test case. The base
type of the range being `int` made it match `int` with `isSubrange` as
in the first `if` branch, but other int types like `int32` matched with
`isFromIntLit` which is a better match.

Instead, int literals with range type now:

1. match their base type with `isFromIntLit`,
2. don't match other int types with `isFromIntLit`, instead giving
`isConvertible` as in the last `if` branch in `handleRange`.
-rw-r--r--compiler/sigmatch.nim13
1 files changed, 10 insertions, 3 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index ee1ad49d0..1650e8598 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -409,9 +409,16 @@ proc handleRange(c: PContext, f, a: PType, min, max: TTypeKind): TTypeRelation =
     let k = ab.kind
     let nf = c.config.normalizeKind(f.kind)
     let na = c.config.normalizeKind(k)
-    if k == f.kind: result = isSubrange
-    elif k == tyInt and f.kind in {tyRange, tyInt..tyInt64,
-                                   tyUInt..tyUInt64} and
+    if k == f.kind:
+      # `a` is a range type matching its base type
+      # see very bottom for range types matching different types
+      if isIntLit(ab):
+        # range type can only give isFromIntLit for base type
+        result = isFromIntLit
+      else:
+        result = isSubrange
+    elif a.kind == tyInt and f.kind in {tyRange, tyInt..tyInt64,
+                                        tyUInt..tyUInt64} and
         isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
                          getInt(ab.n) <= lastOrd(nil, f):
       # passing 'nil' to firstOrd/lastOrd here as type checking rules should