checker: fix compound selector smartcasting/option unwrapping (fix #24662) (#24712)

This commit is contained in:
Felipe Pena 2025-06-15 04:49:56 -03:00 committed by GitHub
parent 364f9ebda3
commit 12c20e3c1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 11 deletions

View File

@ -65,9 +65,10 @@ pub fn (s &Scope) find_struct_field(name string, struct_type Type, field_name st
if s == unsafe { nil } {
return unsafe { nil }
}
k := '${name}.${field_name}'
for sc := unsafe { s }; true; sc = sc.parent {
if field := sc.struct_fields[name] {
if field.struct_type == struct_type && field.name == field_name {
if field := sc.struct_fields[k] {
if field.struct_type == struct_type {
return &ScopeStructField{
...field
}
@ -164,12 +165,13 @@ pub fn (mut s Scope) update_smartcasts(name string, typ Type, is_unwrapped bool)
// selector_expr: name.field_name
pub fn (mut s Scope) register_struct_field(name string, field ScopeStructField) {
if f := s.struct_fields[name] {
if f.struct_type == field.struct_type && f.name == field.name {
k := '${name}.${field.name}'
if f := s.struct_fields[k] {
if f.struct_type == field.struct_type {
return
}
}
s.struct_fields[name] = field
s.struct_fields[k] = field
}
pub fn (mut s Scope) register(obj ScopeObject) {

View File

@ -4416,7 +4416,12 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
orig_type = field.typ
}
}
expr_str := expr.expr.str()
mut expr_str := expr.expr.str()
if mut expr.expr is ast.ParExpr {
if mut expr.expr.expr is ast.AsCast {
expr_str = expr.expr.expr.expr.str()
}
}
field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name)
if field != unsafe { nil } {
smartcasts << field.smartcasts

View File

@ -346,7 +346,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
left.obj.typ = var_type
g.assign_ct_type = var_type
} else if val is ast.Ident && val.info is ast.IdentVar {
val_info := (val as ast.Ident).info
val_info := (val as ast.Ident).info as ast.IdentVar
gen_or = val.or_expr.kind != .absent
if val_info.is_option && gen_or {
var_type = val_type.clear_flag(.option)

View File

@ -359,10 +359,12 @@ fn (mut p Parser) check_sql_where_expr_has_no_undefined_variables(expr &ast.Expr
}
}
} else if expr is ast.InfixExpr {
if expr.left is ast.Ident && expr.right is ast.Ident {
return p.check_sql_where_expr_has_no_undefined_variables(expr.right, [
expr.left.str(),
])
if expr.left is ast.Ident {
if expr.right is ast.Ident {
return p.check_sql_where_expr_has_no_undefined_variables(expr.right, [
expr.left.name,
])
}
}
left_check_result := p.check_sql_where_expr_has_no_undefined_variables(expr.left,

View File

@ -0,0 +1,28 @@
struct Options {
option_1 ?[]int
option_2 ?[]int
}
fn test_none() {
values := Options{
option_1: [1, 2, 3]
option_2: none
}
mut res := 0.0
if values.option_1 != none && values.option_2 != none {
res = values.option_1[0] + values.option_2[0]
}
assert res == 0
}
fn test_add() {
values := Options{
option_1: [1, 2, 3]
option_2: [3]
}
mut res := 0.0
if values.option_1 != none && values.option_2 != none {
res = values.option_1[0] + values.option_2[0]
}
assert res == 4
}