@@ -969,6 +969,15 @@ fn (mut c Checker) comptime_if_to_ifdef(name string) !string {
969969 return error ('bad os ifdef name "${name }"' )
970970}
971971
972+ // check if `ident` is a function generic, such as `T`
973+ fn (mut c Checker) is_generic_ident (ident string ) bool {
974+ if ! isnil (c.table.cur_fn) && ident in c.table.cur_fn.generic_names
975+ && c.table.cur_fn.generic_names.len == c.table.cur_concrete_types.len {
976+ return true
977+ }
978+ return false
979+ }
980+
972981fn (mut c Checker) get_expr_type (cond ast.Expr) ast.Type {
973982 match cond {
974983 ast.Ident {
@@ -978,6 +987,10 @@ fn (mut c Checker) get_expr_type(cond ast.Expr) ast.Type {
978987 || cond.name == c.comptime.comptime_for_field_var) {
979988 // struct field
980989 return c.type_resolver.get_type_from_comptime_var (cond)
990+ } else if c.is_generic_ident (cond.name) {
991+ // generic type `T`
992+ idx := c.table.cur_fn.generic_names.index (cond.name)
993+ return c.table.cur_concrete_types[idx]
981994 } else if var := cond.scope.find_var (cond.name) {
982995 // var
983996 checked_type = c.unwrap_generic (var.typ)
@@ -1042,6 +1055,35 @@ fn (mut c Checker) get_expr_type(cond ast.Expr) ast.Type {
10421055 }
10431056}
10441057
1058+ fn (mut c Checker) check_compatible_types (left_type ast.Type, left_name string , expr ast.Expr) bool {
1059+ if expr is ast.ComptimeType {
1060+ return c.type_resolver.is_comptime_type (left_type, expr as ast.ComptimeType )
1061+ } else if expr is ast.TypeNode {
1062+ typ := c.get_expr_type (expr)
1063+ right_type := c.unwrap_generic (typ)
1064+ right_sym := c.table.sym (right_type)
1065+ if right_sym.kind == .placeholder || right_type.has_flag (.generic) {
1066+ c.error ('unknown type `${right_sym .name }`' , expr.pos)
1067+ }
1068+ if right_sym.kind == .interface && right_sym.info is ast.Interface {
1069+ return left_type.has_flag (.option) == right_type.has_flag (.option)
1070+ && c.table.does_type_implement_interface (left_type, right_type)
1071+ }
1072+ if right_sym.info is ast.FnType && c.comptime.comptime_for_method_var == left_name {
1073+ return c.table.fn_signature (right_sym.info.func,
1074+ skip_receiver: true
1075+ type_only: true
1076+ ) == c.table.fn_signature (c.comptime.comptime_for_method,
1077+ skip_receiver: true
1078+ type_only: true
1079+ )
1080+ } else {
1081+ return left_type == right_type
1082+ }
1083+ }
1084+ return false
1085+ }
1086+
10451087// comptime_if_cond evaluate the `cond` and return (`is_true`, `keep_stmts`)
10461088// `is_true` is the evaluate result of `cond`;
10471089// `keep_stmts` meaning the branch is a `multi pass branch`, we should keep the branch stmts even `is_true` is false, such as `$if T is int {`
@@ -1141,45 +1183,9 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, mut sb strings.Builder) (
11411183 }
11421184 // iter the `type_array`, for `is` and `!is`, it has only one element
11431185 for expr in type_array {
1144- if expr is ast.ComptimeType {
1145- is_true = c.type_resolver.is_comptime_type (left_type,
1146- expr as ast.ComptimeType )
1147- if is_true {
1148- break
1149- }
1150- } else if expr is ast.TypeNode {
1151- typ := c.get_expr_type (expr)
1152- right_type := c.unwrap_generic (typ)
1153- right_sym := c.table.sym (right_type)
1154- if right_sym.kind == .placeholder || right_type.has_flag (.generic) {
1155- c.error ('unknown type `${right_sym .name }`' , expr.pos)
1156- }
1157- if right_sym.kind == .interface && right_sym.info is ast.Interface {
1158- is_true =
1159- left_type.has_flag (.option) == right_type.has_flag (.option)
1160- && c.table.does_type_implement_interface (left_type, right_type)
1161- if is_true {
1162- break
1163- }
1164- }
1165- if right_sym.info is ast.FnType
1166- && c.comptime.comptime_for_method_var == left_name {
1167- is_true = c.table.fn_signature (right_sym.info.func,
1168- skip_receiver: true
1169- type_only: true
1170- ) == c.table.fn_signature (c.comptime.comptime_for_method,
1171- skip_receiver: true
1172- type_only: true
1173- )
1174- if is_true {
1175- break
1176- }
1177- } else {
1178- is_true = left_type == right_type
1179- if is_true {
1180- break
1181- }
1182- }
1186+ is_true = c.check_compatible_types (left_type, left_name, expr)
1187+ if is_true {
1188+ break
11831189 }
11841190 }
11851191 is_true = if cond.op in [.key_in, .key_is] { is_true } else { ! is_true }
0 commit comments