diff --git a/compiler/semcall.nim b/compiler/semcall.nim index fb2f9e97a78e..d0ccb17b1fa1 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -973,8 +973,14 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool) # common case; check the only candidate has the right # number of generic type parameters: result = explicitGenericSym(c, n, s, errors, doError) - if doError and result == nil: - notFoundError(c, n, errors) + if result == nil: + if c.inGenericContext > 0: + # same as in semOverloadedCall, make expression untyped, + # may have failed match due to unresolved types + result = semGenericStmt(c, n) + result.typ() = makeTypeFromExpr(c, result.copyTree) + elif doError: + notFoundError(c, n, errors) elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}: # choose the generic proc with the proper number of type parameters. result = newNodeI(a.kind, getCallLineInfo(n)) @@ -984,6 +990,14 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool) skFunc, skIterator}: let x = explicitGenericSym(c, n, candidate, errors, doError) if x != nil: result.add(x) + elif c.inGenericContext > 0: + # same as in semOverloadedCall, make expression untyped, + # may have failed match due to unresolved types + # any failing match stops building the symchoice for correctness, + # can also make it untyped from the start + result = semGenericStmt(c, n) + result.typ() = makeTypeFromExpr(c, result.copyTree) + return # get rid of nkClosedSymChoice if not ambiguous: if result.len == 0: result = nil diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 6cc4afd6e008..e4c585e0130d 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1816,7 +1816,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = f # type parameters: partial generic specialization n[0] = semSymGenericInstantiation(c, n[0], s) result = maybeInstantiateGeneric(c, n, s, doError = afterOverloading) - if result != nil: + if result != nil and + # leave untyped generic expression alone: + (result.typ == nil or result.typ.kind != tyFromExpr): # check newly created sym/symchoice result = semExpr(c, result, flags) of skMacro, skTemplate: diff --git a/tests/proc/texplicitgenerics.nim b/tests/proc/texplicitgenerics.nim index 833d77b3b790..131a31458d5c 100644 --- a/tests/proc/texplicitgenerics.nim +++ b/tests/proc/texplicitgenerics.nim @@ -53,3 +53,11 @@ block: # issue #21346 b1(false) # Error: cannot instantiate K; got: but expected: b2(false) # Builds, on its own b3(false) + +block: # explicit generic with unresolved generic param, https://forum.nim-lang.org/t/12579 + var s: seq[string] = @[] + proc MyMedian[T](A: var openArray[T],myCmp : proc(x,y:T):int {.nimcall.} = cmp[T]) : T = + if myCmp(A[0], A[1]) == 0: s.add("1") + var x = [1, 1] + discard MyMedian(x) # emits "1\n" + doAssert s == @["1"]