@@ -223,6 +223,8 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
223223 }
224224 }
225225
226+ c.check_option_infix_expr (node, left_type, right_type, left_sym, right_sym)
227+
226228 // Do not allow comparing nil to non-pointers
227229 if node.left.is_nil () {
228230 mut final_type := right_type
@@ -607,11 +609,8 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
607609 }
608610 }
609611 }
610- } else if node.left ! in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector]
611- && (left_type.has_flag (.option) || right_type.has_flag (.option)) {
612- opt_comp_pos := if left_type.has_flag (.option) { left_pos } else { right_pos }
613- c.error ('unwrapped Option cannot be compared in an infix expression' ,
614- opt_comp_pos)
612+ } else {
613+ c.check_option_infix_expr (node, left_type, right_type, left_sym, right_sym)
615614 }
616615 if node.left.is_nil () || node.right.is_nil () {
617616 c.error ('cannot use `${node.op.str()} ` with `nil`' , node.pos)
@@ -829,15 +828,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
829828 c.error ('cannot use operator `${node.op} ` with `${right_sym.name} `' , node.pos)
830829 }
831830 // TODO: move this to symmetric_check? Right now it would break `return 0` for `fn()?int `
832- left_is_option := left_type.has_flag (.option)
833- right_is_option := right_type.has_flag (.option)
834- if left_is_option || right_is_option {
835- opt_infix_pos := if left_is_option { left_pos } else { right_pos }
836- if (node.left ! in [ast.Ident, ast.IndexExpr, ast.SelectorExpr, ast.ComptimeSelector]
837- || (node.op in [.eq, .ne] && ! right_is_option)
838- || node.op in [.lt, .gt, .le, .ge]) && right_sym.kind != .none && ! c.inside_sql {
839- c.error ('unwrapped Option cannot be used in an infix expression' , opt_infix_pos)
840- }
831+ if node.left ! in [ast.Ident, ast.IndexExpr, ast.SelectorExpr, ast.ComptimeSelector]
832+ || node.op in [.eq, .ne] {
833+ c.check_option_infix_expr (node, left_type, right_type, left_sym, right_sym)
841834 }
842835
843836 left_is_result := left_type.has_flag (.result)
@@ -886,7 +879,10 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
886879 node.promoted_type = return_type
887880 return return_type
888881 }
889- if node.right is ast.None && left_is_option {
882+ left_is_option := left_type.has_flag (.option)
883+ right_is_option := right_type.has_flag (.option)
884+ if (node.right is ast.None && left_is_option)
885+ || (node.left is ast.None && right_is_option) {
890886 return ast.bool_type
891887 }
892888 error_left_sym := if node.left.is_auto_deref_var () {
@@ -1091,3 +1087,31 @@ fn (mut c Checker) check_sort_external_variable_access(node ast.Expr) bool {
10911087 }
10921088 return true
10931089}
1090+
1091+ fn (mut c Checker) check_option_infix_expr (node ast.InfixExpr, left_type ast.Type, right_type ast.Type, left_sym ast.TypeSymbol, right_sym ast.TypeSymbol) {
1092+ if c.inside_sql {
1093+ return
1094+ }
1095+ left_is_option := left_type.has_flag (.option)
1096+ right_is_option := right_type.has_flag (.option)
1097+ if (node.left is ast.None && right_is_option)
1098+ || (node.right is ast.None && left_is_option)
1099+ || (left_sym.kind == .none || right_sym.kind == .none ) {
1100+ return
1101+ }
1102+ if left_is_option || right_is_option {
1103+ pos , opt , nopt := if left_is_option {
1104+ node.left.pos (), left_sym.name, right_sym.name
1105+ } else {
1106+ node.right.pos (), right_sym.name, left_sym.name
1107+ }
1108+ if left_is_option && right_is_option {
1109+ if node.op ! in [.eq, .ne] {
1110+ c.error ('`?${opt} ` cannot be used as `${nopt} `, unwrap the option first' ,
1111+ pos)
1112+ }
1113+ return
1114+ }
1115+ c.error ('`?${opt} ` cannot be used as `${nopt} `, unwrap the option first' , pos)
1116+ }
1117+ }
0 commit comments