summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md3
-rw-r--r--compiler/semobjconstr.nim9
-rw-r--r--tests/objvariant/trt_discrim.nim12
3 files changed, 20 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md
index 6c3bc018b..e16211a3d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -236,7 +236,8 @@ proc enumToString*(enums: openArray[enum]): string =
   pragmas for further analysis by macros
 - Custom pragmas are now supported for `var` and `let` symbols.
 - Tuple unpacking is now supported for constants and for loop variables.
-
+- Case object branches can be initialized with a runtime discriminator if
+  possible discriminator values are constrained within a case statement.
 
 ### Language changes
 
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index 4b4c5de02..c9216cc51 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -129,8 +129,10 @@ proc formatUnsafeBranchVals(t: PType, diffVals: IntSet): string =
 
 proc findUsefulCaseContext(c: PContext, discrimator: PNode): (PNode, int) =
   for i in countdown(c.p.caseContext.high, 0):
-    let (caseNode, index) = c.p.caseContext[i]
-    if caseNode[0].kind == nkSym and caseNode[0].sym == discrimator.sym:
+    let
+      (caseNode, index) = c.p.caseContext[i]
+      skipped = caseNode[0].skipHidden
+    if skipped.kind == nkSym and skipped.sym == discrimator.sym:
       return (caseNode, index)
 
 proc pickCaseBranch(caseExpr, matched: PNode): PNode =
@@ -252,7 +254,8 @@ proc semConstructFields(c: PContext, recNode: PNode,
         let (ctorCase, ctorIdx) = findUsefulCaseContext(c, discriminatorVal)
         if ctorCase == nil:
           badDiscriminatorError()
-        elif discriminatorVal.sym.kind != skLet:
+        elif discriminatorVal.sym.kind notin {skLet, skParam} or
+            discriminatorVal.sym.typ.kind == tyVar:
           localError(c.config, discriminatorVal.info,
             "runtime discriminator must be immutable if branch fields are " &
             "initialized, a 'let' binding is required.")
diff --git a/tests/objvariant/trt_discrim.nim b/tests/objvariant/trt_discrim.nim
index 612647fbe..303c0fa55 100644
--- a/tests/objvariant/trt_discrim.nim
+++ b/tests/objvariant/trt_discrim.nim
@@ -136,3 +136,15 @@ reject: # not immutable.
   of k1, k2, k3: discard KindObj(varkind: kind, i32: 1)
   of k4: discard KindObj(varkind: kind, f32: 2.0)
   else: discard KindObj(varkind: kind, str: "3")
+
+accept:
+  proc kindProc(kind: Kind): KindObj =
+    case kind:
+    of k1: result = KindObj(kind: kind, i32: 1)
+    else: discard
+
+reject:
+  proc varKindProc(kind: var Kind): KindObj =
+    case kind:
+    of k1: result = KindObj(kind: kind, i32: 1)
+    else: discard