diff options
author | metagn <metagngn@gmail.com> | 2024-05-08 18:35:26 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-08 09:35:26 -0600 |
commit | 09bd9d0b19a69a56b875eff6e6d119aaf67664fd (patch) | |
tree | 379ac17aa8b136edf0e5def100228b550a39be0e | |
parent | e6f66e4d131fb8cf3236df6cb14e219dbb5d0c77 (diff) | |
download | Nim-09bd9d0b19a69a56b875eff6e6d119aaf67664fd.tar.gz |
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.
-rw-r--r-- | compiler/semexprs.nim | 15 | ||||
-rw-r--r-- | tests/generics/tnestedissues.nim | 24 |
2 files changed, 32 insertions, 7 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 235a4e808..92757c77a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1021,10 +1021,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 = @@ -1047,10 +1051,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) diff --git a/tests/generics/tnestedissues.nim b/tests/generics/tnestedissues.nim new file mode 100644 index 000000000..e96a1927e --- /dev/null +++ b/tests/generics/tnestedissues.nim @@ -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") |