all: mutable smartcasts (#6878)
parent
48b117618d
commit
9feb010355
|
@ -533,7 +533,7 @@ pub:
|
|||
body_pos token.Position
|
||||
comments []Comment
|
||||
left_as_name string // `name` in `if cond is SumType as name`
|
||||
mut_name bool // `if mut name is`
|
||||
is_mut_name bool // `if mut name is`
|
||||
pub mut:
|
||||
stmts []Stmt
|
||||
smartcast bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
|
||||
|
|
|
@ -3516,21 +3516,41 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||
}
|
||||
mut scope := c.file.scope.innermost(branch.pos.pos)
|
||||
match node.cond as node_cond {
|
||||
ast.SelectorExpr { scope.register_struct_field(ast.ScopeStructField{
|
||||
struct_type: node_cond.expr_type
|
||||
name: node_cond.field_name
|
||||
typ: node.cond_type
|
||||
sum_type_cast: expr_type
|
||||
pos: node_cond.pos
|
||||
}) }
|
||||
ast.Ident { scope.register(node.var_name, ast.Var{
|
||||
name: node.var_name
|
||||
typ: node.cond_type
|
||||
pos: node_cond.pos
|
||||
is_used: true
|
||||
is_mut: node.is_mut
|
||||
sum_type_cast: expr_type
|
||||
}) }
|
||||
ast.SelectorExpr {
|
||||
expr_sym := c.table.get_type_symbol(node_cond.expr_type)
|
||||
field := c.table.struct_find_field(expr_sym, node_cond.field_name) or {
|
||||
table.Field{}
|
||||
}
|
||||
is_mut := field.is_mut
|
||||
is_root_mut := scope.is_selector_root_mutable(c.table, node_cond)
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if (!is_root_mut && !is_mut) || node.is_mut {
|
||||
scope.register_struct_field(ast.ScopeStructField{
|
||||
struct_type: node_cond.expr_type
|
||||
name: node_cond.field_name
|
||||
typ: node.cond_type
|
||||
sum_type_cast: expr_type
|
||||
pos: node_cond.pos
|
||||
})
|
||||
}
|
||||
}
|
||||
ast.Ident {
|
||||
mut is_mut := false
|
||||
if v := scope.find_var(node_cond.name) {
|
||||
is_mut = v.is_mut
|
||||
}
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if !is_mut || node.is_mut {
|
||||
scope.register(node.var_name, ast.Var{
|
||||
name: node.var_name
|
||||
typ: node.cond_type
|
||||
pos: node_cond.pos
|
||||
is_used: true
|
||||
is_mut: node.is_mut
|
||||
sum_type_cast: expr_type
|
||||
})
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
@ -3762,7 +3782,9 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||
if v := scope.find_var(infix_left.name) {
|
||||
is_mut = v.is_mut
|
||||
}
|
||||
if !is_mut && left_sym.kind == .union_sum_type {
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if (!is_mut || branch.is_mut_name) &&
|
||||
left_sym.kind == .union_sum_type {
|
||||
scope.register(branch.left_as_name, ast.Var{
|
||||
name: branch.left_as_name
|
||||
typ: infix.left_type
|
||||
|
@ -3780,7 +3802,10 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||
is_mut = field.is_mut
|
||||
is_root_mut := scope.is_selector_root_mutable(c.table,
|
||||
selector)
|
||||
if !is_root_mut && !is_mut && left_sym.kind == .union_sum_type {
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if ((!is_root_mut && !is_mut) ||
|
||||
branch.is_mut_name) &&
|
||||
left_sym.kind == .union_sum_type {
|
||||
scope.register_struct_field(ast.ScopeStructField{
|
||||
struct_type: selector.expr_type
|
||||
name: selector.field_name
|
||||
|
|
|
@ -1423,7 +1423,7 @@ pub fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
|||
}
|
||||
if i < it.branches.len - 1 || !it.has_else {
|
||||
f.write('${dollar}if ')
|
||||
if branch.mut_name {
|
||||
if branch.is_mut_name {
|
||||
f.write('mut ')
|
||||
}
|
||||
f.expr(branch.cond)
|
||||
|
|
|
@ -86,9 +86,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||
}
|
||||
comments << p.eat_comments()
|
||||
// `if mut name is T`
|
||||
mut mut_name := false
|
||||
mut is_mut_name := false
|
||||
if p.tok.kind == .key_mut && p.peek_tok2.kind == .key_is {
|
||||
mut_name = true
|
||||
is_mut_name = true
|
||||
p.next()
|
||||
comments << p.eat_comments()
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||
body_pos: body_pos.extend(p.prev_tok.position())
|
||||
comments: comments
|
||||
left_as_name: left_as_name
|
||||
mut_name: mut_name
|
||||
is_mut_name: is_mut_name
|
||||
}
|
||||
comments = p.eat_comments()
|
||||
if is_comptime {
|
||||
|
|
|
@ -346,10 +346,12 @@ fn test_zero_value_init() {
|
|||
}
|
||||
|
||||
struct Milk {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
struct Eggs {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
|
@ -364,6 +366,50 @@ fn test_match_aggregate() {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_match_mut() {
|
||||
mut f := Food(Milk{'test'})
|
||||
match union mut f {
|
||||
Eggs {
|
||||
f.name = 'eggs'
|
||||
assert f.name == 'eggs'
|
||||
}
|
||||
Milk {
|
||||
f.name = 'milk'
|
||||
assert f.name == 'milk'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_match_not_mut() {
|
||||
mut f := Food(Milk{'test'})
|
||||
match union f {
|
||||
Eggs {
|
||||
// only works without smartcast
|
||||
assert f is Eggs
|
||||
}
|
||||
Milk {
|
||||
// only works without smartcast
|
||||
assert f is Milk
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_if_mut() {
|
||||
mut f := Food(Milk{'test'})
|
||||
if mut f is Milk {
|
||||
f.name = 'milk'
|
||||
assert f.name == 'milk'
|
||||
}
|
||||
}
|
||||
|
||||
fn test_if_not_mut() {
|
||||
mut f := Food(Milk{'test'})
|
||||
if f is Milk {
|
||||
// only works without smartcast
|
||||
assert f is Milk
|
||||
}
|
||||
}
|
||||
|
||||
fn test_sum_type_match() {
|
||||
// TODO: Remove these casts
|
||||
assert is_gt_simple('3', int(2))
|
||||
|
|
Loading…
Reference in New Issue