checker,cgen: stabilise generic method handling (fix a source code ordering issue)
parent
b3161b05a3
commit
e256f1b2aa
|
@ -488,6 +488,7 @@ pub mut:
|
||||||
return_type_pos token.Position // `string` in `fn (u User) name() string` position
|
return_type_pos token.Position // `string` in `fn (u User) name() string` position
|
||||||
has_return bool
|
has_return bool
|
||||||
should_be_skipped bool // true, when -skip-unused could not find any usages of that function, starting from main + other known used functions
|
should_be_skipped bool // true, when -skip-unused could not find any usages of that function, starting from main + other known used functions
|
||||||
|
ninstances int // 0 for generic functions with no concrete instances
|
||||||
has_await bool // 'true' if this function uses JS.await
|
has_await bool // 'true' if this function uses JS.await
|
||||||
//
|
//
|
||||||
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
||||||
|
|
|
@ -291,7 +291,7 @@ pub fn (mut c Checker) check_files(ast_files []&ast.File) {
|
||||||
c.timers.start('checker_post_process_generic_fns')
|
c.timers.start('checker_post_process_generic_fns')
|
||||||
last_file := c.file
|
last_file := c.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 ensure 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 more times if there are more new registered fn concrete types
|
// Check more times if there are more new registered fn concrete types
|
||||||
for {
|
for {
|
||||||
|
@ -4831,7 +4831,11 @@ fn (mut c Checker) post_process_generic_fns() {
|
||||||
for i in 0 .. c.file.generic_fns.len {
|
for i in 0 .. c.file.generic_fns.len {
|
||||||
mut node := c.file.generic_fns[i]
|
mut node := c.file.generic_fns[i]
|
||||||
c.mod = node.mod
|
c.mod = node.mod
|
||||||
for concrete_types in c.table.fn_generic_types[node.name] {
|
gtypes := c.table.fn_generic_types[node.name]
|
||||||
|
$if trace_post_process_generic_fns ? {
|
||||||
|
eprintln('> post_process_generic_fns $node.mod | $node.name | $gtypes')
|
||||||
|
}
|
||||||
|
for concrete_types in gtypes {
|
||||||
c.table.cur_concrete_types = concrete_types
|
c.table.cur_concrete_types = concrete_types
|
||||||
c.fn_decl(mut node)
|
c.fn_decl(mut node)
|
||||||
if node.name == 'vweb.run' {
|
if node.name == 'vweb.run' {
|
||||||
|
@ -4843,6 +4847,11 @@ fn (mut c Checker) post_process_generic_fns() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.table.cur_concrete_types = []
|
c.table.cur_concrete_types = []
|
||||||
|
$if trace_post_process_generic_fns ? {
|
||||||
|
if node.generic_names.len > 0 {
|
||||||
|
eprintln(' > fn_decl node.name: $node.name | generic_names: $node.generic_names | ninstances: $node.ninstances')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
// have a chance to populate c.table.fn_generic_types with
|
// have a chance to populate c.table.fn_generic_types with
|
||||||
// the correct concrete types.
|
// the correct concrete types.
|
||||||
c.file.generic_fns << node
|
c.file.generic_fns << node
|
||||||
|
c.need_recheck_generic_fns = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
node.ninstances++
|
||||||
// save all the state that fn_decl or inner statements/expressions
|
// save all the state that fn_decl or inner statements/expressions
|
||||||
// could potentially modify, since functions can be nested, due to
|
// could potentially modify, since functions can be nested, due to
|
||||||
// anonymous function support, and ensure that it is restored, when
|
// anonymous function support, and ensure that it is restored, when
|
||||||
|
|
|
@ -4855,6 +4855,10 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
has_semicolon = true
|
has_semicolon = true
|
||||||
}
|
}
|
||||||
} else if node.exprs.len >= 1 {
|
} else if node.exprs.len >= 1 {
|
||||||
|
if node.types.len == 0 {
|
||||||
|
g.checker_bug('node.exprs.len == $node.exprs.len && node.types.len == 0',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
// normal return
|
// normal return
|
||||||
return_sym := g.table.sym(node.types[0])
|
return_sym := g.table.sym(node.types[0])
|
||||||
expr0 := node.exprs[0]
|
expr0 := node.exprs[0]
|
||||||
|
|
|
@ -32,6 +32,12 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||||
if node.should_be_skipped {
|
if node.should_be_skipped {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if node.ninstances == 0 && node.generic_names.len > 0 {
|
||||||
|
$if trace_generics ? {
|
||||||
|
eprintln('skipping generic fn with no concrete instances: $node.mod $node.name')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if !g.is_used_by_main(node) {
|
if !g.is_used_by_main(node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -82,7 +88,8 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||||
if node.is_main {
|
if node.is_main {
|
||||||
g.has_main = true
|
g.has_main = true
|
||||||
}
|
}
|
||||||
is_backtrace := node.name.starts_with('backtrace') // TODO PERF remove this from here
|
// TODO PERF remove this from here
|
||||||
|
is_backtrace := node.name.starts_with('backtrace')
|
||||||
&& node.name in ['backtrace_symbols', 'backtrace', 'backtrace_symbols_fd']
|
&& node.name in ['backtrace_symbols', 'backtrace', 'backtrace_symbols_fd']
|
||||||
if is_backtrace {
|
if is_backtrace {
|
||||||
g.write('\n#ifndef __cplusplus\n')
|
g.write('\n#ifndef __cplusplus\n')
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
struct Foo<T> {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (f Foo<T>) pop() {
|
||||||
|
println('hey')
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar<T> {
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: Bar.foo before Bar.pop, should not cause a V compiler panic
|
||||||
|
fn (b Bar<T>) foo() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (b Bar<T>) pop() {
|
||||||
|
println(b.foo())
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn dummy() { println(Bar<int>{}) }
|
||||||
|
|
||||||
|
fn test_foo() {
|
||||||
|
dump(Foo<int>{})
|
||||||
|
assert true
|
||||||
|
}
|
Loading…
Reference in New Issue