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]
|
mut a := t.fn_generic_types[fn_name]
|
||||||
if types in a {
|
if types in a {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
a << types
|
a << types
|
||||||
t.fn_generic_types[fn_name] = a
|
t.fn_generic_types[fn_name] = a
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there is a bug when casting sumtype the other way if its pointer
|
// 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
|
inferred_types << typ
|
||||||
call_expr.concrete_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
|
main_fn_decl_node ast.FnDecl
|
||||||
match_exhaustive_cutoff_limit int = 10
|
match_exhaustive_cutoff_limit int = 10
|
||||||
// TODO: these are here temporarily and used for deprecations; remove soon
|
// TODO: these are here temporarily and used for deprecations; remove soon
|
||||||
using_new_err_struct bool
|
using_new_err_struct bool
|
||||||
inside_selector_expr bool
|
inside_selector_expr bool
|
||||||
inside_println_arg bool
|
inside_println_arg bool
|
||||||
inside_decl_rhs 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 {
|
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
|
// 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)
|
// Check more times if there are more new registered fn concrete types
|
||||||
for _ in 0 .. 2 {
|
for {
|
||||||
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 {
|
||||||
|
@ -206,6 +207,12 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
c.post_process_generic_fns()
|
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
|
// restore the original c.file && c.mod after post processing
|
||||||
c.change_current_file(last_file)
|
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 {
|
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
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
// FIXME: Argument count != 1 will break these
|
// 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 {
|
if has_generic {
|
||||||
|
mut no_exists := true
|
||||||
if c.mod != '' && !fn_name.contains('.') {
|
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)
|
no_exists = c.table.register_fn_concrete_types(c.mod + '.' + fn_name, concrete_types)
|
||||||
} else {
|
} 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' {
|
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