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

pull/9936/head
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,6 +197,8 @@ 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
// Check 2 times (in order to check nested generics fn)
for _ in 0 .. 2 {
for i in 0 .. ast_files.len { for i in 0 .. ast_files.len {
file := unsafe { &ast_files[i] } file := unsafe { &ast_files[i] }
if file.generic_fns.len > 0 { if file.generic_fns.len > 0 {
@ -204,6 +206,7 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
c.post_process_generic_fns() 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
c.change_current_file(last_file) c.change_current_file(last_file)
c.timers.show('checker_post_process_generic_fns') c.timers.show('checker_post_process_generic_fns')
@ -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,8 +6576,6 @@ 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 _ in 0 .. 2 {
for i in 0 .. c.file.generic_fns.len { for i in 0 .. c.file.generic_fns.len {
if c.table.fn_generic_types.len == 0 { if c.table.fn_generic_types.len == 0 {
// no concrete types, so just skip: // no concrete types, so just skip:
@ -6591,7 +6592,6 @@ fn (mut c Checker) post_process_generic_fns() {
} }
node.cur_generic_types = [] node.cur_generic_types = []
} }
}
} }
fn (mut c Checker) fn_decl(mut node ast.FnDecl) { fn (mut c Checker) fn_decl(mut node ast.FnDecl) {

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]
}