checker: fix generics with nested external generics fn (#9933)
parent
e9bbb7de3a
commit
ea0ac09297
|
@ -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:
|
||||||
|
@ -6592,7 +6593,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) {
|
||||||
c.returns = false
|
c.returns = false
|
||||||
|
|
|
@ -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]
|
||||||
|
}
|
Loading…
Reference in New Issue