diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ebc28828ab..19af18757d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -4658,19 +4658,15 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type { c.ensure_type_exists(node.typ, node.pos) or {} if !c.table.sumtype_has_variant(node.expr_type, node.typ) { c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos) - // c.error('only $info.variants can be casted to `$typ`', node.pos) } } else { - mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`' - if type_sym.kind == .sum_type { - s += ' - use e.g. `${type_sym.name}(some_expr)` instead.' - } - c.error(s, node.pos) + // mut s := 'cannot cast non-sum type `$expr_type_sym.name` using `as`' + // if type_sym.kind == .sum_type { + // s += ' - use e.g. `${type_sym.name}(some_expr)` instead.' + // } + // c.error(s, node.pos) } - if expr_type_sym.kind == .sum_type { - return node.typ - } - return node.typ.to_ptr() + return node.typ } ast.Assoc { v := node.scope.find_var(node.var_name) or { panic(err) } @@ -6038,50 +6034,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { c.skip_flags = cur_skip_flags } else { // smartcast sumtypes and interfaces when using `is` - pos := branch.cond.position() - if branch.cond is ast.InfixExpr { - if branch.cond.op == .key_is { - right_expr := branch.cond.right - right_type := match right_expr { - ast.TypeNode { - right_expr.typ - } - ast.None { - ast.none_type_idx - } - else { - c.error('invalid type `$right_expr`', right_expr.position()) - ast.Type(0) - } - } - if right_type != ast.Type(0) { - left_sym := c.table.get_type_symbol(branch.cond.left_type) - expr_type := c.expr(branch.cond.left) - if left_sym.kind == .interface_ { - c.type_implements(right_type, expr_type, pos) - } else if !c.check_types(right_type, expr_type) { - expect_str := c.table.type_to_str(right_type) - expr_str := c.table.type_to_str(expr_type) - c.error('cannot use type `$expect_str` as type `$expr_str`', - pos) - } - if (branch.cond.left is ast.Ident || branch.cond.left is ast.SelectorExpr) - && branch.cond.right is ast.TypeNode { - is_variable := if mut branch.cond.left is ast.Ident { - branch.cond.left.kind == .variable - } else { - true - } - if is_variable { - if left_sym.kind in [.interface_, .sum_type] { - c.smartcast(branch.cond.left, branch.cond.left_type, - right_type, mut branch.scope) - } - } - } - } - } - } + c.smartcast_if_conds(branch.cond, mut branch.scope) c.stmts(branch.stmts) } if expr_required { diff --git a/vlib/v/checker/tests/is_type_invalid.out b/vlib/v/checker/tests/is_type_invalid.out index 1b1d193a0c..0459e96ec5 100644 --- a/vlib/v/checker/tests/is_type_invalid.out +++ b/vlib/v/checker/tests/is_type_invalid.out @@ -5,10 +5,10 @@ vlib/v/checker/tests/is_type_invalid.vv:14:12: error: `IoS` has no variant `byte | ~~ 15 | println('not cool') 16 | } -vlib/v/checker/tests/is_type_invalid.vv:18:5: error: `Cat` doesn't implement method `speak` of interface `Animal` +vlib/v/checker/tests/is_type_invalid.vv:18:7: error: `Cat` doesn't implement method `speak` of interface `Animal` 16 | } 17 | a := Animal(Dog{}) 18 | if a is Cat { - | ~~~~~~~~ + | ~~ 19 | println('not cool either') 20 | } diff --git a/vlib/v/checker/tests/sum.out b/vlib/v/checker/tests/sum.out deleted file mode 100644 index 5c92692ca7..0000000000 --- a/vlib/v/checker/tests/sum.out +++ /dev/null @@ -1,28 +0,0 @@ -vlib/v/checker/tests/sum.vv:5:8: error: cannot cast non-sum type `int` using `as` - 3 | fn non_sum() { - 4 | v := 4 - 5 | _ = v as rune - | ~~ - 6 | _ = v as Var - 7 | } -vlib/v/checker/tests/sum.vv:6:8: error: cannot cast non-sum type `int` using `as` - use e.g. `Var(some_expr)` instead. - 4 | v := 4 - 5 | _ = v as rune - 6 | _ = v as Var - | ~~ - 7 | } - 8 | -vlib/v/checker/tests/sum.vv:10:7: error: cannot cast `rune` to `Var` - 8 | - 9 | fn sum() { - 10 | _ := Var(`J`) - | ~~~~~~~~ - 11 | mut s2 := Var('') - 12 | s2 = true -vlib/v/checker/tests/sum.vv:12:7: error: cannot assign to `s2`: expected `Var`, not `bool` - 10 | _ := Var(`J`) - 11 | mut s2 := Var('') - 12 | s2 = true - | ~~~~ - 13 | _ = s2 - 14 | } diff --git a/vlib/v/checker/tests/sum.vv b/vlib/v/checker/tests/sum.vv deleted file mode 100644 index 6796a2e58f..0000000000 --- a/vlib/v/checker/tests/sum.vv +++ /dev/null @@ -1,14 +0,0 @@ -type Var = int | string - -fn non_sum() { - v := 4 - _ = v as rune - _ = v as Var -} - -fn sum() { - _ := Var(`J`) - mut s2 := Var('') - s2 = true - _ = s2 -} diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index ef148c8bce..8b9f8e0e6c 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -301,8 +301,8 @@ fn (f Fmt) should_insert_newline_before_node(node ast.Node, prev_node ast.Node) prev_line_nr := prev_node.position().last_line // The nodes are Stmts if node is ast.Stmt && prev_node is ast.Stmt { - stmt := node as ast.Stmt - prev_stmt := prev_node as ast.Stmt + stmt := node + prev_stmt := prev_node // Force a newline after a block of HashStmts if prev_stmt is ast.HashStmt && stmt !is ast.HashStmt && stmt !is ast.ExprStmt { return true @@ -1662,8 +1662,7 @@ pub fn (mut f Fmt) call_args(args []ast.CallArg) { } for i, arg in args { if i == args.len - 1 && arg.expr is ast.StructInit { - struct_expr := arg.expr as ast.StructInit - if struct_expr.typ == ast.void_type { + if arg.expr.typ == ast.void_type { f.use_short_fn_args = true } } @@ -2477,7 +2476,7 @@ pub fn (mut f Fmt) prefix_expr_cast_expr(node ast.Expr) { mut is_pe_amp_ce := false if node is ast.PrefixExpr { if node.right is ast.CastExpr && node.op == .amp { - mut ce := node.right as ast.CastExpr + mut ce := node.right ce.typname = f.table.get_type_symbol(ce.typ).name is_pe_amp_ce = true f.expr(ce) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index ac9f35ce17..75382d2362 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6422,6 +6422,8 @@ fn (mut g Gen) as_cast(node ast.AsCast) { variant_sym := g.table.get_type_symbol(variant) g.as_cast_type_names[idx] = variant_sym.name } + } else { + g.expr(node.expr) } } diff --git a/vlib/v/tests/if_smartcast_multi_conds_test.v b/vlib/v/tests/if_smartcast_multi_conds_test.v new file mode 100644 index 0000000000..5d4ac8ce1e --- /dev/null +++ b/vlib/v/tests/if_smartcast_multi_conds_test.v @@ -0,0 +1,47 @@ +struct Empty {} + +struct SourcePosition { + source_line u32 + source_column u32 +} + +type SourcePositionType = Empty | SourcePosition +type NameIndexType = Empty | u32 + +struct GenPosition { + gen_line u32 + gen_column u32 +} + +struct Mapping { + GenPosition + sources_ind u32 + names_ind NameIndexType + source_position SourcePositionType +} + +fn ok(mapping_a Mapping, mapping_b Mapping) bool { + if mapping_a.source_position is SourcePosition && mapping_b.source_position is SourcePosition { + return mapping_a.source_position.source_line != mapping_b.source_position.source_line + || mapping_a.source_position.source_column != mapping_b.source_position.source_column + } + return false +} + +fn test_if_smartcast_multi_conds() { + a := Mapping{ + source_position: SourcePosition{ + source_line: 11 + source_column: 22 + } + } + b := Mapping{ + source_position: SourcePosition{ + source_line: 22 + source_column: 11 + } + } + ret := ok(a, b) + println(ret) + assert ret +}