From e58c2d261c65cf3dd4d3f92a8a4642a24a554f64 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 28 Oct 2019 16:56:38 +0100 Subject: [PATCH] [backport] fix #12528, fix #12525: incorrect generic type resolution for default values (#12538) --- compiler/sigmatch.nim | 22 +++++++++++++++------- lib/pure/complex.nim | 3 +++ tests/generics/tgeneric0.nim | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index a5e588bab6..95e292187a 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -134,11 +134,14 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) = initIdTable(c.bindings) proc put(c: var TCandidate, key, val: PType) {.inline.} = + ## Given: proc foo[T](x: T); foo(4) + ## key: 'T' + ## val: 'int' (typeof(4)) when false: let old = PType(idTableGet(c.bindings, key)) if old != nil: echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old) - if typeToString(old) == "seq[string]": + if typeToString(old) == "float32": writeStackTrace() if c.c.module.name.s == "temp3": echo "binding ", key, " -> ", val @@ -2551,13 +2554,18 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = formal.name.s) if nfDefaultRefsParam in formal.ast.flags: m.call.flags.incl nfDefaultRefsParam - var def = copyTree(formal.ast) - if def.kind == nkNilLit: - def = implicitConv(nkHiddenStdConv, formal.typ, def, m, c) + var defaultValue = copyTree(formal.ast) + if defaultValue.kind == nkNilLit: + defaultValue = implicitConv(nkHiddenStdConv, formal.typ, defaultValue, m, c) + # proc foo(x: T = 0.0) + # foo() if {tfImplicitTypeParam, tfGenericTypeParam} * formal.typ.flags != {}: - put(m, formal.typ, def.typ) - def.flags.incl nfDefaultParam - setSon(m.call, formal.position + 1, def) + let existing = PType(idTableGet(m.bindings, formal.typ)) + if existing == nil or existing.kind == tyTypeDesc: + # see bug #11600: + put(m, formal.typ, defaultValue.typ) + defaultValue.flags.incl nfDefaultParam + setSon(m.call, formal.position + 1, defaultValue) inc(f) # forget all inferred types if the overload matching failed if m.state == csNoMatch: diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 6a5e0465ed..d57adeb920 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -451,3 +451,6 @@ when isMainModule: doAssert(sizeof(a) == 16) doAssert 123.0.im + 456.0 == complex64(456, 123) + + var localA = complex(0.1'f32) + doAssert localA.im is float32 diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim index 3a35ebaba3..ca012734b9 100644 --- a/tests/generics/tgeneric0.nim +++ b/tests/generics/tgeneric0.nim @@ -2,6 +2,8 @@ discard """ output: ''' 100 0 +float32 +float32 ''' """ @@ -110,3 +112,15 @@ block tgeneric4: newSeq result.free, 0 var x = newIDGen[int]() + +block tgeneric5: + # bug #12528 + proc foo[T](a: T; b: T) = + echo T + + foo(0.0'f32, 0.0) + + proc bar[T](a: T; b: T = 0.0) = + echo T + + bar(0.0'f32)