Skip to content

Commit d547f74

Browse files
committed
checker/cgen: interface smart casts
1 parent 912bc8b commit d547f74

File tree

3 files changed

+19
-17
lines changed

3 files changed

+19
-17
lines changed

vlib/v/checker/checker.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,7 +2983,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
29832983
c.error('non-bool type `$typ_sym.source_name` used as if condition', branch.pos)
29842984
}
29852985
}
2986-
// smartcast sumtypes when using `is`
2986+
// smartcast sumtypes and interfaces when using `is`
29872987
if branch.cond is ast.InfixExpr {
29882988
infix := branch.cond as ast.InfixExpr
29892989
if infix.op == .key_is &&
@@ -2994,7 +2994,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
29942994
// Register shadow variable or `as` variable with actual type
29952995
if is_variable {
29962996
left_sym := c.table.get_type_symbol(infix.left_type)
2997-
if left_sym.kind == .sum_type && branch.left_as_name.len > 0 {
2997+
if left_sym.kind in [.sum_type, .interface_] && branch.left_as_name.len > 0 {
29982998
mut is_mut := false
29992999
mut scope := c.file.scope.innermost(branch.body_pos.pos)
30003000
if infix.left is ast.Ident as infix_left {

vlib/v/gen/cgen.v

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,20 +1134,20 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
11341134
got_sym := g.table.get_type_symbol(got_type)
11351135
if expected_is_ptr && got_is_ptr {
11361136
exp_der_styp := g.typ(expected_deref_type)
1137-
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = ')
1137+
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){._object = ')
11381138
g.expr(expr)
11391139
g.write(', .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))')
11401140
} else if expected_is_ptr {
11411141
exp_der_styp := g.typ(expected_deref_type)
1142-
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = memdup(&($got_styp[]) {')
1142+
g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){._object = memdup(&($got_styp[]) {')
11431143
g.expr(expr)
11441144
g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))')
11451145
} else if got_is_ptr {
1146-
g.write('/* sum type cast */ ($exp_styp) {.obj = ')
1146+
g.write('/* sum type cast */ ($exp_styp) {._object = ')
11471147
g.expr(expr)
11481148
g.write(', .typ = $got_idx /* $got_sym.name */}')
11491149
} else {
1150-
g.write('/* sum type cast */ ($exp_styp) {.obj = memdup(&($got_styp[]) {')
1150+
g.write('/* sum type cast */ ($exp_styp) {._object = memdup(&($got_styp[]) {')
11511151
g.expr(expr)
11521152
g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}')
11531153
}
@@ -2604,7 +2604,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
26042604
g.expr(node.cond)
26052605
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
26062606
g.write(dot_or_ptr)
2607-
g.writeln('obj; // ST it')
2607+
g.writeln('_object; // ST it')
26082608
if node.var_name.len > 0 {
26092609
// for now we just copy it
26102610
g.writeln('\t$it_type* $node.var_name = it;')
@@ -2788,7 +2788,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
27882788
} else {
27892789
g.write('.')
27902790
}
2791-
g.writeln('obj;')
2791+
g.writeln('_object;')
27922792
g.writeln('\t$it_type* $branch.left_as_name = _sc_tmp_$branch.pos.pos;')
27932793
}
27942794
g.stmts(branch.stmts)
@@ -3773,7 +3773,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
37733773
g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
37743774
}
37753775
g.type_definitions.writeln('typedef struct {')
3776-
g.type_definitions.writeln(' void* obj;')
3776+
g.type_definitions.writeln(' void* _object;')
37773777
g.type_definitions.writeln(' int typ;')
37783778
g.type_definitions.writeln('} $name;')
37793779
g.type_definitions.writeln('')
@@ -4704,7 +4704,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
47044704
g.write('/* as */ ($styp*)__as_cast(')
47054705
g.expr(node.expr)
47064706
g.write(dot)
4707-
g.write('obj, ')
4707+
g.write('_object, ')
47084708
g.expr(node.expr)
47094709
g.write(dot)
47104710
g.write('typ, /*expected:*/$node.typ)')

vlib/v/tests/interface_test.v

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn (c &Cat) speak(s string) {
2323
}
2424

2525
fn (c Cat) name_detailed(pet_name string) string {
26-
return '$pet_name the ${typeof(c)}, breed:${c.breed}'
26+
return '$pet_name the ${typeof(c)}, breed:$c.breed'
2727
}
2828

2929
fn (mut c Cat) set_breed(new string) {
@@ -46,7 +46,7 @@ fn (d Dog) name() string {
4646
}
4747

4848
fn (d Dog) name_detailed(pet_name string) string {
49-
return '$pet_name the ${typeof(d)}, breed:${d.breed}'
49+
return '$pet_name the ${typeof(d)}, breed:$d.breed'
5050
}
5151

5252
fn (mut d Dog) set_breed(new string) {
@@ -67,23 +67,25 @@ fn perform_speak(a Animal) {
6767
assert name == 'Dog' || name == 'Cat'
6868
if a is Dog {
6969
assert name == 'Dog'
70+
assert a.breed == 'Labrador Retriever' // test smart casting
71+
println(a.breed)
7072
}
7173
println(a.name())
7274
println('Got animal of type: ${typeof(a)}') // TODO: get implementation type (if possible)
73-
// assert a is Dog || a is Cat // TODO: enable when available
75+
assert a is Dog || a is Cat
7476
}
7577

7678
fn perform_speak_on_ptr(a &Animal) {
7779
a.speak('Hi !')
7880
assert true
7981
name := a.name()
8082
assert name == 'Dog' || name == 'Cat'
81-
// if a is Dog {
82-
// assert name == 'Dog'
83-
// }
83+
if a is Dog {
84+
assert name == 'Dog'
85+
}
8486
println(a.name())
8587
println('Got animal of type: ${typeof(a)}') // TODO: get implementation type (if possible)
86-
// assert a is Dog || a is Cat // TODO: enable when available
88+
assert a is Dog || a is Cat
8789
}
8890

8991
fn test_perform_speak() {

0 commit comments

Comments
 (0)