Let inferGenericTypes continue if a param is already bound (#22384)

* Play with typeRel

* Temp solution: Fixup call's param types

* Test result type with two generic params

* Asserts

* Tiny cleanup

* Skip sink

* Ignore proc

* Use changeType

* Remove conversion

* Remove last bits of conversion

* Flag

---------

Co-authored-by: SirOlaf <>
This commit is contained in:
SirOlaf
2023-08-06 14:23:00 +02:00
committed by GitHub
parent d2b197bdcd
commit 67122a9cb6
2 changed files with 30 additions and 4 deletions

View File

@@ -564,7 +564,7 @@ proc getCallLineInfo(n: PNode): TLineInfo =
proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
## Helper proc to inherit bound generic parameters from expectedType into x.
## Does nothing if 'inferGenericTypes' isn't in c.features
## Does nothing if 'inferGenericTypes' isn't in c.features.
if inferGenericTypes notin c.features: return
if expectedType == nil or x.callee[0] == nil: return # required for inference
@@ -578,7 +578,7 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
## skips types and puts the skipped version on stack
# It might make sense to skip here one by one. It's not part of the main
# type reduction because the right side normally won't be skipped
const toSkip = { tyVar, tyLent, tyStatic, tyCompositeTypeClass }
const toSkip = { tyVar, tyLent, tyStatic, tyCompositeTypeClass, tySink }
let
x = a.skipTypes(toSkip)
y = if a.kind notin toSkip: b
@@ -603,7 +603,9 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
if t[i] == nil or u[i] == nil: return
stackPut(t[i], u[i])
of tyGenericParam:
if x.bindings.idTableGet(t) != nil: return
let prebound = x.bindings.idTableGet(t).PType
if prebound != nil:
continue # Skip param, already bound
# fully reduced generic param, bind it
if t notin flatUnbound:
@@ -611,6 +613,7 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
flatBound.add(u)
else:
discard
# update bindings
for i in 0 ..< flatUnbound.len():
x.bindings.idTablePut(flatUnbound[i], flatBound[i])

View File

@@ -136,4 +136,27 @@ block:
x: Table[int, float]
let a = Foo(x: initTable())
doAssert a.x is Table[int, float]
doAssert a.x is Table[int, float]
# partial binding
block:
type
ResultKind = enum
Ok, Error
Result[T, E] = object
case kind: ResultKind
of Ok:
okVal: T
of Error:
errVal: E
proc err[T, E](myParam: E): Result[T, E] =
Result[T, E](kind : Error, errVal : myParam)
proc doStuff(): Result[int, string] =
err("Error")
let res = doStuff()
doAssert res.kind == Error
doAssert res.errVal == "Error"