1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix generic with multi-nested generic method call ref argument (#15421)

This commit is contained in:
yuyi 2022-08-14 00:26:00 +08:00 committed by GitHub
parent 672066b65b
commit 9734148f12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 3 deletions

View File

@ -2247,8 +2247,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
deref_sym := g.table.sym(got_deref_type)
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
got_is_opt := got_type.has_flag(.optional)
if deref_will_match || got_is_opt || expr.is_auto_deref_var()
|| expected_type.has_flag(.generic) {
if deref_will_match || got_is_opt || expr.is_auto_deref_var() {
g.write('*')
}
}

View File

@ -980,7 +980,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
}
}
}
name = g.generic_fn_name(node.concrete_types, name, false)
concrete_types := node.concrete_types.map(g.unwrap_generic(it))
name = g.generic_fn_name(concrete_types, name, false)
// TODO2
// g.generate_tmp_autofree_arg_vars(node, name)
if !node.receiver_type.is_ptr() && left_type.is_ptr() && node.name == 'str' {

View File

@ -0,0 +1,109 @@
struct Wrapper<S> {
mut:
calc Calc<S>
}
fn (mut w Wrapper<S>) next<T>(input T) f64 {
$if S is TypeA || S is TypeB {
$if T is f64 {
return w.calc.next(input)
} $else $if T is SecretCase {
return w.calc.next(input)
} $else {
panic('"$T.name" is not supported')
return -1
}
return -1
} $else {
panic('"$S.name" is not supported')
return -1
}
}
struct Calc<S> {
mut:
typ S
inner InnerCalc
}
struct InnerCalc {}
fn (mut c InnerCalc) next<T>(input T) f64 {
$if T is f64 {
return 64.2
} $else {
return 100.0
}
}
struct TypeA {}
struct TypeB {}
interface SecretCase {
secret() f64
}
interface SpecialCase {
SecretCase
}
struct SecretSkill {}
fn (s &SecretSkill) secret() f64 {
return 101.0
}
fn (mut c Calc<S>) next<T>(input T) f64 {
$if S is TypeA || S is TypeB {
$if T is f64 {
return c.typ.next(input)
} $else $if T is SpecialCase {
return c.typ.next(input)
} $else {
panic('Unsupported type $T.name')
}
} $else {
panic('Unsupported type $S.name')
}
}
fn (mut t TypeA) next<T>(input T) f64 {
return 10
}
fn (mut t TypeB) next<T>(input T) f64 {
return 11
}
fn new<S>() Wrapper<S> {
$if S is TypeA {
return Wrapper<TypeA>{
calc: Calc<TypeA>{
typ: TypeA{}
}
}
} $else $if S is TypeB {
return Wrapper<TypeB>{
calc: Calc<TypeB>{
typ: TypeB{}
}
}
} $else {
panic('unknown type $S.name')
}
}
fn test_generics_with_multi_nested_generic_method_call_ref_arg() {
{
mut c := new<TypeA>()
s := SecretSkill{}
assert c.next(&s) == 10.0
}
{
mut c := new<TypeB>()
s := SecretSkill{}
assert c.next(&s) == 11.0
}
println('OK!!')
}