summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim12
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--tests/exception/texcpt1.nim16
3 files changed, 24 insertions, 9 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 5a84b2b02..dd84452f9 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1667,7 +1667,7 @@ proc skipStmtList*(n: PNode): PNode =
 proc toRef*(typ: PType): PType =
   ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
   ## returned. Otherwise ``typ`` is simply returned as-is.
-  result = typ
+  let typ = typ.skipTypes({tyAlias, tyGenericInst})
   if typ.kind == tyObject:
     result = newType(tyRef, typ.owner)
     rawAddSon(result, typ)
@@ -1676,7 +1676,7 @@ proc toObject*(typ: PType): PType =
   ## If ``typ`` is a tyRef then its immediate son is returned (which in many
   ## cases should be a ``tyObject``).
   ## Otherwise ``typ`` is simply returned as-is.
-  result = typ
+  result = typ.skipTypes({tyAlias, tyGenericInst})
   if result.kind == tyRef:
     result = result.lastSon
 
@@ -1684,14 +1684,12 @@ proc isException*(t: PType): bool =
   # check if `y` is object type and it inherits from Exception
   assert(t != nil)
 
-  if t.kind != tyObject:
-    return false
-
   var base = t
-  while base != nil:
+  while base != nil and base.kind in {tyObject, tyRef, tyGenericInst, tyAlias}:
     if base.sym != nil and base.sym.magic == mException:
       return true
-    base = base.lastSon
+    if base.len == 0: break
+    else: base = base.lastSon
   return false
 
 proc isImportedException*(t: PType; conf: ConfigRef): bool =
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 7213601de..12337262a 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -755,9 +755,10 @@ proc semRaise(c: PContext, n: PNode): PNode =
   checkSonsLen(n, 1, c.config)
   if n[0].kind != nkEmpty:
     n[0] = semExprWithType(c, n[0])
-    let typ = n[0].typ
+    var typ = n[0].typ
     if not isImportedException(typ, c.config):
-      if typ.kind != tyRef or typ.lastSon.kind != tyObject:
+      typ = typ.skipTypes({tyAlias, tyGenericInst})
+      if typ.kind != tyRef:
         localError(c.config, n.info, errExprCannotBeRaised)
       if not isException(typ.lastSon):
         localError(c.config, n.info, "raised object of type $1 does not inherit from Exception",
diff --git a/tests/exception/texcpt1.nim b/tests/exception/texcpt1.nim
index 50a95eeec..ebbb9d44f 100644
--- a/tests/exception/texcpt1.nim
+++ b/tests/exception/texcpt1.nim
@@ -1,9 +1,12 @@
 discard """
   outputsub: "-6"
+  targets: "c cpp"
 """
 type
   ESomething = object of Exception
   ESomeOtherErr = object of Exception
+  ESomethingGen[T] = object of Exception
+  ESomethingGenRef[T] = ref object of Exception
 
 proc genErrors(s: string) =
   if s == "error!":
@@ -27,4 +30,17 @@ proc blah(): int =
 
 echo blah()
 
+# Issue #7845, raise generic exception
+var x: ref ESomethingGen[int]
+new(x)
+try:
+  raise x
+except ESomethingGen[int] as e:
+  discard
 
+try:
+  raise new(ESomethingGenRef[int])
+except ESomethingGenRef[int] as e:
+  discard
+except:
+  discard
\ No newline at end of file