From 0454f43fa394d2883ca06a3ba1d7d4d396732d3d Mon Sep 17 00:00:00 2001 From: Turiiya <34311583+tobealive@users.noreply.github.com> Date: Sun, 18 Jun 2023 21:22:22 +0200 Subject: [PATCH] checker: fix error assigning generic function variable with generic struct return (#18472) --- vlib/v/checker/assign.v | 10 ++++++++++ .../tests/generic_fn_infinite_loop_limit_err.out | 7 +++++++ .../tests/unknown_array_fn_type_in_struct_field.out | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 8029077119..7d6481ff99 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -507,6 +507,16 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { c.error('cannot copy map: call `move` or `clone` method (or use a reference)', right.pos()) } + if left_sym.kind == .function && right_sym.info is ast.FnType { + return_sym := c.table.sym(right_sym.info.func.return_type) + if return_sym.kind == .placeholder { + c.error('unkown return type: cannot assign `${right}` as a function variable', + right.pos()) + } else if (!right_sym.info.is_anon && return_sym.kind == .any) + || (return_sym.info is ast.Struct && (return_sym.info as ast.Struct).is_generic) { + c.error('cannot assign `${right}` as a generic function variable', right.pos()) + } + } if left_type.is_any_kind_of_pointer() && !left.is_auto_deref_var() { if !c.inside_unsafe && node.op !in [.assign, .decl_assign] { // ptr op= diff --git a/vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.out b/vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.out index ae3fea7840..baff173944 100644 --- a/vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.out +++ b/vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.out @@ -5,6 +5,13 @@ vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.vv:6:2: warning: unused | ~~~ 7 | // ff1 := f1[int] <-- is a valid usage with generic return types that are not generic structs 8 | } +vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.vv:6:9: error: cannot assign `f1` as a generic function variable + 4 | + 5 | fn main() { + 6 | ff1 := f1 // <-- missing e.g. `[int]` + | ~~ + 7 | // ff1 := f1[int] <-- is a valid usage with generic return types that are not generic structs + 8 | } vlib/v/checker/tests/generic_fn_infinite_loop_limit_err.vv:1:1: error: generic function visited more than 10000 times 1 | fn f1[T](x T, i int) T { | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/vlib/v/checker/tests/unknown_array_fn_type_in_struct_field.out b/vlib/v/checker/tests/unknown_array_fn_type_in_struct_field.out index 6ed81f7f9a..84c2a0ffe1 100644 --- a/vlib/v/checker/tests/unknown_array_fn_type_in_struct_field.out +++ b/vlib/v/checker/tests/unknown_array_fn_type_in_struct_field.out @@ -5,3 +5,10 @@ Did you mean `[2]fn (u32) UnknownThing`? | ~~~~~~~~~~~~ 3 | } 4 | +vlib/v/checker/tests/unknown_array_fn_type_in_struct_field.vv:6:18: error: unkown return type: cannot assign `virt.fns[0]` as a function variable + 4 | + 5 | fn (virt Virt) caller() { + 6 | func := virt.fns[0] + | ~~~ + 7 | func(5) + 8 | }