From 47aa2b1f93627ca78d72b7b4e4c3447740babab4 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 1 Dec 2021 09:50:53 +0200 Subject: [PATCH] all: fix casting of `string(MyString('abc'))` and `byte(MyByte(123))`; improve TypeSymbol handling (#12617) --- vlib/strings/builder.js.v | 2 +- vlib/v/ast/table.v | 135 +++++----- vlib/v/checker/checker.v | 153 ++++++------ vlib/v/checker/tests/bool_string_cast_err.out | 4 +- vlib/v/checker/tests/cast_string_err.out | 2 +- .../tests/cast_string_with_byte_err.out | 4 +- vlib/v/checker/tests/struct_type_cast_err.out | 20 +- vlib/v/gen/c/cgen.v | 234 ++++++++---------- vlib/v/gen/native/gen.v | 2 +- vlib/v/tests/alias_basic_types_test.v | 66 +++++ vlib/v/token/position.v | 4 + 11 files changed, 348 insertions(+), 278 deletions(-) create mode 100644 vlib/v/tests/alias_basic_types_test.v diff --git a/vlib/strings/builder.js.v b/vlib/strings/builder.js.v index a2cc91854f..356f01516a 100644 --- a/vlib/strings/builder.js.v +++ b/vlib/strings/builder.js.v @@ -92,7 +92,7 @@ pub fn (mut b Builder) cut_to(pos int) string { pub fn (mut b Builder) write_runes(runes []rune) { for r in runes { - res := string(r) + res := r.str() #res.str = String.fromCharCode(r.val) b << res.bytes() } diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 47ec5c9f8f..dd9eaa3436 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -10,7 +10,7 @@ import v.util [heap] pub struct Table { pub mut: - type_symbols []TypeSymbol + type_symbols []&TypeSymbol type_idxs map[string]int fns map[string]Fn iface_types map[string][]Type @@ -42,8 +42,11 @@ pub mut: // used by vls to avoid leaks // TODO remove manual memory management [unsafe] -pub fn (t &Table) free() { +pub fn (mut t Table) free() { unsafe { + for s in t.type_symbols { + s.free() + } t.type_symbols.free() t.type_idxs.free() t.fns.free() @@ -169,7 +172,6 @@ fn (p []Param) equals(o []Param) bool { pub fn new_table() &Table { mut t := &Table{ - type_symbols: []TypeSymbol{cap: 64000} global_scope: &Scope{ parent: 0 } @@ -348,7 +350,7 @@ pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn { if ts.parent_idx == 0 { break } - ts = unsafe { &t.type_symbols[ts.parent_idx] } + ts = t.type_symbols[ts.parent_idx] } return none } @@ -490,7 +492,7 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField { if ts.parent_idx == 0 { break } - ts = unsafe { &t.type_symbols[ts.parent_idx] } + ts = t.type_symbols[ts.parent_idx] } return none } @@ -625,7 +627,7 @@ pub fn (t &Table) find_type_idx(name string) int { } [inline] -pub fn (t &Table) find_type(name string) ?TypeSymbol { +pub fn (t &Table) find_type(name string) ?&TypeSymbol { idx := t.type_idxs[name] if idx > 0 { return t.type_symbols[idx] @@ -634,6 +636,7 @@ pub fn (t &Table) find_type(name string) ?TypeSymbol { } pub const invalid_type_symbol = &TypeSymbol{ + idx: -1 parent_idx: -1 language: .v mod: 'builtin' @@ -643,10 +646,14 @@ pub const invalid_type_symbol = &TypeSymbol{ } [inline] +pub fn (t &Table) get_type_symbol_by_idx(idx int) &TypeSymbol { + return t.type_symbols[idx] +} + pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { idx := typ.idx() if idx > 0 { - return unsafe { &t.type_symbols[idx] } + return t.type_symbols[idx] } // this should never happen t.panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`. @@ -659,11 +666,11 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol { mut idx := typ.idx() if idx > 0 { - current_type := t.type_symbols[idx] - if current_type.kind == .alias { - idx = (current_type.info as Alias).parent_type.idx() + current_symbol := t.type_symbols[idx] + if current_symbol.kind == .alias { + idx = (current_symbol.info as Alias).parent_type.idx() } - return unsafe { &t.type_symbols[idx] } + return t.type_symbols[idx] } // this should never happen t.panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.') @@ -672,8 +679,8 @@ pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol { [inline] pub fn (t &Table) get_type_name(typ Type) string { - typ_sym := t.get_type_symbol(typ) - return typ_sym.name + sym := t.get_type_symbol(typ) + return sym.name } [inline] @@ -688,38 +695,36 @@ pub fn (t &Table) unalias_num_type(typ Type) Type { return typ } -fn (mut t Table) check_for_already_registered_symbol(typ TypeSymbol, existing_idx int) int { - ex_type := t.type_symbols[existing_idx] - match ex_type.kind { - .placeholder { - // override placeholder - t.type_symbols[existing_idx] = TypeSymbol{ - ...typ - methods: ex_type.methods - } - return existing_idx - } - else { - // builtin - // this will override the already registered builtin types - // with the actual v struct declaration in the source - if (existing_idx >= string_type_idx && existing_idx <= map_type_idx) - || existing_idx == error_type_idx { - if existing_idx == string_type_idx { - // existing_type := t.type_symbols[existing_idx] - t.type_symbols[existing_idx] = TypeSymbol{ - ...typ - kind: ex_type.kind - } - } else { - t.type_symbols[existing_idx] = typ - } - return existing_idx - } - return -1 +fn (mut t Table) rewrite_already_registered_symbol(typ TypeSymbol, existing_idx int) int { + existing_symbol := t.type_symbols[existing_idx] + if existing_symbol.kind == .placeholder { + // override placeholder + t.type_symbols[existing_idx] = &TypeSymbol{ + ...typ + methods: existing_symbol.methods } + return existing_idx } - return -2 + // Override the already registered builtin types with the actual + // v struct declarations in the vlib/builtin module sources: + if (existing_idx >= string_type_idx && existing_idx <= map_type_idx) + || existing_idx == error_type_idx { + if existing_idx == string_type_idx { + // existing_type := t.type_symbols[existing_idx] + unsafe { + *existing_symbol = &TypeSymbol{ + ...typ + kind: existing_symbol.kind + } + } + } else { + t.type_symbols[existing_idx] = &TypeSymbol{ + ...typ + } + } + return existing_idx + } + return -1 } [inline] @@ -727,7 +732,7 @@ pub fn (mut t Table) register_type_symbol(sym TypeSymbol) int { mut idx := -2 mut existing_idx := t.type_idxs[sym.name] if existing_idx > 0 { - idx = t.check_for_already_registered_symbol(sym, existing_idx) + idx = t.rewrite_already_registered_symbol(sym, existing_idx) if idx != -2 { return idx } @@ -735,14 +740,16 @@ pub fn (mut t Table) register_type_symbol(sym TypeSymbol) int { if sym.mod == 'main' { existing_idx = t.type_idxs[sym.name.trim_prefix('main.')] if existing_idx > 0 { - idx = t.check_for_already_registered_symbol(sym, existing_idx) + idx = t.rewrite_already_registered_symbol(sym, existing_idx) if idx != -2 { return idx } } } idx = t.type_symbols.len - t.type_symbols << sym + t.type_symbols << &TypeSymbol{ + ...sym + } t.type_symbols[idx].idx = idx t.type_idxs[sym.name] = idx return idx @@ -1088,31 +1095,31 @@ pub fn (mut t Table) add_placeholder_type(name string, language Language) int { [inline] pub fn (t &Table) value_type(typ Type) Type { - typ_sym := t.get_final_type_symbol(typ) + sym := t.get_final_type_symbol(typ) if typ.has_flag(.variadic) { // ...string => string // return typ.clear_flag(.variadic) - array_info := typ_sym.info as Array + array_info := sym.info as Array return array_info.elem_type } - if typ_sym.kind == .array { + if sym.kind == .array { // Check index type - info := typ_sym.info as Array + info := sym.info as Array return info.elem_type } - if typ_sym.kind == .array_fixed { - info := typ_sym.info as ArrayFixed + if sym.kind == .array_fixed { + info := sym.info as ArrayFixed return info.elem_type } - if typ_sym.kind == .map { - info := typ_sym.info as Map + if sym.kind == .map { + info := sym.info as Map return info.value_type } - if typ_sym.kind == .string && typ.is_ptr() { + if sym.kind == .string && typ.is_ptr() { // (&string)[i] => string return string_type } - if typ_sym.kind in [.byteptr, .string] { + if sym.kind in [.byteptr, .string] { return byte_type } if typ.is_ptr() { @@ -1277,18 +1284,18 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool { // `none` "implements" the Error interface return true } - typ_sym := t.get_type_symbol(typ) - if typ_sym.language != .v { + sym := t.get_type_symbol(typ) + if sym.language != .v { return false } // generic struct don't generate cast interface fn - if typ_sym.info is Struct { - if typ_sym.info.is_generic { + if sym.info is Struct { + if sym.info.is_generic { return false } } mut inter_sym := t.get_type_symbol(inter_typ) - if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ { + if sym.kind == .interface_ && inter_sym.kind == .interface_ { return false } if mut inter_sym.info is Interface { @@ -1306,7 +1313,7 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool { } // verify methods for imethod in inter_sym.info.methods { - if method := typ_sym.find_method(imethod.name) { + if method := sym.find_method(imethod.name) { msg := t.is_same_method(imethod, method) if msg.len > 0 { return false @@ -1320,13 +1327,13 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool { if ifield.typ == voidptr_type { // Allow `voidptr` fields in interfaces for now. (for example // to enable .db check in vweb) - if t.struct_has_field(typ_sym, ifield.name) { + if t.struct_has_field(sym, ifield.name) { continue } else { return false } } - if field := t.find_field_with_embeds(typ_sym, ifield.name) { + if field := t.find_field_with_embeds(sym, ifield.name) { if ifield.typ != field.typ { return false } else if ifield.is_mut && !(field.is_mut || field.is_global) { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index daeeeeba39..54d8cef089 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -664,7 +664,7 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) { if node.language == .v && !c.is_builtin_mod { c.check_valid_pascal_case(node.name, 'struct name', node.pos) } - mut struct_sym := c.table.find_type(node.name) or { ast.TypeSymbol{} } + mut struct_sym := c.table.find_type(node.name) or { ast.invalid_type_symbol } mut has_generic_types := false if mut struct_sym.info is ast.Struct { for embed in node.embeds { @@ -5655,77 +5655,93 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type { // } pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { + // Given: `Outside( Inside(xyz) )`, + // node.expr_type: `Inside` + // node.typ: `Outside` node.expr_type = c.expr(node.expr) // type to be casted - from_type_sym := c.table.get_type_symbol(node.expr_type) - to_type_sym := c.table.get_type_symbol(node.typ) // type to be used as cast - + mut from_type := node.expr_type + to_type := node.typ + // + from_type_sym := c.table.get_type_symbol(from_type) + from_type_sym_final := c.table.get_final_type_symbol(from_type) + to_type_sym := c.table.get_type_symbol(to_type) // type to be used as cast + to_type_sym_final := c.table.get_final_type_symbol(to_type) + // if (to_type_sym.is_number() && from_type_sym.name == 'JS.Number') || (to_type_sym.is_number() && from_type_sym.name == 'JS.BigInt') || (to_type_sym.is_string() && from_type_sym.name == 'JS.String') - || (node.typ.is_bool() && from_type_sym.name == 'JS.Boolean') - || (node.expr_type.is_bool() && to_type_sym.name == 'JS.Boolean') + || (to_type.is_bool() && from_type_sym.name == 'JS.Boolean') + || (from_type.is_bool() && to_type_sym.name == 'JS.Boolean') || (from_type_sym.is_number() && to_type_sym.name == 'JS.Number') || (from_type_sym.is_number() && to_type_sym.name == 'JS.BigInt') || (from_type_sym.is_string() && to_type_sym.name == 'JS.String') { - return node.typ + return to_type } if to_type_sym.language != .c { - c.ensure_type_exists(node.typ, node.pos) or {} + c.ensure_type_exists(to_type, node.pos) or {} } - if from_type_sym.kind == .byte && node.expr_type.is_ptr() && to_type_sym.kind == .string - && !node.typ.is_ptr() { + if from_type_sym.kind == .byte && from_type.is_ptr() && to_type_sym.kind == .string + && !to_type.is_ptr() { c.error('to convert a C string buffer pointer to a V string, use x.vstring() instead of string(x)', node.pos) } - if node.expr_type == ast.void_type { + if from_type == ast.void_type { c.error('expression does not return a value so it cannot be cast', node.expr.position()) } - if node.expr_type == ast.byte_type && to_type_sym.kind == .string { - c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.', - node.pos) - } - if to_type_sym.kind == .sum_type { - if node.expr_type in [ast.int_literal_type, ast.float_literal_type] { - node.expr_type = c.promote_num(node.expr_type, if node.expr_type == ast.int_literal_type { - ast.int_type - } else { - ast.f64_type - }) + // + if to_type == ast.string_type { + if from_type in [ast.byte_type, ast.bool_type] { + c.error('cannot cast type `$from_type_sym.name` to string, use `${node.expr.str()}.str()` instead.', + node.pos) } - if !c.table.sumtype_has_variant(node.typ, node.expr_type) && !node.typ.has_flag(.optional) { + if from_type.is_real_pointer() { + c.error('cannot cast pointer type `$from_type_sym.name` to string, use `&byte($node.expr.str()).vstring()` instead.', + node.pos) + } + if from_type.is_number() { + c.error('cannot cast number to string, use `${node.expr.str()}.str()` instead.', + node.pos) + } + if from_type_sym.kind == .alias && from_type_sym_final.name != 'string' { + c.error('cannot cast type `$from_type_sym.name` to string, use `x.str()` instead', + node.pos) + } + } + // + if to_type_sym.kind == .sum_type { + 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) + from_type = node.expr_type + } + if !c.table.sumtype_has_variant(to_type, from_type) && !to_type.has_flag(.optional) { c.error('cannot cast `$from_type_sym.name` to `$to_type_sym.name`', node.pos) } } else if mut to_type_sym.info is ast.Alias { - if !c.check_types(node.expr_type, to_type_sym.info.parent_type) { - parent_type_sym := c.table.get_type_symbol(to_type_sym.info.parent_type) - c.error('cannot convert type `$from_type_sym.name` to `$to_type_sym.name` (alias to `$parent_type_sym.name`)', + if !c.check_types(from_type, to_type_sym.info.parent_type) { + c.error('cannot convert type `$from_type_sym.name` to `$to_type_sym.name` (alias to `$to_type_sym_final.name`)', node.pos) } - } else if node.typ == ast.string_type - && (from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool] - || (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) { - type_name := c.table.type_to_str(node.expr_type) - c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos) - } else if node.expr_type == ast.string_type { - if to_type_sym.kind != .alias { - mut error_msg := 'cannot cast a string' - if mut node.expr is ast.StringLiteral { - if node.expr.val.len == 1 { - error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'" - } + } else if to_type != ast.string_type && from_type == ast.string_type + && (!(to_type_sym.kind == .alias && to_type_sym_final.name == 'string')) { + mut error_msg := 'cannot cast a string to a type `$to_type_sym_final.name`, that is not an alias of string' + if mut node.expr is ast.StringLiteral { + if node.expr.val.len == 1 { + error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'" } - c.error(error_msg, node.pos) } - } else if to_type_sym.kind == .byte && node.expr_type != ast.voidptr_type - && from_type_sym.kind != .enum_ && !node.expr_type.is_int() && !node.expr_type.is_float() - && node.expr_type != ast.bool_type && !node.expr_type.is_ptr() { - type_name := c.table.type_to_str(node.expr_type) + c.error(error_msg, node.pos) + } else if to_type_sym.kind == .byte && from_type != ast.voidptr_type + && from_type_sym.kind != .enum_ && !from_type.is_int() && !from_type.is_float() + && from_type != ast.bool_type && !from_type.is_ptr() && from_type_sym.kind == .alias + && from_type_sym_final.name != 'byte' { + type_name := c.table.type_to_str(from_type) c.error('cannot cast type `$type_name` to `byte`', node.pos) - } else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() + } else if to_type_sym.kind == .struct_ && !to_type.is_ptr() && !(to_type_sym.info as ast.Struct).is_typedef { // For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard - if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { + if from_type_sym.kind == .struct_ && !from_type.is_ptr() { c.warn('casting to struct is deprecated, use e.g. `Struct{...expr}` instead', node.pos) from_type_info := from_type_sym.info as ast.Struct @@ -5735,40 +5751,37 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { node.pos) } } else { - type_name := c.table.type_to_str(node.expr_type) - // dump(node.typ) - // dump(node.expr_type) - // dump(type_name) - // dump(to_type_sym.debug()) + type_name := c.table.type_to_str(from_type) c.error('cannot cast `$type_name` to struct', node.pos) } } else if to_type_sym.kind == .interface_ { - if c.type_implements(node.expr_type, node.typ, node.pos) { - if !node.expr_type.is_ptr() && !node.expr_type.is_pointer() - && from_type_sym.kind != .interface_ && !c.inside_unsafe { + if c.type_implements(from_type, to_type, node.pos) { + if !from_type.is_ptr() && !from_type.is_pointer() && from_type_sym.kind != .interface_ + && !c.inside_unsafe { c.mark_as_referenced(mut &node.expr, true) } } - } else if node.typ == ast.bool_type && node.expr_type != ast.bool_type && !c.inside_unsafe { + } else if to_type == ast.bool_type && from_type != ast.bool_type && !c.inside_unsafe { c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos) - } else if node.expr_type == ast.none_type && !node.typ.has_flag(.optional) { - type_name := c.table.type_to_str(node.typ) + } else if from_type == ast.none_type && !to_type.has_flag(.optional) { + type_name := c.table.type_to_str(to_type) c.error('cannot cast `none` to `$type_name`', node.pos) - } else if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { - if (node.typ.is_ptr() || to_type_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod { - type_name := c.table.type_to_str(node.typ) - c.error('cannot cast struct to `$type_name`', node.pos) + } else if from_type_sym.kind == .struct_ && !from_type.is_ptr() { + if (to_type.is_ptr() || to_type_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod { + from_type_name := c.table.type_to_str(from_type) + type_name := c.table.type_to_str(to_type) + c.error('cannot cast struct `$from_type_name` to `$type_name`', node.pos) } - } else if node.expr_type.has_flag(.optional) || node.expr_type.has_flag(.variadic) { + } else if from_type.has_flag(.optional) || from_type.has_flag(.variadic) { // variadic case can happen when arrays are converted into variadic - msg := if node.expr_type.has_flag(.optional) { 'an optional' } else { 'a variadic' } + msg := if from_type.has_flag(.optional) { 'an optional' } else { 'a variadic' } c.error('cannot type cast $msg', node.pos) - } else if !c.inside_unsafe && node.typ.is_ptr() && node.expr_type.is_ptr() - && node.typ.deref() != ast.char_type && node.expr_type.deref() != ast.char_type { - ft := c.table.type_to_str(node.expr_type) - tt := c.table.type_to_str(node.typ) + } else if !c.inside_unsafe && to_type.is_ptr() && from_type.is_ptr() + && to_type.deref() != ast.char_type && from_type.deref() != ast.char_type { + ft := c.table.type_to_str(from_type) + tt := c.table.type_to_str(to_type) c.warn('casting `$ft` to `$tt` is only allowed in `unsafe` code', node.pos) - } else if from_type_sym.kind == .array_fixed && !node.expr_type.is_ptr() { + } else if from_type_sym.kind == .array_fixed && !from_type.is_ptr() { c.warn('cannot cast a fixed array (use e.g. `&arr[0]` instead)', node.pos) } if node.has_arg { @@ -5778,7 +5791,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { // checks on int literal to enum cast if the value represents a value on the enum if to_type_sym.kind == .enum_ { if node.expr is ast.IntegerLiteral { - enum_typ_name := c.table.get_type_name(node.typ) + enum_typ_name := c.table.get_type_name(to_type) node_val := (node.expr as ast.IntegerLiteral).val.int() if enum_decl := c.table.enum_decls[to_type_sym.name] { @@ -5807,9 +5820,9 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } } - node.typname = c.table.get_type_symbol(node.typ).name + node.typname = c.table.get_type_symbol(to_type).name - return node.typ + return to_type } fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { diff --git a/vlib/v/checker/tests/bool_string_cast_err.out b/vlib/v/checker/tests/bool_string_cast_err.out index 44a1643c87..eb55055a88 100644 --- a/vlib/v/checker/tests/bool_string_cast_err.out +++ b/vlib/v/checker/tests/bool_string_cast_err.out @@ -1,10 +1,10 @@ -vlib/v/checker/tests/bool_string_cast_err.vv:2:13: error: cannot cast type `bool` to string, use `x.str()` instead +vlib/v/checker/tests/bool_string_cast_err.vv:2:13: error: cannot cast type `bool` to string, use `true.str()` instead. 1 | fn main() { 2 | println(string(true)) | ~~~~~~~~~~~~ 3 | println(string(false)) 4 | } -vlib/v/checker/tests/bool_string_cast_err.vv:3:13: error: cannot cast type `bool` to string, use `x.str()` instead +vlib/v/checker/tests/bool_string_cast_err.vv:3:13: error: cannot cast type `bool` to string, use `false.str()` instead. 1 | fn main() { 2 | println(string(true)) 3 | println(string(false)) diff --git a/vlib/v/checker/tests/cast_string_err.out b/vlib/v/checker/tests/cast_string_err.out index 3c09bf4811..939aa1db24 100644 --- a/vlib/v/checker/tests/cast_string_err.out +++ b/vlib/v/checker/tests/cast_string_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/cast_string_err.vv:2:7: error: cannot cast type `int literal` to string, use `x.str()` instead +vlib/v/checker/tests/cast_string_err.vv:2:7: error: cannot cast number to string, use `1.str()` instead. 1 | fn main() { 2 | a := string(1) | ~~~~~~~~~ diff --git a/vlib/v/checker/tests/cast_string_with_byte_err.out b/vlib/v/checker/tests/cast_string_with_byte_err.out index 1b042184f2..7c60cf7e94 100644 --- a/vlib/v/checker/tests/cast_string_with_byte_err.out +++ b/vlib/v/checker/tests/cast_string_with_byte_err.out @@ -1,5 +1,5 @@ -vlib/v/checker/tests/cast_string_with_byte_err.vv:2:12: error: can not cast type `byte` to string, use `by.str()` instead. +vlib/v/checker/tests/cast_string_with_byte_err.vv:2:12: error: cannot cast type `byte` to string, use `by.str()` instead. 1 | for by in 'abc' { 2 | println(string(by)) | ~~~~~~~~~~ - 3 | } \ No newline at end of file + 3 | } diff --git a/vlib/v/checker/tests/struct_type_cast_err.out b/vlib/v/checker/tests/struct_type_cast_err.out index 4648a27f43..c693bedbb0 100644 --- a/vlib/v/checker/tests/struct_type_cast_err.out +++ b/vlib/v/checker/tests/struct_type_cast_err.out @@ -1,63 +1,63 @@ -vlib/v/checker/tests/struct_type_cast_err.vv:5:10: error: cannot cast struct to `string` +vlib/v/checker/tests/struct_type_cast_err.vv:5:10: error: cannot cast struct `Foo` to `string` 3 | fn main() { 4 | foo := Foo{} 5 | _ := string(foo) | ~~~~~~~~~~~ 6 | _ := int(foo) 7 | _ := u64(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:6:10: error: cannot cast struct to `int` +vlib/v/checker/tests/struct_type_cast_err.vv:6:10: error: cannot cast struct `Foo` to `int` 4 | foo := Foo{} 5 | _ := string(foo) 6 | _ := int(foo) | ~~~~~~~~ 7 | _ := u64(foo) 8 | _ := u32(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:7:10: error: cannot cast struct to `u64` +vlib/v/checker/tests/struct_type_cast_err.vv:7:10: error: cannot cast struct `Foo` to `u64` 5 | _ := string(foo) 6 | _ := int(foo) 7 | _ := u64(foo) | ~~~~~~~~ 8 | _ := u32(foo) 9 | _ := rune(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:8:10: error: cannot cast struct to `u32` +vlib/v/checker/tests/struct_type_cast_err.vv:8:10: error: cannot cast struct `Foo` to `u32` 6 | _ := int(foo) 7 | _ := u64(foo) 8 | _ := u32(foo) | ~~~~~~~~ 9 | _ := rune(foo) 10 | _ := byte(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:9:10: error: cannot cast struct to `rune` +vlib/v/checker/tests/struct_type_cast_err.vv:9:10: error: cannot cast struct `Foo` to `rune` 7 | _ := u64(foo) 8 | _ := u32(foo) 9 | _ := rune(foo) | ~~~~~~~~~ 10 | _ := byte(foo) 11 | _ := i8(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:10:10: error: cannot cast type `Foo` to `byte` +vlib/v/checker/tests/struct_type_cast_err.vv:10:10: error: cannot cast struct `Foo` to `byte` 8 | _ := u32(foo) 9 | _ := rune(foo) 10 | _ := byte(foo) | ~~~~~~~~~ 11 | _ := i8(foo) 12 | _ := i64(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:11:10: error: cannot cast struct to `i8` +vlib/v/checker/tests/struct_type_cast_err.vv:11:10: error: cannot cast struct `Foo` to `i8` 9 | _ := rune(foo) 10 | _ := byte(foo) 11 | _ := i8(foo) | ~~~~~~~ 12 | _ := i64(foo) 13 | _ := int(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:12:10: error: cannot cast struct to `i64` +vlib/v/checker/tests/struct_type_cast_err.vv:12:10: error: cannot cast struct `Foo` to `i64` 10 | _ := byte(foo) 11 | _ := i8(foo) 12 | _ := i64(foo) | ~~~~~~~~ 13 | _ := int(foo) 14 | _ = &I1(foo) -vlib/v/checker/tests/struct_type_cast_err.vv:13:10: error: cannot cast struct to `int` +vlib/v/checker/tests/struct_type_cast_err.vv:13:10: error: cannot cast struct `Foo` to `int` 11 | _ := i8(foo) 12 | _ := i64(foo) 13 | _ := int(foo) | ~~~~~~~~ 14 | _ = &I1(foo) - 15 | } \ No newline at end of file + 15 | } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e8ddd80db4..2e1819c8fd 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -378,18 +378,18 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { g.timers.start('cgen common') // to make sure type idx's are the same in cached mods if g.pref.build_mode == .build_module { - for idx, typ in g.table.type_symbols { + for idx, sym in g.table.type_symbols { if idx == 0 { continue } - g.definitions.writeln('int _v_type_idx_${typ.cname}();') + g.definitions.writeln('int _v_type_idx_${sym.cname}();') } } else if g.pref.use_cache { - for idx, typ in g.table.type_symbols { + for idx, sym in g.table.type_symbols { if idx == 0 { continue } - g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };') + g.definitions.writeln('int _v_type_idx_${sym.cname}() { return $idx; };') } } // @@ -745,43 +745,43 @@ pub fn (mut g Gen) finish() { pub fn (mut g Gen) write_typeof_functions() { g.writeln('') g.writeln('// >> typeof() support for sum types / interfaces') - for ityp, typ in g.table.type_symbols { - if typ.kind == .sum_type { - sum_info := typ.info as ast.SumType + for ityp, sym in g.table.type_symbols { + if sym.kind == .sum_type { + sum_info := sym.info as ast.SumType if sum_info.is_generic { continue } - g.writeln('static char * v_typeof_sumtype_${typ.cname}(int sidx) { /* $typ.name */ ') + g.writeln('static char * v_typeof_sumtype_${sym.cname}(int sidx) { /* $sym.name */ ') if g.pref.build_mode == .build_module { - g.writeln('\t\tif( sidx == _v_type_idx_${typ.cname}() ) return "${util.strip_main_name(typ.name)}";') + g.writeln('\t\tif( sidx == _v_type_idx_${sym.cname}() ) return "${util.strip_main_name(sym.name)}";') for v in sum_info.variants { subtype := g.table.get_type_symbol(v) g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return "${util.strip_main_name(subtype.name)}";') } - g.writeln('\treturn "unknown ${util.strip_main_name(typ.name)}";') + g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";') } else { - tidx := g.table.find_type_idx(typ.name) + tidx := g.table.find_type_idx(sym.name) g.writeln('\tswitch(sidx) {') - g.writeln('\t\tcase $tidx: return "${util.strip_main_name(typ.name)}";') + g.writeln('\t\tcase $tidx: return "${util.strip_main_name(sym.name)}";') for v in sum_info.variants { subtype := g.table.get_type_symbol(v) g.writeln('\t\tcase $v: return "${util.strip_main_name(subtype.name)}";') } - g.writeln('\t\tdefault: return "unknown ${util.strip_main_name(typ.name)}";') + g.writeln('\t\tdefault: return "unknown ${util.strip_main_name(sym.name)}";') g.writeln('\t}') } g.writeln('}') g.writeln('') - g.writeln('int v_typeof_sumtype_idx_${typ.cname}(int sidx) { /* $typ.name */ ') + g.writeln('int v_typeof_sumtype_idx_${sym.cname}(int sidx) { /* $sym.name */ ') if g.pref.build_mode == .build_module { - g.writeln('\t\tif( sidx == _v_type_idx_${typ.cname}() ) return ${int(ityp)};') + g.writeln('\t\tif( sidx == _v_type_idx_${sym.cname}() ) return ${int(ityp)};') for v in sum_info.variants { subtype := g.table.get_type_symbol(v) g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return ${int(v)};') } g.writeln('\treturn ${int(ityp)};') } else { - tidx := g.table.find_type_idx(typ.name) + tidx := g.table.find_type_idx(sym.name) g.writeln('\tswitch(sidx) {') g.writeln('\t\tcase $tidx: return ${int(ityp)};') for v in sum_info.variants { @@ -791,27 +791,27 @@ pub fn (mut g Gen) write_typeof_functions() { g.writeln('\t}') } g.writeln('}') - } else if typ.kind == .interface_ { - if typ.info !is ast.Interface { + } else if sym.kind == .interface_ { + if sym.info !is ast.Interface { continue } - inter_info := typ.info as ast.Interface + inter_info := sym.info as ast.Interface if inter_info.is_generic { continue } - g.definitions.writeln('static char * v_typeof_interface_${typ.cname}(int sidx);') - g.writeln('static char * v_typeof_interface_${typ.cname}(int sidx) { /* $typ.name */ ') + g.definitions.writeln('static char * v_typeof_interface_${sym.cname}(int sidx);') + g.writeln('static char * v_typeof_interface_${sym.cname}(int sidx) { /* $sym.name */ ') for t in inter_info.types { subtype := g.table.get_type_symbol(t) - g.writeln('\tif (sidx == _${typ.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";') + g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";') } - g.writeln('\treturn "unknown ${util.strip_main_name(typ.name)}";') + g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";') g.writeln('}') g.writeln('') - g.writeln('static int v_typeof_interface_idx_${typ.cname}(int sidx) { /* $typ.name */ ') + g.writeln('static int v_typeof_interface_idx_${sym.cname}(int sidx) { /* $sym.name */ ') for t in inter_info.types { subtype := g.table.get_type_symbol(t) - g.writeln('\tif (sidx == _${typ.cname}_${subtype.cname}_index) return ${int(t)};') + g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return ${int(t)};') } g.writeln('\treturn ${int(ityp)};') g.writeln('}') @@ -1097,24 +1097,24 @@ fn (g &Gen) type_sidx(t ast.Type) string { // pub fn (mut g Gen) write_typedef_types() { - for typ in g.table.type_symbols { - if typ.name in c.builtins { + for sym in g.table.type_symbols { + if sym.name in c.builtins { continue } - match typ.kind { + match sym.kind { .array { - info := typ.info as ast.Array + info := sym.info as ast.Array elem_sym := g.table.get_type_symbol(info.elem_type) if elem_sym.kind != .placeholder && !info.elem_type.has_flag(.generic) { - g.type_definitions.writeln('typedef array $typ.cname;') + g.type_definitions.writeln('typedef array $sym.cname;') } } .array_fixed { - info := typ.info as ast.ArrayFixed + info := sym.info as ast.ArrayFixed elem_sym := g.table.get_type_symbol(info.elem_type) if elem_sym.is_builtin() { // .array_fixed { - styp := typ.cname + styp := sym.cname // array_fixed_char_300 => char x[300] mut fixed := styp[12..] len := styp.after('_') @@ -1135,59 +1135,59 @@ pub fn (mut g Gen) write_typedef_types() { } } .chan { - if typ.name != 'chan' { - g.type_definitions.writeln('typedef chan $typ.cname;') - chan_inf := typ.chan_info() + if sym.name != 'chan' { + g.type_definitions.writeln('typedef chan $sym.cname;') + chan_inf := sym.chan_info() chan_elem_type := chan_inf.elem_type if !chan_elem_type.has_flag(.generic) { el_stype := g.typ(chan_elem_type) g.channel_definitions.writeln(' -static inline $el_stype __${typ.cname}_popval($typ.cname ch) { +static inline $el_stype __${sym.cname}_popval($sym.cname ch) { $el_stype val; sync__Channel_try_pop_priv(ch, &val, false); return val; }') g.channel_definitions.writeln(' -static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) { +static inline void __${sym.cname}_pushval($sym.cname ch, $el_stype val) { sync__Channel_try_push_priv(ch, &val, false); }') } } } .map { - g.type_definitions.writeln('typedef map $typ.cname;') + g.type_definitions.writeln('typedef map $sym.cname;') } else { continue } } } - for typ in g.table.type_symbols { - if typ.kind == .alias && typ.name !in c.builtins { - g.write_alias_typesymbol_declaration(typ) + for sym in g.table.type_symbols { + if sym.kind == .alias && sym.name !in c.builtins { + g.write_alias_typesymbol_declaration(sym) } } - for typ in g.table.type_symbols { - if typ.kind == .function && typ.name !in c.builtins { - g.write_fn_typesymbol_declaration(typ) + for sym in g.table.type_symbols { + if sym.kind == .function && sym.name !in c.builtins { + g.write_fn_typesymbol_declaration(sym) } } // Generating interfaces after all the common types have been defined // to prevent generating interface struct before definition of field types - for typ in g.table.type_symbols { - if typ.kind == .interface_ && typ.name !in c.builtins { - g.write_interface_typedef(typ) + for sym in g.table.type_symbols { + if sym.kind == .interface_ && sym.name !in c.builtins { + g.write_interface_typedef(sym) } } - for typ in g.table.type_symbols { - if typ.kind == .interface_ && typ.name !in c.builtins { - g.write_interface_typesymbol_declaration(typ) + for sym in g.table.type_symbols { + if sym.kind == .interface_ && sym.name !in c.builtins { + g.write_interface_typesymbol_declaration(sym) } } } pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) { - parent := unsafe { &g.table.type_symbols[sym.parent_idx] } + parent := g.table.type_symbols[sym.parent_idx] is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.` mut is_typedef := false if parent.info is ast.Struct { @@ -3679,9 +3679,9 @@ fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, stri } .voidptr { ts := if g.pref.m64 { - unsafe { &g.table.type_symbols[ast.u64_type_idx] } + unsafe { g.table.get_type_symbol_by_idx(ast.u64_type_idx) } } else { - unsafe { &g.table.type_symbols[ast.u32_type_idx] } + unsafe { g.table.get_type_symbol_by_idx(ast.u32_type_idx) } } return g.map_fn_ptrs(ts) } @@ -5102,27 +5102,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { } g.is_amp = false sym := g.table.get_type_symbol(node.typ) - if sym.kind == .string && !node.typ.is_ptr() { - // `string(x)` needs `tos()`, but not `&string(x) - // `tos(str, len)`, `tos2(str)` - if node.has_arg { - g.write('tos((byteptr)') - } else { - g.write('tos2((byteptr)') - } - g.expr(node.expr) - expr_sym := g.table.get_type_symbol(node.expr_type) - if expr_sym.kind == .array { - // if we are casting an array, we need to add `.data` - g.write('.data') - } - if node.has_arg { - // len argument - g.write(', ') - g.expr(node.arg) - } - g.write(')') - } else if sym.kind in [.sum_type, .interface_] { + if sym.kind in [.sum_type, .interface_] { g.expr_with_cast(node.expr, node.expr_type, node.typ) } else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as ast.Struct).is_typedef { // deprecated, replaced by Struct{...exr} @@ -6328,11 +6308,11 @@ fn (mut g Gen) write_builtin_types() { if g.pref.no_builtin { return } - mut builtin_types := []ast.TypeSymbol{} // builtin types + mut builtin_types := []&ast.TypeSymbol{} // builtin types // builtin types need to be on top // everything except builtin will get sorted for builtin_name in c.builtins { - sym := g.table.type_symbols[g.table.type_idxs[builtin_name]] + sym := g.table.get_type_symbol_by_idx(g.table.type_idxs[builtin_name]) if sym.kind == .interface_ { g.write_interface_typedef(sym) g.write_interface_typesymbol_declaration(sym) @@ -6347,36 +6327,36 @@ fn (mut g Gen) write_builtin_types() { // Sort the types, make sure types that are referenced by other types // are added before them. fn (mut g Gen) write_sorted_types() { - mut types := []ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted - for typ in g.table.type_symbols { - if typ.name !in c.builtins { - types << typ + mut symbols := []&ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted + for sym in g.table.type_symbols { + if sym.name !in c.builtins { + symbols << sym } } // sort structs - types_sorted := g.sort_structs(types) + sorted_symbols := g.sort_structs(symbols) // Generate C code g.type_definitions.writeln('// builtin types:') g.type_definitions.writeln('//------------------ #endbuiltin') - g.write_types(types_sorted) + g.write_types(sorted_symbols) } -fn (mut g Gen) write_types(types []ast.TypeSymbol) { - for typ in types { - if typ.name.starts_with('C.') { +fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { + for sym in symbols { + if sym.name.starts_with('C.') { continue } - if typ.kind == .none_ { + if sym.kind == .none_ { g.type_definitions.writeln('struct none {') g.type_definitions.writeln('\tEMPTY_STRUCT_DECLARATION;') g.type_definitions.writeln('};') g.typedefs2.writeln('typedef struct none none;') } // sym := g.table.get_type_symbol(typ) - mut name := typ.cname - match mut typ.info { + mut name := sym.cname + match mut sym.info { ast.Struct { - if typ.info.is_generic { + if sym.info.is_generic { continue } if name.contains('_T_') { @@ -6388,7 +6368,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { mut pre_pragma := '' mut post_pragma := '' - for attr in typ.info.attrs { + for attr in sym.info.attrs { match attr.name { '_pack' { pre_pragma += '#pragma pack(push, $attr.arg)\n' @@ -6400,13 +6380,13 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { g.type_definitions.writeln(pre_pragma) - if typ.info.is_union { + if sym.info.is_union { g.type_definitions.writeln('union $name {') } else { g.type_definitions.writeln('struct $name {') } - if typ.info.fields.len > 0 || typ.info.embeds.len > 0 { - for field in typ.info.fields { + if sym.info.fields.len > 0 || sym.info.embeds.len > 0 { + for field in sym.info.fields { // Some of these structs may want to contain // optionals that may not be defined at this point // if this is the case then we are going to @@ -6439,7 +6419,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { } // g.type_definitions.writeln('} $name;\n') // - ti_attrs := if typ.info.attrs.contains('packed') { + ti_attrs := if sym.info.attrs.contains('packed') { '__attribute__((__packed__))' } else { '' @@ -6469,26 +6449,26 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { } } ast.SumType { - if typ.info.is_generic { + if sym.info.is_generic { continue } g.typedefs.writeln('typedef struct $name $name;') g.type_definitions.writeln('') g.type_definitions.writeln('// Union sum type $name = ') - for variant in typ.info.variants { + for variant in sym.info.variants { g.type_definitions.writeln('// | ${variant:4d} = ${g.typ(variant.idx()):-20s}') } g.type_definitions.writeln('struct $name {') g.type_definitions.writeln('\tunion {') - for variant in typ.info.variants { + for variant in sym.info.variants { variant_sym := g.table.get_type_symbol(variant) g.type_definitions.writeln('\t\t${g.typ(variant.ref())} _$variant_sym.cname;') } g.type_definitions.writeln('\t};') g.type_definitions.writeln('\tint _typ;') - if typ.info.fields.len > 0 { + if sym.info.fields.len > 0 { g.writeln('\t// pointers to common sumtype fields') - for field in typ.info.fields { + for field in sym.info.fields { g.type_definitions.writeln('\t${g.typ(field.typ.ref())} $field.name;') } } @@ -6496,18 +6476,18 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { g.type_definitions.writeln('') } ast.ArrayFixed { - elem_sym := g.table.get_type_symbol(typ.info.elem_type) - if !elem_sym.is_builtin() && !typ.info.elem_type.has_flag(.generic) { + elem_sym := g.table.get_type_symbol(sym.info.elem_type) + if !elem_sym.is_builtin() && !sym.info.elem_type.has_flag(.generic) { // .array_fixed { - styp := typ.cname + styp := sym.cname // array_fixed_char_300 => char x[300] // [16]&&&EventListener{} => Array_fixed_main__EventListener_16_ptr3 // => typedef main__EventListener*** Array_fixed_main__EventListener_16_ptr3 [16] - mut fixed_elem_name := g.typ(typ.info.elem_type.set_nr_muls(0)) - if typ.info.elem_type.is_ptr() { - fixed_elem_name += '*'.repeat(typ.info.elem_type.nr_muls()) + mut fixed_elem_name := g.typ(sym.info.elem_type.set_nr_muls(0)) + if sym.info.elem_type.is_ptr() { + fixed_elem_name += '*'.repeat(sym.info.elem_type.nr_muls()) } - len := typ.info.size + len := sym.info.size if fixed_elem_name.starts_with('C__') { fixed_elem_name = fixed_elem_name[3..] } @@ -6529,7 +6509,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { } // sort structs by dependant fields -fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol { +fn (g &Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol { util.timing_start(@METHOD) defer { util.timing_measure(@METHOD) @@ -6537,26 +6517,26 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol { mut dep_graph := depgraph.new_dep_graph() // types name list mut type_names := []string{} - for typ in typesa { - type_names << typ.name + for sym in typesa { + type_names << sym.name } // loop over types - for t in typesa { - if t.kind == .interface_ { - dep_graph.add(t.name, []) + for sym in typesa { + if sym.kind == .interface_ { + dep_graph.add(sym.name, []) continue } // create list of deps mut field_deps := []string{} - match mut t.info { + match mut sym.info { ast.ArrayFixed { - dep := g.table.get_type_symbol(t.info.elem_type).name + dep := g.table.get_type_symbol(sym.info.elem_type).name if dep in type_names { field_deps << dep } } ast.Struct { - for embed in t.info.embeds { + for embed in sym.info.embeds { dep := g.table.get_type_symbol(embed).name // skip if not in types list or already in deps if dep !in type_names || dep in field_deps { @@ -6564,7 +6544,7 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol { } field_deps << dep } - for field in t.info.fields { + for field in sym.info.fields { dep := g.table.get_type_symbol(field.typ).name // skip if not in types list or already in deps if dep !in type_names || dep in field_deps || field.typ.is_ptr() { @@ -6577,7 +6557,7 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol { else {} } // add type and dependant types to graph - dep_graph.add(t.name, field_deps) + dep_graph.add(sym.name, field_deps) } // sort graph dep_graph_sorted := dep_graph.resolve() @@ -6590,11 +6570,11 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol { '\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro') } // sort types - mut types_sorted := []ast.TypeSymbol{cap: dep_graph_sorted.nodes.len} + mut sorted_symbols := []&ast.TypeSymbol{cap: dep_graph_sorted.nodes.len} for node in dep_graph_sorted.nodes { - types_sorted << g.table.type_symbols[g.table.type_idxs[node.name]] + sorted_symbols << g.table.get_type_symbol_by_idx(g.table.type_idxs[node.name]) } - return types_sorted + return sorted_symbols } [inline] @@ -7184,19 +7164,19 @@ fn (g Gen) as_cast_name_table() string { fn (mut g Gen) interface_table() string { mut sb := strings.new_builder(100) mut conversion_functions := strings.new_builder(100) - for ityp in g.table.type_symbols { - if ityp.kind != .interface_ { + for isym in g.table.type_symbols { + if isym.kind != .interface_ { continue } - if ityp.info !is ast.Interface { + if isym.info !is ast.Interface { continue } - inter_info := ityp.info as ast.Interface + inter_info := isym.info as ast.Interface if inter_info.is_generic { continue } // interface_name is for example Speaker - interface_name := ityp.cname + interface_name := isym.cname // generate a struct that references interface methods methods_struct_name := 'struct _${interface_name}_interface_methods' mut methods_struct_def := strings.new_builder(100) @@ -7243,7 +7223,7 @@ fn (mut g Gen) interface_table() string { cctype := g.cc_type(st, true) $if debug_interface_table ? { eprintln( - '>> interface name: $ityp.name | concrete type: $st.debug() | st symname: ' + + '>> interface name: $isym.name | concrete type: $st.debug() | st symname: ' + st_sym.name) } // Speaker_Cat_index = 0 @@ -7253,7 +7233,7 @@ fn (mut g Gen) interface_table() string { } already_generated_mwrappers[interface_index_name] = current_iinidx current_iinidx++ - if ityp.name != 'vweb.DbInterface' { // TODO remove this + if isym.name != 'vweb.DbInterface' { // TODO remove this // eprintln('>>> current_iinidx: ${current_iinidx-iinidx_minimum_base} | interface_index_name: $interface_index_name') sb.writeln('static $interface_name I_${cctype}_to_Interface_${interface_name}($cctype* x);') mut cast_struct := strings.new_builder(100) diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index 7853c86971..a066ba5b31 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -119,7 +119,7 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref } pub fn (mut g Gen) typ(a int) &ast.TypeSymbol { - return &g.table.type_symbols[a] + return g.table.type_symbols[a] } pub fn (mut g Gen) generate_header() { diff --git a/vlib/v/tests/alias_basic_types_test.v b/vlib/v/tests/alias_basic_types_test.v new file mode 100644 index 0000000000..8cdb58d372 --- /dev/null +++ b/vlib/v/tests/alias_basic_types_test.v @@ -0,0 +1,66 @@ +type MyByte = byte + +type MyInt = int + +type MyString = string + +fn ok() { + assert true +} + +// bytes +fn test_byte_aliasing() { + dump(byte(123)) + dump(MyByte(byte(123))) + dump(byte(MyByte(byte(123)))) + ok() +} + +fn test_pbyte_aliasing() { + unsafe { + dump(voidptr(&byte(123))) + dump(voidptr(&MyByte(&byte(123)))) + dump(voidptr(&byte(&MyByte(&byte(123))))) + } + ok() +} + +// ints +fn test_int_aliasing() { + dump(int(123)) + dump(int(MyInt(123))) + dump(MyInt(int(MyInt(123)))) + ok() +} + +fn test_pint_aliasing() { + unsafe { + dump(voidptr(&int(123456))) + dump(voidptr(&MyInt(&int(123456)))) + dump(voidptr(&int(&MyInt(&int(123456))))) + } + ok() +} + +// strings +fn test_string_aliasing() { + $if msvc { + eprintln('> TODO: msvc errors out for casting a `string` to a `string`') + } + $if !msvc { + dump(string('abc')) + dump(string(MyString('abc'))) + dump(MyString(string(MyString('abc')))) + } + ok() +} + +fn test_pstring_aliasing() { + s := 'abc' + unsafe { + dump(voidptr(&string(&s))) + dump(voidptr(&string(&MyString(&s)))) + dump(voidptr(&MyString(&string(&MyString(&s))))) + } + ok() +} diff --git a/vlib/v/token/position.v b/vlib/v/token/position.v index 9e15d3e618..f81af40eb8 100644 --- a/vlib/v/token/position.v +++ b/vlib/v/token/position.v @@ -13,6 +13,10 @@ pub mut: last_line int // the line number where the ast object ends (used by vfmt) } +[unsafe] +pub fn (mut p Position) free() { +} + pub fn (pos Position) extend(end Position) Position { return Position{ ...pos