mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: fix type checker on auto deref var (#18842)
This commit is contained in:
parent
efcb15d05b
commit
029e8a815b
@ -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 {
|
pub fn (expr Expr) is_pure_literal() bool {
|
||||||
return match expr {
|
return match expr {
|
||||||
BoolLiteral, CharLiteral, FloatLiteral, StringLiteral, IntegerLiteral { true }
|
BoolLiteral, CharLiteral, FloatLiteral, StringLiteral, IntegerLiteral { true }
|
||||||
|
@ -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()
|
if !is_blank_ident && right_sym.kind != .placeholder && left_sym.kind != .interface_
|
||||||
&& right_sym.kind != .placeholder && left_sym.kind != .interface_
|
|
||||||
&& !right_type.has_flag(.generic) && !left_type.has_flag(.generic) {
|
&& !right_type.has_flag(.generic) && !left_type.has_flag(.generic) {
|
||||||
// Dual sides check (compatibility check)
|
// Dual sides check (compatibility check)
|
||||||
c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
|
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
|
// allow for ptr += 2
|
||||||
if left_type_unwrapped.is_ptr() && right_type_unwrapped.is_int()
|
if left_type_unwrapped.is_ptr() && right_type_unwrapped.is_int()
|
||||||
&& node.op in [.plus_assign, .minus_assign] {
|
&& node.op in [.plus_assign, .minus_assign] {
|
||||||
|
6
vlib/v/checker/tests/auto_deref_assign_err.out
Normal file
6
vlib/v/checker/tests/auto_deref_assign_err.out
Normal file
@ -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
vlib/v/checker/tests/auto_deref_assign_err.vv
Normal file
11
vlib/v/checker/tests/auto_deref_assign_err.vv
Normal file
@ -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??"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user