@@ -969,6 +969,15 @@ fn (mut c Checker) comptime_if_to_ifdef(name string) !string {
969
969
return error ('bad os ifdef name "${name} "' )
970
970
}
971
971
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
+
972
981
fn (mut c Checker) get_expr_type (cond ast.Expr) ast.Type {
973
982
match cond {
974
983
ast.Ident {
@@ -978,6 +987,10 @@ fn (mut c Checker) get_expr_type(cond ast.Expr) ast.Type {
978
987
|| cond.name == c.comptime.comptime_for_field_var) {
979
988
// struct field
980
989
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]
981
994
} else if var := cond.scope.find_var (cond.name) {
982
995
// var
983
996
checked_type = c.unwrap_generic (var.typ)
@@ -1042,6 +1055,35 @@ fn (mut c Checker) get_expr_type(cond ast.Expr) ast.Type {
1042
1055
}
1043
1056
}
1044
1057
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
+
1045
1087
// comptime_if_cond evaluate the `cond` and return (`is_true`, `keep_stmts`)
1046
1088
// `is_true` is the evaluate result of `cond`;
1047
1089
// `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) (
1141
1183
}
1142
1184
// iter the `type_array`, for `is` and `!is`, it has only one element
1143
1185
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
1183
1189
}
1184
1190
}
1185
1191
is_true = if cond.op in [.key_in, .key_is] { is_true } else { ! is_true }
0 commit comments