Skip to content

Commit

Permalink
cgen, checker: fix comptimeselector passing to generic argument (vlan…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Mar 9, 2024
1 parent c48abe5 commit da62854
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
3 changes: 2 additions & 1 deletion vlib/v/checker/check_types.v
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, lan
return error('cannot use `${got_typ_str}` as `${expected_typ_str}`')
}

if !expected.has_flag(.option) && got.has_flag(.option) && (arg.expr !is ast.Ident
if !expected.has_flag(.option) && got.has_flag(.option)
&& (!(arg.expr is ast.Ident || arg.expr is ast.ComptimeSelector)
|| (arg.expr is ast.Ident && c.comptime.get_ct_type_var(arg.expr) != .field_var)) {
got_typ_str, expected_typ_str := c.get_string_names_of(got, expected)
return error('cannot use `${got_typ_str}` as `${expected_typ_str}`, it must be unwrapped first')
Expand Down
8 changes: 8 additions & 0 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -2578,6 +2578,14 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as
g.write('(${g.typ(arg.expr.typ)})')
}
}
} else if arg.expr is ast.ComptimeSelector && arg_typ.has_flag(.option)
&& !expected_type.has_flag(.option) {
// allow to pass val.$(filed.name) where T is expected, doing automatic unwrap in this case
styp := g.base_type(arg_typ)
g.write('*(${styp}*)')
g.expr_with_cast(arg.expr, arg_typ, expected_type)
g.write('.data')
return
}
// check if the argument must be dereferenced or not
g.arg_no_auto_deref = is_smartcast && !arg_is_ptr && !exp_is_ptr && arg.should_be_ptr
Expand Down
40 changes: 40 additions & 0 deletions vlib/v/tests/comptime_selector_generic_arg_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
struct Struc {
a string
b int
c ?string
d ?int
}

pub struct Count {
mut:
total int
}

// count_chars count json sizen whithout new encode
pub fn (mut count Count) count_chars[T](val T) {
$if val is $option {
workaround := val
if workaround != none {
count.count_chars(val)
}
} $else $if T is $struct {
count.chars_in_struct(val)
} $else {
}
}

// chars_in_struct
fn (mut count Count) chars_in_struct[T](val T) {
$for field in T.fields {
va := val.$(field.name)
count.count_chars(va) // works
count.count_chars(val.$(field.name)) // Not works
}
}

fn test_main() {
struc := Struc{}
mut count := Count{}
count.count_chars(struc)
assert true
}

0 comments on commit da62854

Please sign in to comment.