summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-05-08 18:35:26 +0300
committerGitHub <noreply@github.com>2024-05-08 09:35:26 -0600
commit09bd9d0b19a69a56b875eff6e6d119aaf67664fd (patch)
tree379ac17aa8b136edf0e5def100228b550a39be0e
parente6f66e4d131fb8cf3236df6cb14e219dbb5d0c77 (diff)
downloadNim-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.nim15
-rw-r--r--tests/generics/tnestedissues.nim24
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")