parent
ae22967d1d
commit
581fe375cc
|
@ -932,13 +932,14 @@ pub fn (t &Table) mktyp(typ Type) Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut t Table) register_fn_concrete_types(fn_name string, types []Type) {
|
||||
pub fn (mut t Table) register_fn_concrete_types(fn_name string, types []Type) bool {
|
||||
mut a := t.fn_generic_types[fn_name]
|
||||
if types in a {
|
||||
return
|
||||
return false
|
||||
}
|
||||
a << types
|
||||
t.fn_generic_types[fn_name] = a
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: there is a bug when casting sumtype the other way if its pointer
|
||||
|
|
|
@ -571,5 +571,7 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx
|
|||
inferred_types << typ
|
||||
call_expr.concrete_types << typ
|
||||
}
|
||||
c.table.register_fn_concrete_types(f.name, inferred_types)
|
||||
if c.table.register_fn_concrete_types(f.name, inferred_types) {
|
||||
c.need_recheck_generic_fns = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,10 +83,11 @@ mut:
|
|||
main_fn_decl_node ast.FnDecl
|
||||
match_exhaustive_cutoff_limit int = 10
|
||||
// TODO: these are here temporarily and used for deprecations; remove soon
|
||||
using_new_err_struct bool
|
||||
inside_selector_expr bool
|
||||
inside_println_arg bool
|
||||
inside_decl_rhs bool
|
||||
using_new_err_struct bool
|
||||
inside_selector_expr bool
|
||||
inside_println_arg bool
|
||||
inside_decl_rhs bool
|
||||
need_recheck_generic_fns bool // need recheck generic fns because there are cascaded nested generic fn
|
||||
}
|
||||
|
||||
pub fn new_checker(table &ast.Table, pref &pref.Preferences) Checker {
|
||||
|
@ -197,8 +198,8 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||
// post process generic functions. must be done after all files have been
|
||||
// checked, to eunsure all generic calls are processed as this information
|
||||
// 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 {
|
||||
// Check more times if there are more new registered fn concrete types
|
||||
for {
|
||||
for i in 0 .. ast_files.len {
|
||||
file := unsafe { &ast_files[i] }
|
||||
if file.generic_fns.len > 0 {
|
||||
|
@ -206,6 +207,12 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||
c.post_process_generic_fns()
|
||||
}
|
||||
}
|
||||
if c.need_recheck_generic_fns {
|
||||
c.need_recheck_generic_fns = false
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// restore the original c.file && c.mod after post processing
|
||||
c.change_current_file(last_file)
|
||||
|
@ -1657,7 +1664,9 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
if has_generic {
|
||||
c.table.register_fn_concrete_types(call_expr.name, concrete_types)
|
||||
if c.table.register_fn_concrete_types(call_expr.name, concrete_types) {
|
||||
c.need_recheck_generic_fns = true
|
||||
}
|
||||
}
|
||||
// TODO: remove this for actual methods, use only for compiler magic
|
||||
// FIXME: Argument count != 1 will break these
|
||||
|
@ -2117,11 +2126,15 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
if has_generic {
|
||||
mut no_exists := true
|
||||
if c.mod != '' && !fn_name.contains('.') {
|
||||
// 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)
|
||||
no_exists = c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types)
|
||||
} else {
|
||||
c.table.register_fn_concrete_types(fn_name, concrete_types)
|
||||
no_exists = c.table.register_fn_concrete_types(fn_name, concrete_types)
|
||||
}
|
||||
if no_exists {
|
||||
c.need_recheck_generic_fns = true
|
||||
}
|
||||
}
|
||||
if fn_name == 'json.encode' {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
fn gfn1<T>(var T) T {
|
||||
return var
|
||||
}
|
||||
|
||||
fn gfn2<T>(var T) T {
|
||||
return gfn1<T>(var)
|
||||
}
|
||||
|
||||
fn gfn3<T>(var T) T {
|
||||
return gfn2<T>(var)
|
||||
}
|
||||
|
||||
fn gfn4<T>(var T) T {
|
||||
return gfn3<T>(var)
|
||||
}
|
||||
|
||||
// don't give concrete types
|
||||
fn gfn2_infer<T>(var T) T {
|
||||
return gfn1(var)
|
||||
}
|
||||
|
||||
fn gfn3_infer<T>(var T) T {
|
||||
return gfn2_infer(var)
|
||||
}
|
||||
|
||||
fn gfn4_infer<T>(var T) T {
|
||||
return gfn3_infer(var)
|
||||
}
|
||||
|
||||
fn test_generics_with_cascaded_multiple_nested_generics_fn() {
|
||||
println(gfn4(1234))
|
||||
assert gfn4(1234) == 1234
|
||||
println(gfn4_infer(1234))
|
||||
assert gfn4_infer(1234) == 1234
|
||||
}
|
Loading…
Reference in New Issue