From ab3adf3346f182f44193d507e3c5cb1c6754060b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 9 Sep 2021 20:21:01 +0300 Subject: [PATCH] checker: no longer allow automatic dereferncing in `a = b` --- vlib/builtin/builtin_nix.c.v | 2 +- vlib/sokol/sapp/sapp.c.v | 2 +- vlib/v/ast/table.v | 37 ++++++++++++++++++++---------------- vlib/v/ast/types.v | 10 ++++++++++ vlib/v/checker/check_types.v | 2 +- vlib/v/checker/checker.v | 17 +++++++++++++---- vlib/v/gen/js/js.v | 7 ++++--- vlib/v/gen/native/amd64.v | 2 +- vlib/v/gen/native/arm64.v | 2 +- vlib/v/gen/native/gen.v | 10 +++++++--- vlib/v/parser/parser.v | 6 +++--- 11 files changed, 63 insertions(+), 34 deletions(-) diff --git a/vlib/builtin/builtin_nix.c.v b/vlib/builtin/builtin_nix.c.v index 0d79af4f9a..803f716826 100644 --- a/vlib/builtin/builtin_nix.c.v +++ b/vlib/builtin/builtin_nix.c.v @@ -131,7 +131,7 @@ fn break_if_debugger_attached() { unsafe { mut ptr := &voidptr(0) *ptr = voidptr(0) - _ = ptr + //_ = ptr } } diff --git a/vlib/sokol/sapp/sapp.c.v b/vlib/sokol/sapp/sapp.c.v index fc8d00f286..1cb482a4b0 100644 --- a/vlib/sokol/sapp/sapp.c.v +++ b/vlib/sokol/sapp/sapp.c.v @@ -152,7 +152,7 @@ pub fn get_clipboard_string() &char { // special run-function for SOKOL_NO_ENTRY (in standard mode this is an empty stub) [inline] pub fn run(desc &C.sapp_desc) { - g_desc = desc + g_desc = *desc C.sapp_run(desc) } diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 51226a00ce..08fcdd1780 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -122,28 +122,33 @@ pub mut: typ Type } -pub fn (f Fn) new_method_with_receiver_type(new_type Type) Fn { - mut new_method := f - new_method.params = f.params.clone() - for i in 1 .. new_method.params.len { - if new_method.params[i].typ == new_method.params[0].typ { - new_method.params[i].typ = new_type +pub fn (f &Fn) new_method_with_receiver_type(new_type Type) Fn { + unsafe { + mut new_method := f + new_method.params = f.params.clone() + for i in 1 .. new_method.params.len { + if new_method.params[i].typ == new_method.params[0].typ { + new_method.params[i].typ = new_type + } } + new_method.params[0].typ = new_type + + return *new_method } - new_method.params[0].typ = new_type - return new_method } -pub fn (f FnDecl) new_method_with_receiver_type(new_type Type) FnDecl { - mut new_method := f - new_method.params = f.params.clone() - for i in 1 .. new_method.params.len { - if new_method.params[i].typ == new_method.params[0].typ { - new_method.params[i].typ = new_type +pub fn (f &FnDecl) new_method_with_receiver_type(new_type Type) FnDecl { + unsafe { + mut new_method := f + new_method.params = f.params.clone() + for i in 1 .. new_method.params.len { + if new_method.params[i].typ == new_method.params[0].typ { + new_method.params[i].typ = new_type + } } + new_method.params[0].typ = new_type + return *new_method } - new_method.params[0].typ = new_type - return new_method } fn (p &Param) equals(o &Param) bool { diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index f50667bca7..73d40a822d 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -246,6 +246,11 @@ pub fn (t Type) str() string { return 'ast.Type(0x$t.hex() = ${u32(t)})' } +pub fn (t &Table) type_str(typ Type) string { + sym := t.get_type_symbol(typ) + return sym.name +} + // debug returns a verbose representation of the information in the type `t`, useful for tracing/debugging pub fn (t Type) debug() []string { mut res := []string{} @@ -309,6 +314,11 @@ pub fn (typ Type) is_pointer() bool { return typ.idx() in ast.pointer_type_idxs } +[inline] +pub fn (typ Type) is_real_pointer() bool { + return typ.is_ptr() || typ.is_pointer() +} + [inline] pub fn (typ Type) is_float() bool { return typ.clear_flags() in ast.float_type_idxs diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 8d14cb0960..baed7a734a 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -288,7 +288,7 @@ pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool { } // allow direct int-literal assignment for pointers for now // maybe in the future optionals should be used for that - if expected.is_ptr() || expected.is_pointer() { + if expected.is_real_pointer() { if got == ast.int_literal_type { return true } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 50f6e09a1d..4d58a459eb 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4020,6 +4020,14 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } } + // Do not allow `a := 0; b := 0; a = &b` + if !is_decl && left is ast.Ident && !is_blank_ident && !left_type.is_real_pointer() + && right_type.is_real_pointer() { + c.warn( + 'cannot assign a reference to a value (this will be an error soon) left=${c.table.type_str(left_type)} $left_type.is_ptr() ' + + 'right=${c.table.type_str(right_type)} $right_type.is_real_pointer() ptr=$right_type.is_ptr()', + node.pos) + } node.left_types << left_type match mut left { ast.Ident { @@ -5742,7 +5750,8 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { - node.sym = c.table.get_type_symbol(c.unwrap_generic(c.expr(node.left))) + sym := c.table.get_type_symbol(c.unwrap_generic(c.expr(node.left))) + node.sym = *sym if node.is_env { env_value := util.resolve_env_value("\$env('$node.args_var')", false) or { c.error(err.msg, node.env_pos) @@ -7770,7 +7779,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type { } sym := c.table.get_type_symbol(node.table_expr.typ) c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } - c.cur_orm_ts = sym + c.cur_orm_ts = *sym info := sym.info as ast.Struct fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name) mut sub_structs := map[int]ast.SqlExpr{} @@ -7868,7 +7877,7 @@ fn (mut c Checker) sql_stmt_line(mut node ast.SqlStmtLine) ast.Type { } c.ensure_type_exists(node.table_expr.typ, node.pos) or { return ast.void_type } table_sym := c.table.get_type_symbol(node.table_expr.typ) - c.cur_orm_ts = table_sym + c.cur_orm_ts = *table_sym if table_sym.info !is ast.Struct { c.error('unknown type `$table_sym.name`', node.pos) return ast.void_type @@ -8071,7 +8080,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.check_valid_snake_case(node.name, 'function name', node.pos) } if node.name == 'main.main' { - c.main_fn_decl_node = node + c.main_fn_decl_node = *node } if node.return_type != ast.void_type { if ct_attr_idx := node.attrs.find_comptime_define() { diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 41ecc0b5fa..469b615c1a 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -76,7 +76,7 @@ mut: cast_stack []ast.Type call_stack []ast.CallExpr is_vlines_enabled bool // is it safe to generate #line directives when -g is passed - sourcemap sourcemap.SourceMap // maps lines in generated javascrip file to original source files and line + sourcemap &sourcemap.SourceMap // maps lines in generated javascrip file to original source files and line comptime_var_type_map map[string]ast.Type defer_ifdef string out strings.Builder = strings.new_builder(128) @@ -98,6 +98,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { ns: 0 enable_doc: true file: 0 + sourcemap: 0 } g.doc = new_jsdoc(g) // TODO: Add '[-no]-jsdoc' flag @@ -185,7 +186,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { // out += 'const $name = (function (' mut namespace := g.namespaces[node.name] - + if g.pref.sourcemap { // calculate current output start line mut current_line := u32(out.count('\n') + 1) @@ -206,7 +207,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { sm_pos = sourcemap_ns_entry.ns_pos } } - + // public scope out += '\n' diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 11e9683678..7ee4e7e421 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -6,7 +6,7 @@ import v.token pub struct Amd64 { mut: - g Gen + g &Gen // arm64 specific stuff for code generation } diff --git a/vlib/v/gen/native/arm64.v b/vlib/v/gen/native/arm64.v index 22336c92a1..74b8f8ccea 100644 --- a/vlib/v/gen/native/arm64.v +++ b/vlib/v/gen/native/arm64.v @@ -38,7 +38,7 @@ enum Arm64Register { pub struct Arm64 { mut: - g Gen + g &Gen // arm64 specific stuff for code generation } diff --git a/vlib/v/gen/native/gen.v b/vlib/v/gen/native/gen.v index e85ca0e740..6df674f017 100644 --- a/vlib/v/gen/native/gen.v +++ b/vlib/v/gen/native/gen.v @@ -16,7 +16,7 @@ pub const builtins = ['assert', 'print', 'eprint', 'println', 'eprintln', 'exit' interface CodeGen { mut: - g Gen + g &Gen gen_exit(mut g Gen, expr ast.Expr) // XXX WHY gen_exit fn (expr ast.Expr) } @@ -58,10 +58,14 @@ enum Size { fn get_backend(arch pref.Arch) ?CodeGen { match arch { .arm64 { - return Arm64{} + return Arm64{ + g: 0 + } } .amd64 { - return Amd64{} + return Amd64{ + g: 0 + } } else {} } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index eff7017105..ca15e76913 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -147,12 +147,12 @@ pub fn (mut p Parser) set_path(path string) { } before_dot_v := path.all_before_last('.v') // also works for .vv and .vsh language := before_dot_v.all_after_last('.') - langauge_with_underscore := before_dot_v.all_after_last('_') - if language == before_dot_v && langauge_with_underscore == before_dot_v { + language_with_underscore := before_dot_v.all_after_last('_') + if language == before_dot_v && language_with_underscore == before_dot_v { p.file_backend_mode = .v return } - actual_language := if language == before_dot_v { langauge_with_underscore } else { language } + actual_language := if language == before_dot_v { language_with_underscore } else { language } match actual_language { 'c' { p.file_backend_mode = .c