From e9c7f315399ca4bc2dc5f592a70bc0b967e65938 Mon Sep 17 00:00:00 2001 From: metagn Date: Sun, 25 Aug 2024 23:16:23 +0300 Subject: [PATCH 1/2] reject `or` types matching multiple types for int literals fixes #4858 --- compiler/sigmatch.nim | 6 +++++- tests/overload/tambiguousintlit.nim | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/overload/tambiguousintlit.nim diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ee1ad49d07a8f..b4e4324194d75 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1700,14 +1700,18 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, result = isNone let oldInheritancePenalty = c.inheritancePenalty var minInheritance = maxInheritancePenalty + var intLitConvCount = 0 for branch in f.kids: c.inheritancePenalty = -1 let x = typeRel(c, branch, aOrig, flags) + if x == isFromIntLit: + inc intLitConvCount if x >= result: if c.inheritancePenalty > -1: minInheritance = min(minInheritance, c.inheritancePenalty) result = x - if result >= isIntConv: + if result >= isIntConv and not + (result == isFromIntLit and intLitConvCount > 1): if minInheritance < maxInheritancePenalty: c.inheritancePenalty = oldInheritancePenalty + minInheritance if result > isGeneric: result = isGeneric diff --git a/tests/overload/tambiguousintlit.nim b/tests/overload/tambiguousintlit.nim new file mode 100644 index 0000000000000..a35d4ff6dc207 --- /dev/null +++ b/tests/overload/tambiguousintlit.nim @@ -0,0 +1,8 @@ +block: # issue #4858 + type + SomeType = object + field1: uint + proc namedProc(an: var SomeType, b: SomeUnsignedInt) = discard + var t = SomeType() + namedProc(t, 0) #[tt.Error + ^ type mismatch: got ]# From 2957aac4ee4b98c8af69e07047e002ceffdc07f7 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 26 Aug 2024 13:59:15 +0300 Subject: [PATCH 2/2] range type doesn't give isFromIntLit for different base types --- compiler/sigmatch.nim | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b4e4324194d75..5afe54d299dc3 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