diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2b885fb15f..d1311af330 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1825,6 +1825,13 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { if !c.check_types(arg_type, info.elem_type) && !c.check_types(left_type, arg_type) { c.error('cannot $method_name `$arg_sym.name` to `$left_type_sym.name`', arg_expr.position()) } + } else if c.table.get_final_type_symbol(left_type).kind == .array + && method_name in ['first', 'last', 'pop'] { + info := c.table.get_final_type_symbol(left_type).info + if info is ast.Array { + call_expr.return_type = info.elem_type + return info.elem_type + } } else if left_type_sym.kind == .thread && method_name == 'wait' { info := left_type_sym.info as ast.Thread if call_expr.args.len > 0 { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 7243cf47b5..cf722d21c9 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -558,6 +558,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) { return } left_sym := g.table.get_type_symbol(node.left_type) + final_left_sym := g.table.get_final_type_symbol(node.left_type) if left_sym.kind == .array { match node.name { 'filter' { @@ -645,16 +646,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) { if left_sym.kind == .map && node.name in ['clone', 'move'] { receiver_type_name = 'map' } - // TODO performance, detect `array` method differently - if left_sym.kind == .array + if final_left_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'pop', 'clone', 'reverse', 'slice', 'pointers'] { - // && rec_sym.name == 'array' { - // && rec_sym.name == 'array' && receiver_name.starts_with('array') { - // `array_byte_clone` => `array_clone` - receiver_type_name = 'array' - if false && node.name == 'free' && typ_sym.has_method(node.name) { - // TODO: allow for more specific overrides of array .free() like `pub fn (x []string) free() {` - receiver_type_name = g.typ(unwrapped_rec_type).trim('*') + if !(left_sym.info is ast.Alias && typ_sym.has_method(node.name)) { + // `array_Xyz_clone` => `array_clone` + receiver_type_name = 'array' } if node.name in ['last', 'first', 'pop'] { return_type_str := g.typ(node.return_type) diff --git a/vlib/v/tests/aliased_array_operations_test.v b/vlib/v/tests/aliased_array_operations_test.v new file mode 100644 index 0000000000..971ddfc595 --- /dev/null +++ b/vlib/v/tests/aliased_array_operations_test.v @@ -0,0 +1,16 @@ +type Ints = []int + +fn test_first() { + ints := Ints([5, 10]) + assert ints.first() == 5 +} + +fn test_last() { + ints := Ints([7, 4]) + assert ints.last() == 4 +} + +fn test_index() { + ints := Ints([1, 5, 2, 3]) + assert ints[2] == 2 +}