From 076e12c44963efc6f7a4ddfa3ed5e740d54cab13 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 16 Nov 2024 08:48:09 -0300 Subject: [PATCH 1/4] fix --- vlib/v/ast/table.v | 6 +++-- vlib/v/checker/checker.v | 6 +++++ .../tests/aliases/alias_generic_struct_test.v | 25 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/aliases/alias_generic_struct_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 1d13cd276373b1..e6943a9c1d9c6a 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1945,7 +1945,9 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co return new_type(idx).derive_add_muls(typ).clear_flag(.generic) } Struct, Interface, SumType { - if !ts.info.is_generic { + // alias to generic type needs to be rechecked + // e.g. type Vec4 = vec.Vec4[f64] + if !ts.info.is_generic && !(generic_names.len > 0 && recheck_concrete_types) { return typ } mut t_generic_names := generic_names.clone() @@ -2054,7 +2056,7 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co } } if final_concrete_types.len > 0 { - for method in ts.methods { + for method in ts.get_methods() { for i in 1 .. method.params.len { if method.params[i].typ.has_flag(.generic) && method.params[i].typ != method.params[0].typ { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 965cee2bf2e44a..c6346419667e2d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -599,6 +599,12 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) { } } } + + // Recheck generic type with its supplied concrete type + if parent_typ_sym.info.generic_types.len > 0 { + c.table.unwrap_generic_type_ex(node.parent_type, parent_typ_sym.info.generic_types.map(c.table.type_to_str(it)), + parent_typ_sym.info.concrete_types, true) + } } } .array { diff --git a/vlib/v/tests/aliases/alias_generic_struct_test.v b/vlib/v/tests/aliases/alias_generic_struct_test.v new file mode 100644 index 00000000000000..b195949815cbce --- /dev/null +++ b/vlib/v/tests/aliases/alias_generic_struct_test.v @@ -0,0 +1,25 @@ +module main + +import math.vec + +type Vec4 = vec.Vec4[f32] +type Vec4x = vec.Vec4[f32] + +fn test_main() { + mut v := Vec4{0, 0, 0, 1} + v.one() + assert v.x == 1 + assert v.y == 1 + assert v.z == 1 + assert v.w == 1 + v.from(vec.Vec4[f32]{2, 2, 2, 2}) + assert v.x == 2 + assert v.y == 2 + assert v.z == 2 + assert v.w == 2 + v.from(Vec4x{3, 3, 3, 3}) + assert v.x == 3 + assert v.y == 3 + assert v.z == 3 + assert v.w == 3 +} From 4ba0cf5daedc1cda268ce79ae033c66cff1c887a Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 16 Nov 2024 09:14:02 -0300 Subject: [PATCH 2/4] cleanup --- vlib/v/ast/table.v | 68 ++++++++++++++++++++++++---------------- vlib/v/checker/checker.v | 6 ---- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index e6943a9c1d9c6a..3f855fc837b47f 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1907,7 +1907,6 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, concrete_types []Type, recheck_concrete_types bool) Type { mut final_concrete_types := []Type{} mut fields := []StructField{} - mut needs_unwrap_types := []Type{} mut nrt := '' mut c_nrt := '' ts := t.sym(typ) @@ -1947,7 +1946,7 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co Struct, Interface, SumType { // alias to generic type needs to be rechecked // e.g. type Vec4 = vec.Vec4[f64] - if !ts.info.is_generic && !(generic_names.len > 0 && recheck_concrete_types) { + if !ts.info.is_generic { // && !(generic_names.len > 0 && recheck_concrete_types) { return typ } mut t_generic_names := generic_names.clone() @@ -2007,6 +2006,17 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co recheck_concrete_types) } } + // update concrete types + for i in 0 .. ts.info.generic_types.len { + if t_typ := t.convert_generic_type(ts.info.generic_types[i], t_generic_names, + t_concrete_types) + { + final_concrete_types << t_typ + } + } + if final_concrete_types.len > 0 { + t.unwrap_method_types(ts, generic_names, concrete_types, final_concrete_types) + } } return new_type(idx).derive(typ).clear_flag(.generic) } else { @@ -2055,27 +2065,6 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co final_concrete_types << t_typ } } - if final_concrete_types.len > 0 { - for method in ts.get_methods() { - for i in 1 .. method.params.len { - if method.params[i].typ.has_flag(.generic) - && method.params[i].typ != method.params[0].typ { - if method.params[i].typ !in needs_unwrap_types { - needs_unwrap_types << method.params[i].typ - } - } - if method.return_type.has_flag(.generic) - && method.return_type != method.params[0].typ { - if method.return_type !in needs_unwrap_types { - needs_unwrap_types << method.return_type - } - } - } - if final_concrete_types.len == method.generic_names.len { - t.register_fn_concrete_types(method.fkey(), final_concrete_types) - } - } - } } } else {} @@ -2095,8 +2084,8 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co info: info is_pub: ts.is_pub ) - for typ_ in needs_unwrap_types { - t.unwrap_generic_type(typ_, generic_names, concrete_types) + if final_concrete_types.len > 0 { + t.unwrap_method_types(ts, generic_names, concrete_types, final_concrete_types) } return new_type(new_idx).derive(typ).clear_flag(.generic) } @@ -2131,8 +2120,8 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co info: info is_pub: ts.is_pub ) - for typ_ in needs_unwrap_types { - t.unwrap_generic_type(typ_, generic_names, concrete_types) + if final_concrete_types.len > 0 { + t.unwrap_method_types(ts, generic_names, concrete_types, final_concrete_types) } return new_type(new_idx).derive(typ).clear_flag(.generic) } @@ -2186,6 +2175,31 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co return typ } +fn (mut t Table) unwrap_method_types(ts &TypeSymbol, generic_names []string, concrete_types []Type, final_concrete_types []Type) { + mut needs_unwrap_types := []Type{} + for method in ts.get_methods() { + for i in 1 .. method.params.len { + if method.params[i].typ.has_flag(.generic) + && method.params[i].typ != method.params[0].typ { + if method.params[i].typ !in needs_unwrap_types { + needs_unwrap_types << method.params[i].typ + } + } + if method.return_type.has_flag(.generic) && method.return_type != method.params[0].typ { + if method.return_type !in needs_unwrap_types { + needs_unwrap_types << method.return_type + } + } + } + if final_concrete_types.len == method.generic_names.len { + t.register_fn_concrete_types(method.fkey(), final_concrete_types) + } + } + for typ_ in needs_unwrap_types { + t.unwrap_generic_type(typ_, generic_names, concrete_types) + } +} + // generic struct instantiations to concrete types pub fn (mut t Table) generic_insts_to_concrete() { for mut sym in t.type_symbols { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index c6346419667e2d..965cee2bf2e44a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -599,12 +599,6 @@ fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) { } } } - - // Recheck generic type with its supplied concrete type - if parent_typ_sym.info.generic_types.len > 0 { - c.table.unwrap_generic_type_ex(node.parent_type, parent_typ_sym.info.generic_types.map(c.table.type_to_str(it)), - parent_typ_sym.info.concrete_types, true) - } } } .array { From ae668527b159fc4722d6873996a0055529ebafaf Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 16 Nov 2024 09:16:41 -0300 Subject: [PATCH 3/4] cleanup --- vlib/v/ast/table.v | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 3f855fc837b47f..723ae3da2ec812 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1944,9 +1944,7 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co return new_type(idx).derive_add_muls(typ).clear_flag(.generic) } Struct, Interface, SumType { - // alias to generic type needs to be rechecked - // e.g. type Vec4 = vec.Vec4[f64] - if !ts.info.is_generic { // && !(generic_names.len > 0 && recheck_concrete_types) { + if !ts.info.is_generic { return typ } mut t_generic_names := generic_names.clone() From b402e4a9c63926b39ce6f7124a9655401ed83084 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 17 Nov 2024 07:37:03 -0300 Subject: [PATCH 4/4] fix test for reproduce bug --- vlib/v/tests/aliases/alias_generic_struct_test.v | 5 ----- 1 file changed, 5 deletions(-) diff --git a/vlib/v/tests/aliases/alias_generic_struct_test.v b/vlib/v/tests/aliases/alias_generic_struct_test.v index b195949815cbce..3ead570c911cf0 100644 --- a/vlib/v/tests/aliases/alias_generic_struct_test.v +++ b/vlib/v/tests/aliases/alias_generic_struct_test.v @@ -12,11 +12,6 @@ fn test_main() { assert v.y == 1 assert v.z == 1 assert v.w == 1 - v.from(vec.Vec4[f32]{2, 2, 2, 2}) - assert v.x == 2 - assert v.y == 2 - assert v.z == 2 - assert v.w == 2 v.from(Vec4x{3, 3, 3, 3}) assert v.x == 3 assert v.y == 3