diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 18a7401c08cdb3..465abd4dd1784d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -614,6 +614,16 @@ and use a reference to the sum type instead: `var := &${node.name}(${variant_nam } } } else if sym.info is ast.FnType { + if sym.info.func.generic_names.len > 0 { + if !variant.typ.has_flag(.generic) { + c.error('generic fntype `${sym.name}` must specify generic type names, e.g. ${sym.name}[T]', + variant.pos) + } + if node.generic_types.len == 0 { + c.error('generic sumtype `${node.name}` must specify generic type names, e.g. ${node.name}[T]', + node.name_pos) + } + } if c.table.sym(sym.info.func.return_type).name.ends_with('.${node.name}') { c.error('sum type `${node.name}` cannot be defined recursively', variant.pos) } @@ -2889,6 +2899,11 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { if to_type.has_flag(.option) && from_type == ast.none_type { // allow conversion from none to every option type } else if to_sym.kind == .sum_type { + to_sym_info := to_sym.info as ast.SumType + if to_sym_info.generic_types.len > 0 && to_sym_info.concrete_types.len == 0 { + c.error('generic sumtype `${to_sym.name}` must specify type parameter, e.g. ${to_sym.name}[int]', + node.pos) + } if from_type in [ast.int_literal_type, ast.float_literal_type] { xx := if from_type == ast.int_literal_type { ast.int_type } else { ast.f64_type } node.expr_type = c.promote_num(node.expr_type, xx) diff --git a/vlib/v/checker/tests/generic_sumtype_decl_err_d.out b/vlib/v/checker/tests/generic_sumtype_decl_err_d.out new file mode 100644 index 00000000000000..a748a26e068f31 --- /dev/null +++ b/vlib/v/checker/tests/generic_sumtype_decl_err_d.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generic_sumtype_decl_err_d.vv:5:15: error: generic fntype `Fn` must specify generic type names, e.g. Fn[T] + 3 | type Fnn = fn (string) string + 4 | + 5 | type Parser = Fn | Fnn + | ~~ + 6 | + 7 | fn main() { diff --git a/vlib/v/checker/tests/generic_sumtype_decl_err_d.vv b/vlib/v/checker/tests/generic_sumtype_decl_err_d.vv new file mode 100644 index 00000000000000..d1a870cb63935a --- /dev/null +++ b/vlib/v/checker/tests/generic_sumtype_decl_err_d.vv @@ -0,0 +1,9 @@ +type Fn[T] = fn (string) T + +type Fnn = fn (string) string + +type Parser = Fn | Fnn + +fn main() { + println('hello') +} diff --git a/vlib/v/checker/tests/generic_sumtype_decl_err_e.out b/vlib/v/checker/tests/generic_sumtype_decl_err_e.out new file mode 100644 index 00000000000000..be4ac16fa15b0b --- /dev/null +++ b/vlib/v/checker/tests/generic_sumtype_decl_err_e.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/generic_sumtype_decl_err_e.vv:10:10: error: generic sumtype `Parser` must specify type parameter, e.g. Parser[int] + 8 | + 9 | fn main() { + 10 | _ := Parser(f) + | ~~~~~~~~~ + 11 | } diff --git a/vlib/v/checker/tests/generic_sumtype_decl_err_e.vv b/vlib/v/checker/tests/generic_sumtype_decl_err_e.vv new file mode 100644 index 00000000000000..362ff7dcb43886 --- /dev/null +++ b/vlib/v/checker/tests/generic_sumtype_decl_err_e.vv @@ -0,0 +1,11 @@ +type Fn[T] = fn (string) T + +type Fnn = fn (string) string + +type Parser[T] = Fn[T] | Fnn + +fn f(x string) string { return '>> f $x' } + +fn main() { + _ := Parser(f) +}