@@ -979,15 +979,112 @@ fn (mut g Gen) resolve_selector_smartcast_type(node ast.SelectorExpr) ast.Type {
979979 scope := g.file.scope.innermost (node.pos.pos)
980980 field := scope.find_struct_field (node.expr.str (), node.expr_type, node.field_name)
981981 if field != unsafe { nil } && field.smartcasts.len > 0 {
982+ smartcast_type := field.smartcasts.last ()
983+ field_unwrapped_type := field.orig_type.clear_option_and_result ()
984+ if field.orig_type.has_option_or_result () && ! smartcast_type.has_option_or_result ()
985+ && smartcast_type == field_unwrapped_type {
986+ left_default := if node.expr_type != 0 { node.expr_type } else { field.struct_type }
987+ left_type := g.resolved_expr_type (node.expr, left_default)
988+ resolved_field_type := g.resolved_selector_field_type (node, left_type)
989+ if resolved_field_type != 0 {
990+ return resolved_field_type.clear_option_and_result ()
991+ }
992+ }
982993 resolved_sc := g.unwrap_generic (g.recheck_concrete_type (g.exposed_smartcast_type (field.orig_type,
983- field.smartcasts. last () , field.is_mut)))
994+ smartcast_type , field.is_mut)))
984995 if resolved_sc != 0 {
985996 return resolved_sc
986997 }
987998 }
988999 return 0
9891000}
9901001
1002+ fn (mut g Gen) resolved_selector_field_type (node ast.SelectorExpr, receiver_type ast.Type) ast.Type {
1003+ if receiver_type == 0 {
1004+ return 0
1005+ }
1006+ sym := g.table.sym (g.unwrap_generic (receiver_type))
1007+ if field := g.table.find_field_with_embeds (sym, node.field_name) {
1008+ mut field_type := field.typ
1009+ match sym.info {
1010+ ast.Struct, ast.Interface, ast.SumType {
1011+ mut generic_names := sym.info.generic_types.map (g.table.sym (it ).name)
1012+ mut concrete_types := sym.info.concrete_types.clone ()
1013+ if concrete_types.len == 0 && sym.generic_types.len == generic_names.len
1014+ && sym.generic_types != sym.info.generic_types {
1015+ concrete_types = sym.generic_types.clone ()
1016+ }
1017+ mut source_field_type := field.typ
1018+ if sym.info.parent_type.has_flag (.generic) {
1019+ parent_sym := g.table.sym (sym.info.parent_type)
1020+ if parent_field := g.table.find_field_with_embeds (parent_sym, node.field_name) {
1021+ source_field_type = parent_field.typ
1022+ match parent_sym.info {
1023+ ast.Struct, ast.Interface, ast.SumType {
1024+ generic_names =
1025+ parent_sym.info.generic_types.map (g.table.sym (it ).name)
1026+ }
1027+ else {}
1028+ }
1029+ }
1030+ }
1031+ if generic_names.len == concrete_types.len && concrete_types.len > 0 {
1032+ mut muttable := unsafe { & ast.Table (g.table) }
1033+ resolved_field_type := muttable.unwrap_generic_type_ex (source_field_type,
1034+ generic_names, concrete_types, true )
1035+ if resolved_field_type != source_field_type {
1036+ field_type = resolved_field_type
1037+ } else {
1038+ if converted_field_type := muttable.convert_generic_type (source_field_type,
1039+ generic_names, concrete_types)
1040+ {
1041+ field_type = converted_field_type
1042+ }
1043+ }
1044+ }
1045+ }
1046+ ast.GenericInst {
1047+ parent_sym := g.table.sym (ast.new_type (sym.info.parent_idx))
1048+ mut source_field_type := field.typ
1049+ if parent_field := g.table.find_field_with_embeds (parent_sym, node.field_name) {
1050+ source_field_type = parent_field.typ
1051+ }
1052+ match parent_sym.info {
1053+ ast.Struct, ast.Interface, ast.SumType {
1054+ generic_names := parent_sym.info.generic_types.map (g.table.sym (it ).name)
1055+ if generic_names.len == sym.info.concrete_types.len
1056+ && sym.info.concrete_types.len > 0 {
1057+ mut muttable := unsafe { & ast.Table (g.table) }
1058+ resolved_field_type := muttable.unwrap_generic_type_ex (source_field_type,
1059+ generic_names, sym.info.concrete_types, true )
1060+ if resolved_field_type != source_field_type {
1061+ field_type = resolved_field_type
1062+ } else {
1063+ if converted_field_type := muttable.convert_generic_type (source_field_type,
1064+ generic_names, sym.info.concrete_types)
1065+ {
1066+ field_type = converted_field_type
1067+ }
1068+ }
1069+ }
1070+ }
1071+ else {}
1072+ }
1073+ }
1074+ else {}
1075+ }
1076+
1077+ $if trace_ci_fixes ? {
1078+ if g.file.path.contains ('binary_search_tree.v' ) && node.expr is ast.Ident
1079+ && node.expr.name == 'tree' {
1080+ eprintln ('resolved selector ${node.expr.name} .${node.field_name} left=${g.table.type_to_str(receiver_type)} field=${g.table.type_to_str(field.typ)} final=${g.table.type_to_str(field_type)} expr_typ=${g.table.type_to_str(node.typ)} ' )
1081+ }
1082+ }
1083+ return g.unwrap_generic (g.recheck_concrete_type (field_type))
1084+ }
1085+ return 0
1086+ }
1087+
9911088fn (mut g Gen) resolved_expr_type (expr ast.Expr, default_typ ast.Type) ast.Type {
9921089 match expr {
9931090 ast.ParExpr {
@@ -1179,89 +1276,8 @@ fn (mut g Gen) resolved_expr_type(expr ast.Expr, default_typ ast.Type) ast.Type
11791276 left_default := if expr.expr_type != 0 { expr.expr_type } else { default_typ }
11801277 left_type := g.recheck_concrete_type (g.resolved_expr_type (expr.expr, left_default))
11811278 if left_type != 0 {
1182- sym := g.table.sym (g.unwrap_generic (left_type))
1183- if field := g.table.find_field_with_embeds (sym, expr.field_name) {
1184- mut field_type := field.typ
1185- match sym.info {
1186- ast.Struct, ast.Interface, ast.SumType {
1187- mut generic_names := sym.info.generic_types.map (g.table.sym (it ).name)
1188- mut concrete_types := sym.info.concrete_types.clone ()
1189- if concrete_types.len == 0 && sym.generic_types.len == generic_names.len
1190- && sym.generic_types != sym.info.generic_types {
1191- concrete_types = sym.generic_types.clone ()
1192- }
1193- mut source_field_type := field.typ
1194- if sym.info.parent_type.has_flag (.generic) {
1195- parent_sym := g.table.sym (sym.info.parent_type)
1196- if parent_field := g.table.find_field_with_embeds (parent_sym,
1197- expr.field_name)
1198- {
1199- source_field_type = parent_field.typ
1200- match parent_sym.info {
1201- ast.Struct, ast.Interface, ast.SumType {
1202- generic_names =
1203- parent_sym.info.generic_types.map (g.table.sym (it ).name)
1204- }
1205- else {}
1206- }
1207- }
1208- }
1209- if generic_names.len == concrete_types.len && concrete_types.len > 0 {
1210- mut muttable := unsafe { & ast.Table (g.table) }
1211- resolved_field_type := muttable.unwrap_generic_type_ex (source_field_type,
1212- generic_names, concrete_types, true )
1213- if resolved_field_type != source_field_type {
1214- field_type = resolved_field_type
1215- } else {
1216- if converted_field_type := muttable.convert_generic_type (source_field_type,
1217- generic_names, concrete_types)
1218- {
1219- field_type = converted_field_type
1220- }
1221- }
1222- }
1223- }
1224- ast.GenericInst {
1225- parent_sym := g.table.sym (ast.new_type (sym.info.parent_idx))
1226- mut source_field_type := field.typ
1227- if parent_field := g.table.find_field_with_embeds (parent_sym,
1228- expr.field_name)
1229- {
1230- source_field_type = parent_field.typ
1231- }
1232- match parent_sym.info {
1233- ast.Struct, ast.Interface, ast.SumType {
1234- generic_names :=
1235- parent_sym.info.generic_types.map (g.table.sym (it ).name)
1236- if generic_names.len == sym.info.concrete_types.len
1237- && sym.info.concrete_types.len > 0 {
1238- mut muttable := unsafe { & ast.Table (g.table) }
1239- resolved_field_type := muttable.unwrap_generic_type_ex (source_field_type,
1240- generic_names, sym.info.concrete_types, true )
1241- if resolved_field_type != source_field_type {
1242- field_type = resolved_field_type
1243- } else {
1244- if converted_field_type := muttable.convert_generic_type (source_field_type,
1245- generic_names, sym.info.concrete_types)
1246- {
1247- field_type = converted_field_type
1248- }
1249- }
1250- }
1251- }
1252- else {}
1253- }
1254- }
1255- else {}
1256- }
1257-
1258- $if trace_ci_fixes ? {
1259- if g.file.path.contains ('binary_search_tree.v' ) && expr.expr is ast.Ident
1260- && expr.expr.name == 'tree' {
1261- eprintln ('resolved selector ${expr.expr.name} .${expr.field_name} left=${g.table.type_to_str(left_type)} field=${g.table.type_to_str(field.typ)} final=${g.table.type_to_str(field_type)} expr_typ=${g.table.type_to_str(expr.typ)} ' )
1262- }
1263- }
1264- mut resolved_type := g.unwrap_generic (g.recheck_concrete_type (field_type))
1279+ mut resolved_type := g.resolved_selector_field_type (expr, left_type)
1280+ if resolved_type != 0 {
12651281 if expr.or_block.kind != .absent {
12661282 resolved_type = resolved_type.clear_option_and_result ()
12671283 }
0 commit comments