1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: add check for mut ident but not if mut ident is for interfaces (#16214)

This commit is contained in:
Swastik Baranwal 2022-10-29 09:06:44 +05:30 committed by GitHub
parent ee782e9119
commit a988ef3474
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 3 deletions

View File

@ -353,6 +353,15 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
&& (node.left as ast.SelectorExpr).is_mut) {
c.fail_if_immutable(node.left)
}
// TODO: Add check for sum types in a way that it doesn't break a lot of compiler code
if node.left is ast.Ident
&& (left_sym.kind == .interface_ && right_sym.kind != .interface_) {
v := scope.find_var(node.left.name) or { &ast.Var{} }
if v.is_mut && !node.left.is_mut {
c.error('smart casting a mutable interface value requires `if mut $node.left.name is ...`',
node.left.pos)
}
}
if left_sym.kind in [.interface_, .sum_type] {
c.smartcast(node.left, node.left_type, right_type, mut scope)
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/if_smartcast_mut_var_interface_err.vv:13:5: error: smart casting a mutable interface value requires `if mut foo_mut is ...`
11 | fn main() {
12 | mut foo_mut := Foo(Bar{})
13 | if foo_mut is Bar {
| ~~~~~~~
14 | println(json.encode(foo_mut))
15 | }

View File

@ -0,0 +1,16 @@
import json
interface Foo {
a int
}
struct Bar {
a int
}
fn main() {
mut foo_mut := Foo(Bar{})
if foo_mut is Bar {
println(json.encode(foo_mut))
}
}

View File

@ -5,6 +5,13 @@ vlib/v/checker/tests/incorrect_smartcast_err.vv:10:5: notice: smartcasting requi
| ~~~~~~~
11 | println(example.field)
12 | }
vlib/v/checker/tests/incorrect_smartcast_err.vv:10:5: error: smart casting a mutable interface value requires `if mut example is ...`
8 | fn main(){
9 | mut example := IExample(Example{field:"test"})
10 | if example is Example{
| ~~~~~~~
11 | println(example.field)
12 | }
vlib/v/checker/tests/incorrect_smartcast_err.vv:11:19: error: type `IExample` has no field named `field`
9 | mut example := IExample(Example{field:"test"})
10 | if example is Example{

View File

@ -26,12 +26,12 @@ fn use_interface(a Animal) {
}
fn mutate_interface(mut a Animal) {
if a is Cat {
if mut a is Cat {
a.breed = 'Siamese'
} else {
a.breed = 'Golden Retriever'
}
if a is Cat {
if mut a is Cat {
assert a.breed == 'Siamese'
} else {
assert a.breed == 'Golden Retriever'

View File

@ -43,7 +43,7 @@ pub fn (mut ll LinearLayout) layout() string {
for mut l in ll.layoutables {
dump(l.type_name())
output += '$l.type_name()\n'
if l is Container {
if mut l is Container {
dump(l.type_name())
output += '$l.type_name()\n'
}