mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
cgen: fix comptime is
condition when using interface (#20952)
This commit is contained in:
parent
0211a0d548
commit
a3bb422ec4
4 changed files with 46 additions and 4 deletions
|
@ -10,6 +10,10 @@ fn (mut c Checker) check_compatible_types(left_type ast.Type, right ast.TypeNode
|
||||||
right_type := c.unwrap_generic(right.typ)
|
right_type := c.unwrap_generic(right.typ)
|
||||||
sym := c.table.sym(right_type)
|
sym := c.table.sym(right_type)
|
||||||
|
|
||||||
|
if right_type.has_flag(.option) != left_type.has_flag(.option) {
|
||||||
|
return .skip
|
||||||
|
}
|
||||||
|
|
||||||
if sym.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
checked_type := c.unwrap_generic(left_type)
|
checked_type := c.unwrap_generic(left_type)
|
||||||
return if c.table.does_type_implement_interface(checked_type, right_type) {
|
return if c.table.does_type_implement_interface(checked_type, right_type) {
|
||||||
|
|
|
@ -19,7 +19,8 @@ fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type {
|
||||||
node.expr.pos())
|
node.expr.pos())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.inside_unsafe && is_non_void_pointer && !node.expr.is_auto_deref_var() {
|
if node.op != .question && !c.inside_unsafe && is_non_void_pointer
|
||||||
|
&& !node.expr.is_auto_deref_var() {
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
||||||
}
|
}
|
||||||
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
|
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
|
||||||
|
|
|
@ -516,11 +516,11 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
|
||||||
got_sym := g.table.sym(got_type)
|
got_sym := g.table.sym(got_type)
|
||||||
|
|
||||||
if got_sym.kind == .interface_ && got_sym.info is ast.Interface {
|
if got_sym.kind == .interface_ && got_sym.info is ast.Interface {
|
||||||
is_true := g.table.does_type_implement_interface(exp_type,
|
is_true := exp_type.has_flag(.option) == got_type.has_flag(.option)
|
||||||
got_type)
|
&& g.table.does_type_implement_interface(exp_type, got_type)
|
||||||
if cond.op == .key_is {
|
if cond.op == .key_is {
|
||||||
if is_true {
|
if is_true {
|
||||||
g.write('1')
|
g.write('1 && ${exp_type.has_flag(.option)} == ${got_type.has_flag(.option)}')
|
||||||
} else {
|
} else {
|
||||||
g.write('0')
|
g.write('0')
|
||||||
}
|
}
|
||||||
|
|
37
vlib/v/tests/comptime_is_interface_check_test.v
Normal file
37
vlib/v/tests/comptime_is_interface_check_test.v
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
interface TestInterface {
|
||||||
|
test_func() f64
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Struct1 {
|
||||||
|
num f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (o &Struct1) test_func() f64 {
|
||||||
|
return o.num
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Struct2 {
|
||||||
|
mut:
|
||||||
|
s1 ?&Struct1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_thing[T](s1 Struct1) T {
|
||||||
|
mut t := T{}
|
||||||
|
t.s1 = &s1
|
||||||
|
$for field in T.fields {
|
||||||
|
$if field.typ is TestInterface {
|
||||||
|
i := TestInterface(t.$(field.name))
|
||||||
|
assert false
|
||||||
|
} $else $if field.typ is ?TestInterface {
|
||||||
|
i := TestInterface(t.$(field.name) ?)
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
assert do_thing[Struct2](Struct1{1.23}).s1?.num == 1.23
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue