mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
fix semFinishOperands for bracket expressions [backport:2.0] (#23571)
fixes #23568, fixes #23310
In #23091 `semFinishOperands` was changed to not be called for `mArrGet`
and `mArrPut`, presumably in preparation for #23188 (not sure why it was
needed in #23091, maybe they got mixed together), since the compiler
handles these later and needs the first argument to not be completely
"typed" since brackets can serve as explicit generic instantiations in
which case the first argument would have to be an unresolved generic
proc (not accepted by `finishOperand`).
In this PR we just make it so `mArrGet` and `mArrPut` specifically skip
calling `finishOperand` on the first argument. This way the generic
arguments in the explicit instantiation get typed, but not the
unresolved generic proc.
(cherry picked from commit 09bd9d0b19)
This commit is contained in:
@@ -1012,10 +1012,14 @@ proc finishOperand(c: PContext, a: PNode): PNode =
|
||||
localError(c.config, a.info, err)
|
||||
considerGenSyms(c, result)
|
||||
|
||||
proc semFinishOperands(c: PContext; n: PNode) =
|
||||
proc semFinishOperands(c: PContext; n: PNode; isBracketExpr = false) =
|
||||
# this needs to be called to ensure that after overloading resolution every
|
||||
# argument has been sem'checked:
|
||||
for i in 1..<n.len:
|
||||
# argument has been sem'checked
|
||||
|
||||
# skip the first argument for operands of `[]` since it may be an unresolved
|
||||
# generic proc, which is handled in semMagic
|
||||
let start = 1 + ord(isBracketExpr)
|
||||
for i in start..<n.len:
|
||||
n[i] = finishOperand(c, n[i])
|
||||
|
||||
proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -1038,10 +1042,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy
|
||||
of skMacro: result = semMacroExpr(c, result, orig, callee, flags, expectedType)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee, flags, expectedType)
|
||||
else:
|
||||
if callee.magic notin {mArrGet, mArrPut, mNBindSym}:
|
||||
# calls to `[]` can be explicit generic instantiations,
|
||||
# don't sem every operand now, leave it to semmagic
|
||||
semFinishOperands(c, result)
|
||||
semFinishOperands(c, result, isBracketExpr = callee.magic in {mArrGet, mArrPut})
|
||||
activate(c, result)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
|
||||
24
tests/generics/tnestedissues.nim
Normal file
24
tests/generics/tnestedissues.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
block: # issue #23568
|
||||
type G[T] = object
|
||||
j: T
|
||||
proc s[T](u: int) = discard
|
||||
proc s[T]() = discard
|
||||
proc c(e: int | int): G[G[G[int]]] = s[G[G[int]]]()
|
||||
discard c(0)
|
||||
|
||||
import std/options
|
||||
|
||||
block: # issue #23310
|
||||
type
|
||||
BID = string or uint64
|
||||
Future[T] = ref object of RootObj
|
||||
internalValue: T
|
||||
InternalRaisesFuture[T] = ref object of Future[T]
|
||||
proc newInternalRaisesFutureImpl[T](): InternalRaisesFuture[T] =
|
||||
let fut = InternalRaisesFuture[T]()
|
||||
template newFuture[T](): auto =
|
||||
newInternalRaisesFutureImpl[T]()
|
||||
proc problematic(blockId: BID): Future[Option[seq[int]]] =
|
||||
let resultFuture = newFuture[Option[seq[int]]]()
|
||||
return resultFuture
|
||||
let x = problematic("latest")
|
||||
Reference in New Issue
Block a user