diff --git a/vlib/v/ast/scope.v b/vlib/v/ast/scope.v index 8cd33a0e62..fbfeb6dbf5 100644 --- a/vlib/v/ast/scope.v +++ b/vlib/v/ast/scope.v @@ -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) { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 794f042d07..11202d8ba8 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index e29e2df671..9c5f1cde78 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -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) diff --git a/vlib/v/parser/orm.v b/vlib/v/parser/orm.v index e2884f6c7a..130545a647 100644 --- a/vlib/v/parser/orm.v +++ b/vlib/v/parser/orm.v @@ -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, diff --git a/vlib/v/tests/options/option_selector_none_unwrap_test.v b/vlib/v/tests/options/option_selector_none_unwrap_test.v new file mode 100644 index 0000000000..cca07b2204 --- /dev/null +++ b/vlib/v/tests/options/option_selector_none_unwrap_test.v @@ -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 +}