checker: check or block inside println calls (#10354)

pull/10359/head
Lukas Neubert 2021-06-05 22:01:58 +02:00 committed by GitHub
parent 9924f6c54b
commit 3f00ff465b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 15 additions and 18 deletions

View File

@ -2416,6 +2416,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
c.inside_println_arg = true
c.expected_type = ast.string_type
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() {
c.error('`$fn_name` can not print void expressions', call_expr.pos)
}

View File

@ -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 | }

View File

@ -0,0 +1,7 @@
fn funcy() ?int {
return none
}
fn main() {
println(funcy() or { '' })
}

View File

@ -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
// 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)
// println('parse_file("$path")')
// text := os.read_file(path) or {
// panic(err)
// }
mut p := Parser{
scanner: scanner.new_scanner_file(path, comments_mode, pref)
comments_mode: comments_mode
@ -274,7 +270,6 @@ pub fn (mut p Parser) parse() &ast.File {
p.check_unused_imports()
break
}
// println('stmt at ' + p.tok.str())
stmt := p.top_stmt()
// clear the attributes after each statement
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
}
// println('nr stmts = $stmts.len')
// println(stmts[0])
p.scope.end_pos = p.tok.pos
//
return &ast.File{
path: p.file_name
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 ? {
timers.should_print = true
}
// println('nr_cpus= $nr_cpus')
$if macos {
/*
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{}
for path in paths {
// println('parse_files $path')
timers.start('parse_file $path')
files << parse_file(path, table, .skip_comments, pref, global_scope)
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 {
p.open_scope()
// println('parse block')
stmts := p.parse_block_no_scope(false)
p.close_scope()
// println('nr exprs in block = $exprs.len')
return stmts
}
@ -2089,7 +2076,6 @@ pub fn (mut p Parser) name_expr() ast.Expr {
return node
} else {
// fn call
// println('calling $p.tok.lit')
if is_optional {
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 {
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)
val := p.check_name()
// println('enum val $enum_name . $val')
p.expr_mod = ''
return ast.EnumVal{
enum_name: enum_name
@ -3178,7 +3162,6 @@ fn (mut p Parser) assoc() ast.Assoc {
}
}
v.is_used = true
// println('assoc var $name typ=$var.typ')
mut fields := []string{}
mut vals := []ast.Expr{}
p.check(.pipe)

View File

@ -121,6 +121,6 @@ pub fn iter_data<T>(data []T) Iterator<T> {
fn test_generics_return_generic_struct_from_fn() {
mut it := iter_data<int>([1, 2, 3])
println(it.next())
println(it.next() or { -1 })
assert '$it.next()' == 'Option(1)'
}