diff --git a/vlib/v/ast/scope.v b/vlib/v/ast/scope.v index 127240c624..03cf92b7c5 100644 --- a/vlib/v/ast/scope.v +++ b/vlib/v/ast/scope.v @@ -61,21 +61,23 @@ pub fn (s &Scope) find(name string) ?ScopeObject { } // selector_expr: name.field_name -pub fn (s &Scope) find_struct_field(name string, struct_type Type, field_name string) ?ScopeStructField { +pub fn (s &Scope) find_struct_field(name string, struct_type Type, field_name string) &ScopeStructField { if s == unsafe { nil } { - return none + return unsafe { nil } } for sc := unsafe { s }; true; sc = sc.parent { if field := sc.struct_fields[name] { if field.struct_type == struct_type && field.name == field_name { - return field + return &ScopeStructField{ + ...field + } } } if sc.dont_lookup_parent() { break } } - return none + return unsafe { nil } } pub fn (s &Scope) find_var(name string) ?&Var { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index bfb3520f5d..d6f15a7fea 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1794,7 +1794,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { } if field_sym.kind in [.sum_type, .interface] || field.typ.has_flag(.option) { if !prevent_sum_type_unwrapping_once { - if scope_field := node.scope.find_struct_field(node.expr.str(), typ, field_name) { + scope_field := node.scope.find_struct_field(node.expr.str(), typ, field_name) + if scope_field != unsafe { nil } { return scope_field.smartcasts.last() } } @@ -4379,7 +4380,8 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast. } } expr_str := expr.expr.str() - if mut field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name) { + field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name) + if field != unsafe { nil } { smartcasts << field.smartcasts } // smartcast either if the value is immutable or if the mut argument is explicitly given diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index fcd9e46756..5049b8b242 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -2164,9 +2164,9 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) mut field_typ := field.typ if field.typ.has_flag(.option) { // unwrapped callback (if f.func != none {}) - if scope_field := node.scope.find_struct_field(node.left.str(), node.left_type, + scope_field := node.scope.find_struct_field(node.left.str(), node.left_type, method_name) - { + if scope_field != unsafe { nil } { field_typ = scope_field.smartcasts.last() node.is_unwrapped_fn_selector = true } else { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index ff18c04f2e..000575fd8e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3008,7 +3008,8 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ } } } else if expr is ast.SelectorExpr { - if v := scope.find_struct_field(expr.expr.str(), expr.expr_type, expr.field_name) { + v := scope.find_struct_field(expr.expr.str(), expr.expr_type, expr.field_name) + if v != unsafe { nil } { if v.smartcasts.len > 0 && unwrapped_expected_type == v.orig_type { is_already_sum_type = true } @@ -4178,7 +4179,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { if !prevent_sum_type_unwrapping_once { // check first if field is sum type because scope searching is expensive scope := g.file.scope.innermost(node.pos.pos) - if field := scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) { + field := scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) + if field != unsafe { nil } { nested_unwrap := is_option && field.smartcasts.len > 1 is_option_unwrap = is_option && field.smartcasts.len > 0 && field.typ.clear_flag(.option) == field.smartcasts.last() diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 188c4fd5c8..7e41da7a4c 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -1125,7 +1125,8 @@ fn (mut g Gen) comptime_selector_type(node ast.SelectorExpr) ast.Type { field_sym := g.table.sym(field.typ) if field_sym.kind in [.sum_type, .interface] { if !prevent_sum_type_unwrapping_once { - if scope_field := node.scope.find_struct_field(node.expr.str(), typ, field_name) { + scope_field := node.scope.find_struct_field(node.expr.str(), typ, field_name) + if scope_field != unsafe { nil } { return scope_field.smartcasts.last() } } diff --git a/vlib/v/type_resolver/comptime_resolver.v b/vlib/v/type_resolver/comptime_resolver.v index e3eed8a580..af37d42c24 100644 --- a/vlib/v/type_resolver/comptime_resolver.v +++ b/vlib/v/type_resolver/comptime_resolver.v @@ -75,7 +75,8 @@ pub fn (mut t TypeResolver) typeof_type(node ast.Expr, default_type ast.Type) as if node.expr is ast.Ident && node.is_field_typ { return t.get_type_from_comptime_var(node.expr) } - if field := node.scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) { + field := node.scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) + if field != unsafe { nil } { if field.smartcasts.len > 0 { return field.smartcasts.last() } diff --git a/vlib/v/type_resolver/type_resolver.v b/vlib/v/type_resolver/type_resolver.v index 05a8f9b49c..4586a4ba5e 100644 --- a/vlib/v/type_resolver/type_resolver.v +++ b/vlib/v/type_resolver/type_resolver.v @@ -234,9 +234,9 @@ pub fn (mut t TypeResolver) get_type(node ast.Expr) ast.Type { // Struct[T] can have field with generic type if struct_sym.info is ast.Struct && struct_sym.info.generic_types.len > 0 { if field := t.table.find_field(struct_sym, node.field_name) { - if f_unwrap := node.scope.find_struct_field(ast.Expr(node.expr).str(), + f_unwrap := node.scope.find_struct_field(ast.Expr(node.expr).str(), t.get_type_or_default(node.expr, node.expr_type), node.field_name) - { + if f_unwrap != unsafe { nil } { return f_unwrap.smartcasts.last() } return field.typ