From 029e8a815b5e7ff60edfb9f5587a37877865b247 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 13 Jul 2023 05:56:11 -0300 Subject: [PATCH] checker: fix type checker on auto deref var (#18842) --- vlib/v/ast/ast.v | 11 ++++++++++ vlib/v/checker/assign.v | 21 +++++++++++++++++-- .../v/checker/tests/auto_deref_assign_err.out | 6 ++++++ vlib/v/checker/tests/auto_deref_assign_err.vv | 11 ++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 vlib/v/checker/tests/auto_deref_assign_err.out create mode 100644 vlib/v/checker/tests/auto_deref_assign_err.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index e2583fb1bf..5afaf2c04d 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -2013,6 +2013,17 @@ pub fn (expr Expr) is_expr() bool { } } +pub fn (expr Expr) get_pure_type() Type { + match expr { + BoolLiteral { return bool_type } + CharLiteral { return char_type } + FloatLiteral { return f64_type } + StringLiteral { return string_type } + IntegerLiteral { return i64_type } + else { return void_type } + } +} + pub fn (expr Expr) is_pure_literal() bool { return match expr { BoolLiteral, CharLiteral, FloatLiteral, StringLiteral, IntegerLiteral { true } diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 03197237c7..468f04ca4f 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -664,11 +664,28 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { } } } - if !is_blank_ident && !left.is_auto_deref_var() && !right.is_auto_deref_var() - && right_sym.kind != .placeholder && left_sym.kind != .interface_ + if !is_blank_ident && right_sym.kind != .placeholder && left_sym.kind != .interface_ && !right_type.has_flag(.generic) && !left_type.has_flag(.generic) { // Dual sides check (compatibility check) c.check_expected(right_type_unwrapped, left_type_unwrapped) or { + // allow literal values to auto deref var (e.g.`for mut v in values { v = 1.0 }`) + if left.is_auto_deref_var() || right.is_auto_deref_var() { + left_deref := if left.is_auto_deref_var() { + left_type.deref() + } else { + left_type + } + right_deref := if right.is_pure_literal() { + right.get_pure_type() + } else if right.is_auto_deref_var() { + right_type.deref() + } else { + right_type + } + if c.check_types(left_deref, right_deref) { + continue + } + } // allow for ptr += 2 if left_type_unwrapped.is_ptr() && right_type_unwrapped.is_int() && node.op in [.plus_assign, .minus_assign] { diff --git a/vlib/v/checker/tests/auto_deref_assign_err.out b/vlib/v/checker/tests/auto_deref_assign_err.out new file mode 100644 index 0000000000..afb32550ad --- /dev/null +++ b/vlib/v/checker/tests/auto_deref_assign_err.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/auto_deref_assign_err.vv:10:6: error: cannot assign to `o`: expected `&int`, not `string` + 8 | fn sub( mut o &int ) { + 9 | println( 'in function got: ' + o.str() ) + 10 | o = "mutate int as string??" + | ~~~~~~~~~~~~~~~~~~~~~~~~ + 11 | } diff --git a/vlib/v/checker/tests/auto_deref_assign_err.vv b/vlib/v/checker/tests/auto_deref_assign_err.vv new file mode 100644 index 0000000000..1c16db3422 --- /dev/null +++ b/vlib/v/checker/tests/auto_deref_assign_err.vv @@ -0,0 +1,11 @@ +fn main() { + mut a := 42 + println( 'before sub: ' + a.str() ) + sub( mut a ) + println( 'after sub: ' + a.str() ) +} + +fn sub( mut o &int ) { + println( 'in function got: ' + o.str() ) + o = "mutate int as string??" +} \ No newline at end of file