checker: check or block inside println calls (#10354)
parent
9924f6c54b
commit
3f00ff465b
|
@ -2416,6 +2416,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
c.inside_println_arg = true
|
c.inside_println_arg = true
|
||||||
c.expected_type = ast.string_type
|
c.expected_type = ast.string_type
|
||||||
call_expr.args[0].typ = c.expr(call_expr.args[0].expr)
|
call_expr.args[0].typ = c.expr(call_expr.args[0].expr)
|
||||||
|
_ := c.check_expr_opt_call(call_expr.args[0].expr, call_expr.args[0].typ)
|
||||||
if call_expr.args[0].typ.is_void() {
|
if call_expr.args[0].typ.is_void() {
|
||||||
c.error('`$fn_name` can not print void expressions', call_expr.pos)
|
c.error('`$fn_name` can not print void expressions', call_expr.pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/optional_in_println_mismatch.vv:6:23: error: wrong return type `string` in the `or {}` block, expected `int`
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | println(funcy() or { '' })
|
||||||
|
| ~~
|
||||||
|
7 | }
|
|
@ -0,0 +1,7 @@
|
||||||
|
fn funcy() ?int {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println(funcy() or { '' })
|
||||||
|
}
|
|
@ -181,10 +181,6 @@ pub fn parse_file(path string, table &ast.Table, comments_mode scanner.CommentsM
|
||||||
// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
|
// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
|
||||||
// all the tricky inner comments. This is needed because we do not have a good general solution
|
// all the tricky inner comments. This is needed because we do not have a good general solution
|
||||||
// for handling them, and should be removed when we do (the general solution is also needed for vfmt)
|
// for handling them, and should be removed when we do (the general solution is also needed for vfmt)
|
||||||
// println('parse_file("$path")')
|
|
||||||
// text := os.read_file(path) or {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: scanner.new_scanner_file(path, comments_mode, pref)
|
scanner: scanner.new_scanner_file(path, comments_mode, pref)
|
||||||
comments_mode: comments_mode
|
comments_mode: comments_mode
|
||||||
|
@ -274,7 +270,6 @@ pub fn (mut p Parser) parse() &ast.File {
|
||||||
p.check_unused_imports()
|
p.check_unused_imports()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// println('stmt at ' + p.tok.str())
|
|
||||||
stmt := p.top_stmt()
|
stmt := p.top_stmt()
|
||||||
// clear the attributes after each statement
|
// clear the attributes after each statement
|
||||||
if !(stmt is ast.ExprStmt && (stmt as ast.ExprStmt).expr is ast.Comment) {
|
if !(stmt is ast.ExprStmt && (stmt as ast.ExprStmt).expr is ast.Comment) {
|
||||||
|
@ -282,10 +277,7 @@ pub fn (mut p Parser) parse() &ast.File {
|
||||||
}
|
}
|
||||||
stmts << stmt
|
stmts << stmt
|
||||||
}
|
}
|
||||||
// println('nr stmts = $stmts.len')
|
|
||||||
// println(stmts[0])
|
|
||||||
p.scope.end_pos = p.tok.pos
|
p.scope.end_pos = p.tok.pos
|
||||||
//
|
|
||||||
return &ast.File{
|
return &ast.File{
|
||||||
path: p.file_name
|
path: p.file_name
|
||||||
path_base: p.file_base
|
path_base: p.file_base
|
||||||
|
@ -343,7 +335,6 @@ pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, glo
|
||||||
$if time_parsing ? {
|
$if time_parsing ? {
|
||||||
timers.should_print = true
|
timers.should_print = true
|
||||||
}
|
}
|
||||||
// println('nr_cpus= $nr_cpus')
|
|
||||||
$if macos {
|
$if macos {
|
||||||
/*
|
/*
|
||||||
if pref.is_parallel && paths[0].contains('/array.v') {
|
if pref.is_parallel && paths[0].contains('/array.v') {
|
||||||
|
@ -367,10 +358,8 @@ pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, glo
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
// ///////////////
|
|
||||||
mut files := []&ast.File{}
|
mut files := []&ast.File{}
|
||||||
for path in paths {
|
for path in paths {
|
||||||
// println('parse_files $path')
|
|
||||||
timers.start('parse_file $path')
|
timers.start('parse_file $path')
|
||||||
files << parse_file(path, table, .skip_comments, pref, global_scope)
|
files << parse_file(path, table, .skip_comments, pref, global_scope)
|
||||||
timers.show('parse_file $path')
|
timers.show('parse_file $path')
|
||||||
|
@ -414,10 +403,8 @@ pub fn (mut p Parser) close_scope() {
|
||||||
|
|
||||||
pub fn (mut p Parser) parse_block() []ast.Stmt {
|
pub fn (mut p Parser) parse_block() []ast.Stmt {
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
// println('parse block')
|
|
||||||
stmts := p.parse_block_no_scope(false)
|
stmts := p.parse_block_no_scope(false)
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
// println('nr exprs in block = $exprs.len')
|
|
||||||
return stmts
|
return stmts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2089,7 +2076,6 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
return node
|
return node
|
||||||
} else {
|
} else {
|
||||||
// fn call
|
// fn call
|
||||||
// println('calling $p.tok.lit')
|
|
||||||
if is_optional {
|
if is_optional {
|
||||||
p.error_with_pos('unexpected $p.prev_tok', p.prev_tok.position())
|
p.error_with_pos('unexpected $p.prev_tok', p.prev_tok.position())
|
||||||
}
|
}
|
||||||
|
@ -2136,10 +2122,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
} else {
|
} else {
|
||||||
enum_name = p.imported_symbols[enum_name] or { p.prepend_mod(enum_name) }
|
enum_name = p.imported_symbols[enum_name] or { p.prepend_mod(enum_name) }
|
||||||
}
|
}
|
||||||
// p.warn('Color.green $enum_name ' + p.prepend_mod(enum_name) + 'mod=$mod')
|
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
val := p.check_name()
|
val := p.check_name()
|
||||||
// println('enum val $enum_name . $val')
|
|
||||||
p.expr_mod = ''
|
p.expr_mod = ''
|
||||||
return ast.EnumVal{
|
return ast.EnumVal{
|
||||||
enum_name: enum_name
|
enum_name: enum_name
|
||||||
|
@ -3178,7 +3162,6 @@ fn (mut p Parser) assoc() ast.Assoc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.is_used = true
|
v.is_used = true
|
||||||
// println('assoc var $name typ=$var.typ')
|
|
||||||
mut fields := []string{}
|
mut fields := []string{}
|
||||||
mut vals := []ast.Expr{}
|
mut vals := []ast.Expr{}
|
||||||
p.check(.pipe)
|
p.check(.pipe)
|
||||||
|
|
|
@ -121,6 +121,6 @@ pub fn iter_data<T>(data []T) Iterator<T> {
|
||||||
|
|
||||||
fn test_generics_return_generic_struct_from_fn() {
|
fn test_generics_return_generic_struct_from_fn() {
|
||||||
mut it := iter_data<int>([1, 2, 3])
|
mut it := iter_data<int>([1, 2, 3])
|
||||||
println(it.next())
|
println(it.next() or { -1 })
|
||||||
assert '$it.next()' == 'Option(1)'
|
assert '$it.next()' == 'Option(1)'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue