1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: replace generic '<>' with '[]' in error messages and comments (#16571)

This commit is contained in:
yuyi 2022-12-02 15:22:48 +08:00 committed by GitHub
parent cbe64cb543
commit f16722596c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 70 additions and 71 deletions

View File

@ -1986,7 +1986,7 @@ fn (t Tree) asm_io(node ast.AsmIO) &Node {
}
// do not support yet by vlang
// fn (t Tree) array_node1<T>(nodes []T, method_name string) &Node {
// fn (t Tree) array_node1[T](nodes []T, method_name string) &Node {
// mut arr := new_array()
// // call method dynamically, V do not support yet
@ -2009,7 +2009,7 @@ fn (t Tree) asm_io(node ast.AsmIO) &Node {
// }
// do not support yet by vlang
// fn (t Tree) array_node2<T>(nodes []T) &Node {
// fn (t Tree) array_node2[T](nodes []T) &Node {
// mut arr := new_array()
// for node in nodes {

View File

@ -7,7 +7,7 @@ mut:
prev &DoublyListNode[T] = unsafe { 0 }
}
// DoublyLinkedList<T> represents a generic doubly linked list of elements, each of type T.
// DoublyLinkedList[T] represents a generic doubly linked list of elements, each of type T.
pub struct DoublyLinkedList[T] {
mut:
head &DoublyListNode[T] = unsafe { 0 }
@ -298,7 +298,7 @@ pub fn (mut list DoublyLinkedList[T]) back_iterator() DoublyListIterBack[T] {
}
}
// DoublyListIter<T> is an iterator for DoublyLinkedList.
// DoublyListIter[T] is an iterator for DoublyLinkedList.
// It starts from *the start* and moves forwards to *the end* of the list.
// It can be used with V's `for x in iter {` construct.
// One list can have multiple independent iterators, pointing to different positions/places in the list.
@ -319,7 +319,7 @@ pub fn (mut iter DoublyListIter[T]) next() ?T {
return res
}
// DoublyListIterBack<T> is an iterator for DoublyLinkedList.
// DoublyListIterBack[T] is an iterator for DoublyLinkedList.
// It starts from *the end* and moves backwards to *the start* of the list.
// It can be used with V's `for x in iter {` construct.
// One list can have multiple independent iterators, pointing to different positions/places in the list.

View File

@ -192,7 +192,7 @@ pub fn (mut list LinkedList[T]) iterator() ListIter[T] {
}
}
// ListIter<T> is an iterator for LinkedList.
// ListIter[T] is an iterator for LinkedList.
// It can be used with V's `for x in iter {` construct.
// One list can have multiple independent iterators, pointing to different positions/places in the list.
// An iterator instance always traverses the list from start to finish.

View File

@ -47,7 +47,7 @@ pub fn (mut set Set[T]) clear() {
}
// equal checks whether the two given sets are equal (i.e. contain all and only the same elements).
[deprecated: 'use set1<T> == set2<T> instead']
[deprecated: 'use set1[T] == set2[T] instead']
pub fn (l Set[T]) equal(r Set[T]) bool {
return l == r
}
@ -115,7 +115,7 @@ pub fn (l Set[T]) intersection(r Set[T]) Set[T] {
}
// difference returns the difference of sets.
[deprecated: 'use set1<T> - set2<T> instead']
[deprecated: 'use set1[T] - set2[T] instead']
pub fn (l Set[T]) difference(r Set[T]) Set[T] {
return l - r
}

View File

@ -678,7 +678,7 @@ fn test_uname() {
assert u.machine.len > 0
}
// tests for write_file_array and read_file_array<T>:
// tests for write_file_array and read_file_array[T]:
const maxn = 3
struct IntPoint {

View File

@ -2005,7 +2005,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
return typ
}
// Foo<U>{ bar: U } to Foo<T>{ bar: T }
// Foo[U]{ bar: U } to Foo[T]{ bar: T }
pub fn (mut t Table) replace_generic_type(typ Type, generic_types []Type) {
mut ts := t.sym(typ)
match mut ts.info {

View File

@ -260,11 +260,11 @@ fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, lan
expected_typ_sym := c.table.sym(expected_)
// Check on Generics types, there are some case where we have the following case
// `&Type<int> == &Type<>`. This is a common case we are implementing a function
// with generic parameters like `compare(bst Bst<T> node) {}`
// `&Type[int] == &Type[]`. This is a common case we are implementing a function
// with generic parameters like `compare(bst Bst[T] node) {}`
if got_typ_sym.symbol_name_except_generic() == expected_typ_sym.symbol_name_except_generic() {
// Check if we are making a comparison between two different types of
// the same type like `Type<int> and &Type<>`
// the same type like `Type[int] and &Type[]`
if (got.is_ptr() != expected.is_ptr())
|| !c.check_same_module(got, expected)
|| (!got.is_ptr() && !expected.is_ptr()

View File

@ -497,11 +497,11 @@ fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) {
} else if mut sym.info is ast.Struct {
if sym.info.is_generic {
if !variant.typ.has_flag(.generic) {
c.error('generic struct `${sym.name}` must specify generic type names, e.g. Foo<T>',
c.error('generic struct `${sym.name}` must specify generic type names, e.g. Foo[T]',
variant.pos)
}
if node.generic_types.len == 0 {
c.error('generic sumtype `${node.name}` must specify generic type names, e.g. Foo<T>',
c.error('generic sumtype `${node.name}` must specify generic type names, e.g. Foo[T]',
node.name_pos)
} else {
for typ in sym.info.generic_types {

View File

@ -17,10 +17,10 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
if elem_info.generic_types.len > 0 && elem_info.concrete_types.len == 0
&& !node.elem_type.has_flag(.generic) {
if c.table.cur_concrete_types.len == 0 {
c.error('generic struct must specify type parameter, e.g. Foo<int>',
c.error('generic struct must specify type parameter, e.g. Foo[int]',
node.elem_type_pos)
} else {
c.error('generic struct must specify type parameter, e.g. Foo<T>',
c.error('generic struct must specify type parameter, e.g. Foo[T]',
node.elem_type_pos)
}
}
@ -29,10 +29,10 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
if elem_info.generic_types.len > 0 && elem_info.concrete_types.len == 0
&& !node.elem_type.has_flag(.generic) {
if c.table.cur_concrete_types.len == 0 {
c.error('generic interface must specify type parameter, e.g. Foo<int>',
c.error('generic interface must specify type parameter, e.g. Foo[int]',
node.elem_type_pos)
} else {
c.error('generic interface must specify type parameter, e.g. Foo<T>',
c.error('generic interface must specify type parameter, e.g. Foo[T]',
node.elem_type_pos)
}
}
@ -41,10 +41,10 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
if elem_info.generic_types.len > 0 && elem_info.concrete_types.len == 0
&& !node.elem_type.has_flag(.generic) {
if c.table.cur_concrete_types.len == 0 {
c.error('generic sumtype must specify type parameter, e.g. Foo<int>',
c.error('generic sumtype must specify type parameter, e.g. Foo[int]',
node.elem_type_pos)
} else {
c.error('generic sumtype must specify type parameter, e.g. Foo<T>',
c.error('generic sumtype must specify type parameter, e.g. Foo[T]',
node.elem_type_pos)
}
}
@ -307,10 +307,10 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
if val_info.generic_types.len > 0 && val_info.concrete_types.len == 0
&& !info.value_type.has_flag(.generic) {
if c.table.cur_concrete_types.len == 0 {
c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. Foo<int>',
c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. Foo[int]',
node.pos)
} else {
c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. Foo<T>',
c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. Foo[T]',
node.pos)
}
}

View File

@ -76,11 +76,11 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
}
if need_generic_names {
if node.is_method {
c.add_error_detail('use `fn (r SomeType<T>) foo<T>() {`, not just `fn (r SomeType<T>) foo() {`')
c.add_error_detail('use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`')
c.error('generic method declaration must specify generic type names',
node.pos)
} else {
c.add_error_detail('use `fn foo<T>(x T) {`, not just `fn foo(x T) {`')
c.add_error_detail('use `fn foo[T](x T) {`, not just `fn foo(x T) {`')
c.error('generic function declaration must specify generic type names',
node.pos)
}
@ -105,7 +105,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
gs := c.table.sym(node.return_type)
if gs.info is ast.Struct {
if gs.info.is_generic && !node.return_type.has_flag(.generic) {
c.error('return generic struct in fn declaration must specify the generic type names, e.g. Foo<T>',
c.error('return generic struct in fn declaration must specify the generic type names, e.g. Foo[T]',
node.return_type_pos)
}
}
@ -136,7 +136,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
for name in generic_names {
if name !in node.generic_names {
fn_generic_names := node.generic_names.join(', ')
c.error('generic type name `${name}` is not mentioned in fn `${node.name}<${fn_generic_names}>`',
c.error('generic type name `${name}` is not mentioned in fn `${node.name}[${fn_generic_names}]`',
node.return_type_pos)
}
}
@ -224,19 +224,19 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
}
if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic)
&& arg_typ_sym.info.concrete_types.len == 0 {
c.error('generic struct in fn declaration must specify the generic type names, e.g. Foo<T>',
c.error('generic struct in fn declaration must specify the generic type names, e.g. Foo[T]',
param.type_pos)
}
} else if arg_typ_sym.info is ast.Interface {
if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic)
&& arg_typ_sym.info.concrete_types.len == 0 {
c.error('generic interface in fn declaration must specify the generic type names, e.g. Foo<T>',
c.error('generic interface in fn declaration must specify the generic type names, e.g. Foo[T]',
param.type_pos)
}
} else if arg_typ_sym.info is ast.SumType {
if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic)
&& arg_typ_sym.info.concrete_types.len == 0 {
c.error('generic sumtype in fn declaration must specify the generic type names, e.g. Foo<T>',
c.error('generic sumtype in fn declaration must specify the generic type names, e.g. Foo[T]',
param.type_pos)
}
}
@ -247,7 +247,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
for name in generic_names {
if name !in node.generic_names {
fn_generic_names := node.generic_names.join(', ')
c.error('generic type name `${name}` is not mentioned in fn `${node.name}<${fn_generic_names}>`',
c.error('generic type name `${name}` is not mentioned in fn `${node.name}[${fn_generic_names}]`',
param.type_pos)
}
}
@ -439,7 +439,7 @@ fn (mut c Checker) anon_fn(mut node ast.AnonFn) ast.Type {
c.stmts(node.decl.stmts)
c.fn_decl(mut node.decl)
if has_generic && node.decl.generic_names.len == 0 {
c.error('generic closure fn must specify type parameter, e.g. fn [foo] <T>()',
c.error('generic closure fn must specify type parameter, e.g. fn [foo] [T]()',
node.decl.pos)
}
return node.typ
@ -551,7 +551,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
if fn_name == 'main' {
c.error('the `main` function cannot be called in the program', node.pos)
}
mut has_generic := false // foo<T>() instead of foo<int>()
mut has_generic := false // foo[T]() instead of foo[int]()
mut concrete_types := []ast.Type{}
node.concrete_types = node.raw_concrete_types
for concrete_type in node.concrete_types {
@ -593,7 +593,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
typ := c.expr(node.args[0].expr)
tsym := c.table.sym(typ)
if !tsym.name.starts_with('Promise<') {
if !tsym.name.starts_with('Promise[') {
c.error('JS.await: first argument must be a promise, got `${tsym.name}`',
node.pos)
return ast.void_type
@ -918,7 +918,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
c.ensure_type_exists(concrete_type, node.concrete_list_pos) or {}
}
if func.generic_names.len > 0 && node.args.len == 0 && node.concrete_types.len == 0 {
c.error('no argument generic function must add concrete types, e.g. foo<int>()',
c.error('no argument generic function must add concrete types, e.g. foo[int]()',
node.pos)
return func.return_type
}
@ -1382,7 +1382,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
}
} else if final_left_sym.info is ast.Array && method_name in ['first', 'last', 'pop'] {
return c.array_builtin_method_call(mut node, left_type, final_left_sym)
} else if c.pref.backend.is_js() && left_sym.name.starts_with('Promise<')
} else if c.pref.backend.is_js() && left_sym.name.starts_with('Promise[')
&& method_name == 'wait' {
info := left_sym.info as ast.Struct
if node.args.len > 0 {
@ -1455,7 +1455,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
}
}
if has_method {
// x is Bar<T>, x.foo() -> x.foo<T>()
// x is Bar[T], x.foo() -> x.foo[T]()
rec_sym := c.table.final_sym(node.left_type)
rec_is_generic := left_type.has_flag(.generic)
mut rec_concrete_types := []ast.Type{}

View File

@ -211,7 +211,7 @@ fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
}
}
if node.generic_types.len == 0 && has_generic_types {
c.error('generic interface declaration must specify the generic type names, e.g. Foo<T>',
c.error('generic interface declaration must specify the generic type names, e.g. Foo[T]',
node.pos)
}
}

View File

@ -1,11 +1,11 @@
vlib/v/checker/tests/array_of_generic_struct_init_err.vv:6:6: warning: unused variable: `arr`
4 |
4 |
5 | fn main() {
6 | mut arr := []Item{}
| ~~~
7 | }
vlib/v/checker/tests/array_of_generic_struct_init_err.vv:6:15: error: generic struct must specify type parameter, e.g. Foo<int>
4 |
vlib/v/checker/tests/array_of_generic_struct_init_err.vv:6:15: error: generic struct must specify type parameter, e.g. Foo[int]
4 |
5 | fn main() {
6 | mut arr := []Item{}
| ~~~~

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generic_closure_fn_decl_err.vv:5:2: error: generic closure fn must specify type parameter, e.g. fn [foo] <T>()
vlib/v/checker/tests/generic_closure_fn_decl_err.vv:5:2: error: generic closure fn must specify type parameter, e.g. fn [foo] [T]()
3 |
4 | pub fn (mut app App) register<T>(service T) {
5 | fn [service] () {

View File

@ -1,32 +1,32 @@
vlib/v/checker/tests/generic_fn_decl_err.vv:19:29: error: generic type name `P` is not mentioned in fn `create1<U>`
vlib/v/checker/tests/generic_fn_decl_err.vv:19:29: error: generic type name `P` is not mentioned in fn `create1[U]`
17 | }
18 |
19 | fn (r Db) create1<U>(u U, p P) {
| ^
20 | println('Yo')
21 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:23:29: error: generic type name `P` is not mentioned in fn `create2<U>`
vlib/v/checker/tests/generic_fn_decl_err.vv:23:29: error: generic type name `P` is not mentioned in fn `create2[U]`
21 | }
22 |
23 | fn (r Db) create2<U>(u U, p &P) {
| ~~
24 | println('Yo')
25 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:27:29: error: generic type name `P` is not mentioned in fn `create3<U>`
vlib/v/checker/tests/generic_fn_decl_err.vv:27:29: error: generic type name `P` is not mentioned in fn `create3[U]`
25 | }
26 |
27 | fn (r Db) create3<U>(u U, p []P) {
| ~~~
28 | println('Yo')
29 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:31:27: error: generic type name `P` is not mentioned in fn `create4<U>`
vlib/v/checker/tests/generic_fn_decl_err.vv:31:27: error: generic type name `P` is not mentioned in fn `create4[U]`
29 | }
30 |
31 | fn (r Db) create4<U>(u U) P {
| ^
32 | return P{}
33 | }
vlib/v/checker/tests/generic_fn_decl_err.vv:35:27: error: generic type name `P` is not mentioned in fn `create5<U>`
vlib/v/checker/tests/generic_fn_decl_err.vv:35:27: error: generic type name `P` is not mentioned in fn `create5[U]`
33 | }
34 |
35 | fn (r Db) create5<U>(u U) []P {

View File

@ -1,24 +1,24 @@
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:26:1: error: generic function declaration must specify generic type names
24 | }
25 |
25 |
26 | fn g_worker(g Generic<T>) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~
27 | t := <-g.ch
28 | handle(t)
Details: use `fn foo<T>(x T) {`, not just `fn foo(x T) {`
Details: use `fn foo[T](x T) {`, not just `fn foo(x T) {`
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:32:1: error: generic function declaration must specify generic type names
30 | }
31 |
31 |
32 | fn handle(t T) {
| ~~~~~~~~~~~~~~
33 | println('hi')
34 | }
Details: use `fn foo<T>(x T) {`, not just `fn foo(x T) {`
Details: use `fn foo[T](x T) {`, not just `fn foo(x T) {`
vlib/v/checker/tests/generic_fn_decl_without_generic_names_err.vv:40:1: error: generic method declaration must specify generic type names
38 | type MayBe<T> = None | T
39 |
39 |
40 | fn (m MayBe<T>) is_some() bool {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41 | return m is T
42 | }
Details: use `fn (r SomeType<T>) foo<T>() {`, not just `fn (r SomeType<T>) foo() {`
Details: use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generic_interface_missing_type_names_err.vv:16:17: error: generic interface must specify type parameter, e.g. Foo<int>
vlib/v/checker/tests/generic_interface_missing_type_names_err.vv:16:17: error: generic interface must specify type parameter, e.g. Foo[int]
14 |
15 | fn main() {
16 | mut outs := []Output{}

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generic_sumtype_decl_err_a.vv:7:24: error: generic struct `Just` must specify generic type names, e.g. Foo<T>
vlib/v/checker/tests/generic_sumtype_decl_err_a.vv:7:24: error: generic struct `Just` must specify generic type names, e.g. Foo[T]
5 | struct Nothing {}
6 |
7 | type Maybe = Nothing | Just

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generic_sumtype_decl_err_b.vv:7:6: error: generic sumtype `Maybe` must specify generic type names, e.g. Foo<T>
vlib/v/checker/tests/generic_sumtype_decl_err_b.vv:7:6: error: generic sumtype `Maybe` must specify generic type names, e.g. Foo[T]
5 | struct Nothing {}
6 |
7 | type Maybe = Nothing | Just<T>

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generics_fn_arg_type_err.vv:14:23: error: generic interface in fn declaration must specify the generic type names, e.g. Foo<T>
vlib/v/checker/tests/generics_fn_arg_type_err.vv:14:23: error: generic interface in fn declaration must specify the generic type names, e.g. Foo[T]
12 | }
13 |
14 | fn do_list_thing(list List) { // <--- Error here

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generics_fn_called_no_arg_err.vv:13:10: error: no argument generic function must add concrete types, e.g. foo<int>()
vlib/v/checker/tests/generics_fn_called_no_arg_err.vv:13:10: error: no argument generic function must add concrete types, e.g. foo[int]()
11 |
12 | fn main() {
13 | q := new_queue()

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:13:32: error: return generic struct in fn declaration must specify the generic type names, e.g. Foo<T>
vlib/v/checker/tests/generics_fn_return_generic_struct_err.vv:13:32: error: return generic struct in fn declaration must specify the generic type names, e.g. Foo[T]
11 | }
12 |
13 | pub fn new_channel_struct[T]() GenericChannelStruct {

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generics_interface_declaration_err.vv:1:1: error: generic interface declaration must specify the generic type names, e.g. Foo<T>
vlib/v/checker/tests/generics_interface_declaration_err.vv:1:1: error: generic interface declaration must specify the generic type names, e.g. Foo[T]
1 | interface Expr {
| ~~~~~~~~~~~~~~~~
2 | accept(v Visitor<R>) R

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/generics_method_receiver_type_err.vv:6:11: error: generic struct in fn declaration must specify the generic type names, e.g. Foo<T>
vlib/v/checker/tests/generics_method_receiver_type_err.vv:6:11: error: generic struct in fn declaration must specify the generic type names, e.g. Foo[T]
4 | }
5 |
6 | pub fn (x Node) str() string {

View File

@ -1,11 +1,11 @@
vlib/v/checker/tests/map_of_generic_struct_init_err.vv:6:6: warning: unused variable: `m`
4 |
4 |
5 | fn main() {
6 | mut m := map[string]Item{}
| ^
7 | }
vlib/v/checker/tests/map_of_generic_struct_init_err.vv:6:11: error: generic struct `Item` must specify type parameter, e.g. Foo<int>
4 |
vlib/v/checker/tests/map_of_generic_struct_init_err.vv:6:11: error: generic struct `Item` must specify type parameter, e.g. Foo[int]
4 |
5 | fn main() {
6 | mut m := map[string]Item{}
| ~~~~~~~~~~~~~~~~~

View File

@ -251,7 +251,7 @@ pub fn (mut f Gen) mark_types_import_as_used(typ ast.Type) {
f.mark_types_import_as_used(concrete_typ)
}
}
name := sym.name.split('<')[0] // take `Type` from `Type<T>`
name := sym.name.split('[')[0] // take `Type` from `Type[T]`
f.mark_import_as_used(name)
}

View File

@ -333,7 +333,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
scope: 0
}
}
// <T>
// [T]
_, mut generic_names := p.parse_generic_types()
// generic names can be infer with receiver's generic names
if is_method && rec.typ.has_flag(.generic) {

View File

@ -22,7 +22,7 @@ fn test_fn_variadic() {
/*
// QTODO
// generic
fn variadic_test_generic<T>(a int, b ...T) T {
fn variadic_test_generic[T](a int, b ...T) T {
b1 := b[0]
b2 := b[1]
return '$a $b1 $b2'

View File

@ -202,7 +202,7 @@ fn map_f[T, U](l []T, f fn (T) U) []U {
}
/*
fn foldl<T>(l []T, nil T, f fn(T,T)T) T {
fn foldl[T](l []T, nil T, f fn(T,T)T) T {
mut r := nil
for e in l {
r = f(r, e)
@ -302,8 +302,8 @@ pub mut:
}
// TODO: multiple type generic struct needs fixing in return for fn
// fn new_repo<T>(db DB) Repo<T,U> {
// return Repo<T,Permission>{db: db}
// fn new_repo[T](db DB) Repo[T,U] {
// return Repo[T,Permission]{db: db}
// }
fn test_generic_struct() {
mut a := Repo[User, Permission]{
@ -474,7 +474,6 @@ fn test_generic_init() {
}
fn return_one[T](rec int, useless T) T {
// foo < bar<T>() should work
if rec == 0 || 0 < return_one[T](rec - 1, useless) {
return T(1)
}