From 8b02d8f406119a4ec25e22dc98b161727a367726 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 06:00:39 +0300 Subject: [PATCH] comptime: fix unknown type error when using a generic interface (fixes #20762) --- vlib/v/checker/comptime.v | 14 +++++++-- .../comptime_if_is_generic_interface_test.v | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/comptime/comptime_if_is_generic_interface_test.v diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index e6f78502c..00386287a 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -1266,10 +1266,19 @@ fn (mut c Checker) check_compatible_types(left_type ast.Type, left_name string, } else if expr is ast.TypeNode { typ := c.get_expr_type(expr) right_type := c.unwrap_generic(typ) + mut right_sym := c.table.sym(right_type) + if right_sym.kind == .generic_inst { + gi := right_sym.info as ast.GenericInst + if gi.parent_idx > 0 && gi.parent_idx < c.table.type_symbols.len + && c.table.type_symbols[gi.parent_idx].kind == .interface + && !gi.concrete_types.any(c.type_has_unresolved_generic_parts(it)) { + c.table.generic_insts_to_concrete() + right_sym = c.table.sym(right_type) + } + } if c.type_resolver.bind_matching_generic_type(resolved_left_type, right_type) { return true } - right_sym := c.table.sym(right_type) if right_sym.kind == .placeholder || right_type.has_flag(.generic) { c.error('unknown type `${right_sym.name}`', expr.pos) } @@ -1278,7 +1287,8 @@ fn (mut c Checker) check_compatible_types(left_type ast.Type, left_name string, && c.table.does_type_implement_interface(resolved_left_type, right_type) } if right_sym.info is ast.FnType && c.comptime.comptime_for_method_var == left_name { - return c.table.fn_signature(right_sym.info.func, + right_fn_type := right_sym.info as ast.FnType + return c.table.fn_signature(right_fn_type.func, skip_receiver: true type_only: true ) == c.table.fn_signature(c.comptime.comptime_for_method, diff --git a/vlib/v/tests/comptime/comptime_if_is_generic_interface_test.v b/vlib/v/tests/comptime/comptime_if_is_generic_interface_test.v new file mode 100644 index 000000000..f365815de --- /dev/null +++ b/vlib/v/tests/comptime/comptime_if_is_generic_interface_test.v @@ -0,0 +1,31 @@ +struct Context {} + +struct App { +mut: + called bool +} + +fn (mut app App) before_request(mut ctx Context) { + app.called = true +} + +interface HasBeforeRequest[X] { +mut: + before_request(mut ctx X) +} + +fn check_before_request[A, X](mut app A) bool { + mut ctx := Context{} + $if A is HasBeforeRequest[X] { + app.before_request(mut ctx) + return true + } $else { + return false + } +} + +fn test_comptime_if_is_generic_interface_with_generic_type_param() { + mut app := App{} + assert check_before_request[App, Context](mut app) + assert app.called +} -- 2.39.5