From 30b8d0091c9b9e571f3324e128ba32567c2fdbf5 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 14 Apr 2026 12:45:23 +0300 Subject: [PATCH] checker: Unknown type for json.decode with nested generics (fixes #22220) --- .../tests/json_decode_with_generic_test.v | 25 +++++++++++++++++++ vlib/v/checker/fn.v | 4 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/vlib/json/tests/json_decode_with_generic_test.v b/vlib/json/tests/json_decode_with_generic_test.v index 19ac5378c..efde9c2af 100644 --- a/vlib/json/tests/json_decode_with_generic_test.v +++ b/vlib/json/tests/json_decode_with_generic_test.v @@ -10,15 +10,40 @@ struct User { username string } +struct Box[T] { + items []T +} + fn func[T]() !T { text := '{"ok": true, "result":{"id":37467243, "username": "ciao"}}' a := json.decode(Result[T], text)! return a.result } +fn string_decode[T](text string) !T { + return json.decode(T, text) +} + +fn open_box[T](text string) ![]T { + box := string_decode[Box[T]](text)! + return box.items +} + fn test_decode_with_generic_struct() { ret := func[User]()! println(ret) assert ret.id == 37467243 assert ret.username == 'ciao' } + +fn test_decode_with_nested_generic_struct() { + text := '{"items":[{},{"id":37467243,"username":"ciao"},{}]}' + items := open_box[User](text)! + assert items.len == 3 + assert items[0].id == 0 + assert items[0].username == '' + assert items[1].id == 37467243 + assert items[1].username == 'ciao' + assert items[2].id == 0 + assert items[2].username == '' +} diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index e6afbce17..8d5f1b647 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1302,7 +1302,9 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. mut concrete_types := []ast.Type{} node.concrete_types = node.raw_concrete_types for concrete_type in node.concrete_types { - if concrete_type.has_flag(.generic) { + if concrete_type.has_flag(.generic) + || (c.type_has_unresolved_generic_parts(concrete_type) + && c.table.sym(concrete_type).kind != .placeholder) { has_generic = true concrete_types << c.unwrap_generic(concrete_type) } else { -- 2.39.5