Skip to content

Commit

Permalink
checker: fix type checker on auto deref var (#18842)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Jul 13, 2023
1 parent efcb15d commit 029e8a8
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
11 changes: 11 additions & 0 deletions vlib/v/ast/ast.v
Expand Up @@ -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 }
Expand Down
21 changes: 19 additions & 2 deletions vlib/v/checker/assign.v
Expand Up @@ -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] {
Expand Down
6 changes: 6 additions & 0 deletions 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 | }
11 changes: 11 additions & 0 deletions 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??"
}

0 comments on commit 029e8a8

Please sign in to comment.