diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 4727f9eeb9..69700b25f7 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -905,7 +905,8 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) { } } - if arg.expr.is_auto_deref_var() { + if arg.expr.is_auto_deref_var() || (arg.expr is ast.ComptimeSelector + && (arg.expr as ast.ComptimeSelector).left.is_auto_deref_var()) { typ = typ.deref() } // resolve &T &&T ... diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index df5dfecc23..27a98ae55a 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1027,6 +1027,7 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret if !param.typ.has_flag(.generic) { continue } + param_typ := param.typ if mut call_arg.expr is ast.Ident { if mut call_arg.expr.obj is ast.Var { node_.args[i].typ = call_arg.expr.obj.typ @@ -1034,7 +1035,6 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret mut ctyp := g.get_comptime_var_type(call_arg.expr) if ctyp != ast.void_type { arg_sym := g.table.sym(ctyp) - param_typ := param.typ if arg_sym.kind == .array && param_typ.has_flag(.generic) && g.table.final_sym(param_typ).kind == .array { ctyp = (arg_sym.info as ast.Array).elem_type @@ -1044,10 +1044,8 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret } else if call_arg.expr.obj.ct_type_var == .generic_param { mut ctyp := g.get_comptime_var_type(call_arg.expr) if ctyp != ast.void_type { - param_typ := param.typ arg_sym := g.table.final_sym(call_arg.typ) param_typ_sym := g.table.sym(param_typ) - if param_typ.has_flag(.variadic) { ctyp = ast.mktyp(ctyp) comptime_args[i] = ctyp @@ -1098,6 +1096,12 @@ fn (mut g Gen) change_comptime_args(func ast.Fn, mut node_ ast.CallExpr, concret } } else if mut call_arg.expr is ast.ComptimeSelector { comptime_args[i] = g.comptime_for_field_type + if call_arg.expr.left.is_auto_deref_var() { + comptime_args[i] = comptime_args[i].deref() + } + if param_typ.nr_muls() > 0 && comptime_args[i].nr_muls() > 0 { + comptime_args[i] = comptime_args[i].set_nr_muls(0) + } } } } diff --git a/vlib/v/tests/comptime_selector_ptr_test.v b/vlib/v/tests/comptime_selector_ptr_test.v new file mode 100644 index 0000000000..fc03eb0c9f --- /dev/null +++ b/vlib/v/tests/comptime_selector_ptr_test.v @@ -0,0 +1,46 @@ +struct Encoder {} + +struct Writer {} + +struct APrice {} + +struct Association { + association &Association = unsafe { nil } + price APrice +} + +fn get_value_from_ref[T](val &T) T { + return *val +} + +fn (e &Encoder) encode_struct[U](val U, mut wr Writer) ! { + $for field in U.fields { + $if field.typ is &Association { + assert get_value_from_ref(val.$(field.name)) == Association{ + association: unsafe { nil } + price: APrice{} + } + } + } +} + +fn test_main() { + e := Encoder{} + mut sb := Writer{} + + value := Association{ + association: &Association{ + price: APrice{} + } + price: APrice{} + } + + assert get_value_from_ref(&Association{ + price: APrice{} + }) == Association{ + association: unsafe { nil } + price: APrice{} + } + + e.encode_struct(value, mut sb)! +}