From 275b36577606f97fe59927fccf971c8ea4b593e2 Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Thu, 2 Nov 2023 19:50:18 +0530
Subject: [PATCH 1/7] checker: warn on unused imported functions used via
 `import math { sin, cos }`

---
 vlib/v/checker/checker.v                               |  3 +++
 .../checker/tests/import_sym_fn_unused_warning_err.out | 10 ++++++++++
 .../checker/tests/import_sym_fn_unused_warning_err.vv  |  3 +++
 3 files changed, 16 insertions(+)
 create mode 100644 vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
 create mode 100644 vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv

diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v
index d64a823d57abb8..5a7e00a2455232 100644
--- a/vlib/v/checker/checker.v
+++ b/vlib/v/checker/checker.v
@@ -2791,6 +2791,9 @@ fn (mut c Checker) import_stmt(node ast.Import) {
 			if !func.is_pub {
 				c.error('module `${node.mod}` function `${sym.name}()` is private', sym.pos)
 			}
+			if func.usages != 1 {
+				c.warn('module `${node.mod}` function `${sym.name}()` is unused', sym.pos)
+			}
 			continue
 		}
 		if _ := c.file.global_scope.find_const(name) {
diff --git a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
new file mode 100644
index 00000000000000..d0bb2c363db71a
--- /dev/null
+++ b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
@@ -0,0 +1,10 @@
+vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv:1:15: warning: module `math` function `sin()` is unused
+    1 | import math { sin, cos }
+      |               ~~~
+    2 | 
+    3 | fn main() {}
+vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv:1:20: warning: module `math` function `cos()` is unused
+    1 | import math { sin, cos }
+      |                    ~~~
+    2 | 
+    3 | fn main() {}
diff --git a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv
new file mode 100644
index 00000000000000..e5a7d32933c895
--- /dev/null
+++ b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv
@@ -0,0 +1,3 @@
+import math { sin, cos }
+
+fn main() {}

From e2882efe9ef54286ea4574a54ae44e97d1678902 Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Thu, 2 Nov 2023 19:50:42 +0530
Subject: [PATCH 2/7] Revert "checker: warn on unused imported functions used
 via `import math { sin, cos }`"

This reverts commit ddf0468f1c4f9af54ada162712c212214e58ca56.
---
 vlib/v/checker/checker.v                               |  3 ---
 .../checker/tests/import_sym_fn_unused_warning_err.out | 10 ----------
 .../checker/tests/import_sym_fn_unused_warning_err.vv  |  3 ---
 3 files changed, 16 deletions(-)
 delete mode 100644 vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
 delete mode 100644 vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv

diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v
index 5a7e00a2455232..d64a823d57abb8 100644
--- a/vlib/v/checker/checker.v
+++ b/vlib/v/checker/checker.v
@@ -2791,9 +2791,6 @@ fn (mut c Checker) import_stmt(node ast.Import) {
 			if !func.is_pub {
 				c.error('module `${node.mod}` function `${sym.name}()` is private', sym.pos)
 			}
-			if func.usages != 1 {
-				c.warn('module `${node.mod}` function `${sym.name}()` is unused', sym.pos)
-			}
 			continue
 		}
 		if _ := c.file.global_scope.find_const(name) {
diff --git a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
deleted file mode 100644
index d0bb2c363db71a..00000000000000
--- a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.out
+++ /dev/null
@@ -1,10 +0,0 @@
-vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv:1:15: warning: module `math` function `sin()` is unused
-    1 | import math { sin, cos }
-      |               ~~~
-    2 | 
-    3 | fn main() {}
-vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv:1:20: warning: module `math` function `cos()` is unused
-    1 | import math { sin, cos }
-      |                    ~~~
-    2 | 
-    3 | fn main() {}
diff --git a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv b/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv
deleted file mode 100644
index e5a7d32933c895..00000000000000
--- a/vlib/v/checker/tests/import_sym_fn_unused_warning_err.vv
+++ /dev/null
@@ -1,3 +0,0 @@
-import math { sin, cos }
-
-fn main() {}

From 897257a52ebf8a48ca512d8d2aaba5100098027c Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Sun, 19 Jan 2025 00:25:38 +0530
Subject: [PATCH 3/7] checker: disallow `expr is Type` if expr is Optional

---
 vlib/v/checker/infix.v                        |  4 ++++
 vlib/v/checker/tests/opt_is_op_check_err.out  |  7 +++++++
 vlib/v/checker/tests/opt_is_op_check_err.vv   | 21 +++++++++++++++++++
 .../tests/orm_op_with_option_and_none.out     | 14 +++++++++++++
 4 files changed, 46 insertions(+)
 create mode 100644 vlib/v/checker/tests/opt_is_op_check_err.out
 create mode 100644 vlib/v/checker/tests/opt_is_op_check_err.vv

diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v
index 4466525eac1897..d2b0b94457f20b 100644
--- a/vlib/v/checker/infix.v
+++ b/vlib/v/checker/infix.v
@@ -781,6 +781,10 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
 			if typ != ast.no_type {
 				typ_sym := c.table.sym(typ)
 				op := node.op.str()
+				if left_type.has_flag(.option) {
+					c.error('${node.left} is an Optional, it needs to be unwrapped first',
+						node.left.pos())
+				}
 				if typ_sym.kind == .placeholder {
 					c.error('${op}: type `${typ_sym.name}` does not exist', right_expr.pos())
 				}
diff --git a/vlib/v/checker/tests/opt_is_op_check_err.out b/vlib/v/checker/tests/opt_is_op_check_err.out
new file mode 100644
index 00000000000000..f10ce93db2bbfa
--- /dev/null
+++ b/vlib/v/checker/tests/opt_is_op_check_err.out
@@ -0,0 +1,7 @@
+vlib/v/checker/tests/opt_is_op_check_err.vv:13:7: error: t.a is an Optional, it needs to be unwrapped first
+   11 |         a: s
+   12 |     }
+   13 |     if t.a is string {
+      |          ^
+   14 |         r(t.a)
+   15 |     }
diff --git a/vlib/v/checker/tests/opt_is_op_check_err.vv b/vlib/v/checker/tests/opt_is_op_check_err.vv
new file mode 100644
index 00000000000000..917bdacba26ff4
--- /dev/null
+++ b/vlib/v/checker/tests/opt_is_op_check_err.vv
@@ -0,0 +1,21 @@
+type Foo = int | string
+
+struct Struct {
+	a ?Foo
+}
+
+fn r(a string) {}
+
+fn t(s ?Foo) {
+	mut t := Struct{
+		a: s
+	}
+	if t.a is string {
+		r(t.a)
+	}
+}
+
+fn main() {
+	s := ?Foo('hello')
+	t(s)
+}
diff --git a/vlib/v/checker/tests/orm_op_with_option_and_none.out b/vlib/v/checker/tests/orm_op_with_option_and_none.out
index 01ee85cbe75fb2..29aeb2dcfb2129 100644
--- a/vlib/v/checker/tests/orm_op_with_option_and_none.out
+++ b/vlib/v/checker/tests/orm_op_with_option_and_none.out
@@ -47,3 +47,17 @@ vlib/v/checker/tests/orm_op_with_option_and_none.vv:45:30: warning: comparison w
       |                                    ~~
    46 |     }!
    47 |
+vlib/v/checker/tests/orm_op_with_option_and_none.vv:49:25: error: name is an Optional, it needs to be unwrapped first
+   47 | 
+   48 |     _ := sql db {
+   49 |         select from Foo where name is none
+      |                               ~~~~
+   50 |     }!
+   51 |
+vlib/v/checker/tests/orm_op_with_option_and_none.vv:53:25: error: name is an Optional, it needs to be unwrapped first
+   51 | 
+   52 |     _ := sql db {
+   53 |         select from Foo where name !is none
+      |                               ~~~~
+   54 |     }!
+   55 | }

From 4a2c3ce7dc28c122e28c1e22bf8afd771c689b0a Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Sun, 19 Jan 2025 00:36:35 +0530
Subject: [PATCH 4/7] add more check

---
 vlib/v/checker/infix.v                             |  2 +-
 .../checker/tests/orm_op_with_option_and_none.out  | 14 --------------
 2 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v
index d2b0b94457f20b..25f62660768fc6 100644
--- a/vlib/v/checker/infix.v
+++ b/vlib/v/checker/infix.v
@@ -781,7 +781,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
 			if typ != ast.no_type {
 				typ_sym := c.table.sym(typ)
 				op := node.op.str()
-				if left_type.has_flag(.option) {
+				if left_type.has_flag(.option) && !c.inside_sql {
 					c.error('${node.left} is an Optional, it needs to be unwrapped first',
 						node.left.pos())
 				}
diff --git a/vlib/v/checker/tests/orm_op_with_option_and_none.out b/vlib/v/checker/tests/orm_op_with_option_and_none.out
index 29aeb2dcfb2129..01ee85cbe75fb2 100644
--- a/vlib/v/checker/tests/orm_op_with_option_and_none.out
+++ b/vlib/v/checker/tests/orm_op_with_option_and_none.out
@@ -47,17 +47,3 @@ vlib/v/checker/tests/orm_op_with_option_and_none.vv:45:30: warning: comparison w
       |                                    ~~
    46 |     }!
    47 |
-vlib/v/checker/tests/orm_op_with_option_and_none.vv:49:25: error: name is an Optional, it needs to be unwrapped first
-   47 | 
-   48 |     _ := sql db {
-   49 |         select from Foo where name is none
-      |                               ~~~~
-   50 |     }!
-   51 |
-vlib/v/checker/tests/orm_op_with_option_and_none.vv:53:25: error: name is an Optional, it needs to be unwrapped first
-   51 | 
-   52 |     _ := sql db {
-   53 |         select from Foo where name !is none
-      |                               ~~~~
-   54 |     }!
-   55 | }

From 7f68daf51e44bdfe81460e98dec915711fb11eaa Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Sun, 19 Jan 2025 14:40:02 +0530
Subject: [PATCH 5/7] fix test

---
 vlib/v/tests/options/option_sumtype_test.v | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/vlib/v/tests/options/option_sumtype_test.v b/vlib/v/tests/options/option_sumtype_test.v
index f17b78733600e0..9190634c64ab15 100644
--- a/vlib/v/tests/options/option_sumtype_test.v
+++ b/vlib/v/tests/options/option_sumtype_test.v
@@ -6,11 +6,13 @@ pub fn teste() ?TType {
 
 fn test_main() {
 	x := teste()
-	if x is []int {
-		dump(x)
-		y := x as []int
-		assert y == [1, 2]
-		return
+	if x != none {
+		if x is []int {
+			dump(x)
+			y := x as []int
+			assert y == [1, 2]
+			return
+		}
 	}
 	assert false
 }

From 5aab6acd45d7e55c539e1deeb4310b93a9bb66ff Mon Sep 17 00:00:00 2001
From: Swastik <swstkbaranwal@gmail.com>
Date: Sun, 19 Jan 2025 15:49:07 +0530
Subject: [PATCH 6/7] fix more tests

---
 vlib/v/debug/tests/sumtype.vv | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/vlib/v/debug/tests/sumtype.vv b/vlib/v/debug/tests/sumtype.vv
index 66ffe8bcfdcfea..21b7115df4b5e4 100644
--- a/vlib/v/debug/tests/sumtype.vv
+++ b/vlib/v/debug/tests/sumtype.vv
@@ -20,9 +20,11 @@ fn sumtype() {
 	b := ?MySum(Test{
 		a: 1
 	})
-	if b is Test {
-		dump(b)
-		$dbg;
+	if b != none {
+		if b is Test {
+    		dump(b)
+    		$dbg;
+    	}
 	}
 }
 

From 66a887beaee1f9df819928f646a4ceb9f3759b22 Mon Sep 17 00:00:00 2001
From: Felipe Pena <felipensp@gmail.com>
Date: Fri, 24 Jan 2025 20:38:04 -0300
Subject: [PATCH 7/7] fix

---
 vlib/v/gen/c/cgen.v | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v
index 36830e82cac738..a7f7254bbafb94 100644
--- a/vlib/v/gen/c/cgen.v
+++ b/vlib/v/gen/c/cgen.v
@@ -4347,17 +4347,20 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) {
 				cast_sym := g.table.sym(var_typ)
 
 				mut param_var := strings.new_builder(50)
-				is_option := obj.typ.has_flag(.option)
+				is_option := obj.orig_type.has_flag(.option)
 				var_typ_is_option := var_typ.has_flag(.option)
 				if obj.smartcasts.len > 0 {
-					is_option_unwrap := is_option && var_typ == obj.typ.clear_flag(.option)
+					is_option_unwrap := is_option && !obj.typ.has_flag(.option)
+						&& obj.orig_type.has_flag(.option)
 					mut opt_cast := false
 					mut func := if cast_sym.info is ast.Aggregate {
 						''
 					} else {
 						g.get_str_fn(var_typ)
 					}
-
+					if obj.smartcasts.len > 1 && obj_sym.kind == .sum_type {
+						param_var.write_string('*(')
+					}
 					param_var.write_string('(')
 					if obj_sym.kind == .sum_type && !obj.is_auto_heap {
 						if is_option {