cgen: fix comptime is condition when using interface (#20952)

This commit is contained in:
Felipe Pena 2024-03-04 05:20:19 -03:00 committed by GitHub
parent 0211a0d548
commit a3bb422ec4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 46 additions and 4 deletions

View file

@ -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) {

View file

@ -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)) {

View file

@ -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')
} }

View 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
}