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

checker: fix generics with nested external generics fn (#9933)

This commit is contained in:
yuyi 2021-04-29 22:37:54 +08:00 committed by GitHub
parent e9bbb7de3a
commit ea0ac09297
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 23 deletions

View File

@ -197,11 +197,14 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
// post process generic functions. must be done after all files have been // post process generic functions. must be done after all files have been
// checked, to eunsure all generic calls are processed as this information // checked, to eunsure all generic calls are processed as this information
// is needed when the generic type is auto inferred from the call argument // is needed when the generic type is auto inferred from the call argument
for i in 0 .. ast_files.len { // Check 2 times (in order to check nested generics fn)
file := unsafe { &ast_files[i] } for _ in 0 .. 2 {
if file.generic_fns.len > 0 { for i in 0 .. ast_files.len {
c.change_current_file(file) file := unsafe { &ast_files[i] }
c.post_process_generic_fns() if file.generic_fns.len > 0 {
c.change_current_file(file)
c.post_process_generic_fns()
}
} }
} }
// restore the original c.file && c.mod after post processing // restore the original c.file && c.mod after post processing
@ -1990,7 +1993,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
} }
} }
if has_generic { if has_generic {
if c.mod != '' && !fn_name.starts_with('${c.mod}.') { if c.mod != '' && !fn_name.contains('.') {
// Need to prepend the module when adding a generic type to a function // Need to prepend the module when adding a generic type to a function
c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types) c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types)
} else { } else {
@ -6573,24 +6576,21 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Positi
fn (mut c Checker) post_process_generic_fns() { fn (mut c Checker) post_process_generic_fns() {
// Loop thru each generic function concrete type. // Loop thru each generic function concrete type.
// Check each specific fn instantiation. // Check each specific fn instantiation.
// Check 2 times (in order to check nested generics fn) for i in 0 .. c.file.generic_fns.len {
for _ in 0 .. 2 { if c.table.fn_generic_types.len == 0 {
for i in 0 .. c.file.generic_fns.len { // no concrete types, so just skip:
if c.table.fn_generic_types.len == 0 { continue
// no concrete types, so just skip:
continue
}
mut node := c.file.generic_fns[i]
c.mod = node.mod
for generic_types in c.table.fn_generic_types[node.name] {
node.cur_generic_types = generic_types
c.fn_decl(mut node)
if node.name in ['vweb.run_app', 'vweb.run'] {
c.vweb_gen_types << generic_types
}
}
node.cur_generic_types = []
} }
mut node := c.file.generic_fns[i]
c.mod = node.mod
for generic_types in c.table.fn_generic_types[node.name] {
node.cur_generic_types = generic_types
c.fn_decl(mut node)
if node.name in ['vweb.run_app', 'vweb.run'] {
c.vweb_gen_types << generic_types
}
}
node.cur_generic_types = []
} }
} }

View File

@ -0,0 +1,21 @@
import rand.util
import rand
pub fn sample<T>(arr []T, k int) []T {
mut result := arr.clone()
rand.seed([u32(1), 2]) // set seed to produce same results in order
util.shuffle<T>(mut result, k)
return result[0..k]
}
fn test_generics_with_nested_external_generics_fn() {
mut arr := [11, 32, 24, 45, 57, 32, 37, 52, 37, 24]
println(arr)
ret := sample<int>(arr, 5)
println(ret)
assert ret == [32, 45, 57, 11, 37]
}