From f1333be65e9895d2099cd99dc9426c218ea966b3 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 17 Nov 2024 08:35:04 -0300 Subject: [PATCH] checker: fix alias to struct generic type (fix #22866) (#22872) --- vlib/v/ast/table.v | 66 +++++++++++-------- .../tests/aliases/alias_generic_struct_test.v | 20 ++++++ 2 files changed, 60 insertions(+), 26 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 a305a27ce45a1a..ed94ea826c87cb 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1910,7 +1910,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) @@ -2008,6 +2007,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 { @@ -2056,27 +2066,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.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 {} @@ -2096,8 +2085,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) } @@ -2132,8 +2121,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) } @@ -2187,6 +2176,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/tests/aliases/alias_generic_struct_test.v b/vlib/v/tests/aliases/alias_generic_struct_test.v new file mode 100644 index 00000000000000..3ead570c911cf0 --- /dev/null +++ b/vlib/v/tests/aliases/alias_generic_struct_test.v @@ -0,0 +1,20 @@ +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(Vec4x{3, 3, 3, 3}) + assert v.x == 3 + assert v.y == 3 + assert v.z == 3 + assert v.w == 3 +}