v: cleanup if smartcasts in the compiler (#24734)

This commit is contained in:
Felipe Pena 2025-06-17 12:49:49 -03:00 committed by GitHub
parent e7905ea841
commit e14853d6e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 89 additions and 133 deletions

View file

@ -2594,10 +2594,8 @@ pub fn (mut lx IndexExpr) recursive_arraymap_set_is_setter() {
lx.is_setter = true lx.is_setter = true
if mut lx.left is IndexExpr { if mut lx.left is IndexExpr {
lx.left.recursive_arraymap_set_is_setter() lx.left.recursive_arraymap_set_is_setter()
} else if mut lx.left is SelectorExpr { } else if mut lx.left is SelectorExpr && lx.left.expr is IndexExpr {
if mut lx.left.expr is IndexExpr { lx.left.expr.recursive_arraymap_set_is_setter()
lx.left.expr.recursive_arraymap_set_is_setter()
}
} }
} }

View file

@ -103,10 +103,8 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
c.error('cannot assign a `none` value to a variable', right.pos) c.error('cannot assign a `none` value to a variable', right.pos)
} }
// Handle `left_name := unsafe { none }` // Handle `left_name := unsafe { none }`
if mut right is ast.UnsafeExpr { if mut right is ast.UnsafeExpr && right.expr is ast.None {
if mut right.expr is ast.None { c.error('cannot use `none` in `unsafe` blocks', right.expr.pos)
c.error('cannot use `none` in `unsafe` blocks', right.expr.pos)
}
} }
if mut right is ast.AnonFn { if mut right is ast.AnonFn {
if right.decl.generic_names.len > 0 { if right.decl.generic_names.len > 0 {
@ -159,11 +157,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
c.error('cannot dereference a function call on the left side of an assignment, use a temporary variable', c.error('cannot dereference a function call on the left side of an assignment, use a temporary variable',
left.pos) left.pos)
} }
} else if mut left is ast.IndexExpr { } else if mut left is ast.IndexExpr && left.index is ast.RangeExpr {
if left.index is ast.RangeExpr { c.error('cannot reassign using range expression on the left side of an assignment',
c.error('cannot reassign using range expression on the left side of an assignment', left.pos)
left.pos)
}
} else if mut left is ast.Ident && node.op == .decl_assign { } else if mut left is ast.Ident && node.op == .decl_assign {
if left.name in c.global_names { if left.name in c.global_names {
c.note('the global variable named `${left.name}` already exists', left.pos) c.note('the global variable named `${left.name}` already exists', left.pos)
@ -199,10 +195,8 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
} }
if node.right_types.len < node.left.len { // first type or multi return types added above if node.right_types.len < node.left.len { // first type or multi return types added above
old_inside_ref_lit := c.inside_ref_lit old_inside_ref_lit := c.inside_ref_lit
if mut left is ast.Ident { if mut left is ast.Ident && left.info is ast.IdentVar {
if mut left.info is ast.IdentVar { c.inside_ref_lit = c.inside_ref_lit || left.info.share == .shared_t
c.inside_ref_lit = c.inside_ref_lit || left.info.share == .shared_t
}
} }
c.inside_decl_rhs = is_decl c.inside_decl_rhs = is_decl
mut expr := node.right[i] mut expr := node.right[i]
@ -666,11 +660,9 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
} }
} }
} }
if mut left is ast.Ident { if mut left is ast.Ident && left.info is ast.IdentVar {
if mut left.info is ast.IdentVar { if left.info.is_static && right_sym.kind == .map {
if left.info.is_static && right_sym.kind == .map { c.error('maps cannot be static', left.pos)
c.error('maps cannot be static', left.pos)
}
} }
} }
// Single side check // Single side check

View file

@ -911,10 +911,8 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
} }
ast.ComptimeSelector { ast.ComptimeSelector {
mut expr_left := expr.left mut expr_left := expr.left
if mut expr.left is ast.Ident { if mut expr.left is ast.Ident && expr.left.obj is ast.Var {
if mut expr.left.obj is ast.Var { c.fail_if_immutable(mut expr_left)
c.fail_if_immutable(mut expr_left)
}
} }
return '', expr.pos return '', expr.pos
} }
@ -1117,6 +1115,9 @@ fn (mut c Checker) fail_if_immutable(mut expr ast.Expr) (string, token.Pos) {
} }
return '', expr.pos return '', expr.pos
} }
ast.AsCast {
to_lock, pos = c.fail_if_immutable(mut expr.expr)
}
else { else {
if !expr.is_pure_literal() { if !expr.is_pure_literal() {
c.error('unexpected expression `${expr.type_name()}`', expr.pos()) c.error('unexpected expression `${expr.type_name()}`', expr.pos())
@ -1678,10 +1679,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
c.inside_selector_expr = true c.inside_selector_expr = true
mut typ := c.expr(mut node.expr) mut typ := c.expr(mut node.expr)
if node.expr.is_auto_deref_var() { if node.expr.is_auto_deref_var() {
if mut node.expr is ast.Ident { if mut node.expr is ast.Ident && node.expr.obj is ast.Var {
if mut node.expr.obj is ast.Var { typ = node.expr.obj.typ
typ = node.expr.obj.typ
}
} }
} }
c.inside_selector_expr = old_selector_expr c.inside_selector_expr = old_selector_expr
@ -4417,10 +4416,8 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
} }
} }
mut expr_str := expr.expr.str() mut expr_str := expr.expr.str()
if mut expr.expr is ast.ParExpr { if mut expr.expr is ast.ParExpr && expr.expr.expr is ast.AsCast {
if mut expr.expr.expr is ast.AsCast { expr_str = expr.expr.expr.expr.str()
expr_str = expr.expr.expr.expr.str()
}
} }
field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name) field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name)
if field != unsafe { nil } { if field != unsafe { nil } {
@ -5058,15 +5055,12 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|| typ.is_pointer() { || typ.is_pointer() {
mut is_ok := false mut is_ok := false
mut is_mut_struct := false mut is_mut_struct := false
if mut node.left is ast.Ident { if mut node.left is ast.Ident && node.left.obj is ast.Var {
if mut node.left.obj is ast.Var { // `mut param []T` function parameter
// `mut param []T` function parameter is_ok = node.left.obj.is_mut && node.left.obj.is_arg && !typ.deref().is_ptr()
is_ok = node.left.obj.is_mut && node.left.obj.is_arg && !typ.deref().is_ptr() && typ_sym.kind != .struct
&& typ_sym.kind != .struct // `mut param Struct`
// `mut param Struct` is_mut_struct = node.left.obj.is_mut && node.left.obj.is_arg && typ_sym.kind == .struct
is_mut_struct = node.left.obj.is_mut && node.left.obj.is_arg
&& typ_sym.kind == .struct
}
} }
if !is_ok && node.index is ast.RangeExpr { if !is_ok && node.index is ast.RangeExpr {
s := c.table.type_to_str(typ) s := c.table.type_to_str(typ)

View file

@ -799,10 +799,8 @@ fn (mut c Checker) check_append(mut node ast.InfixExpr, left_type ast.Type, righ
right := node.right right := node.right
if right is ast.PrefixExpr && right.op == .amp { if right is ast.PrefixExpr && right.op == .amp {
mut expr2 := right.right mut expr2 := right.right
if mut expr2 is ast.Ident { if mut expr2 is ast.Ident && !node.left.is_blank_ident() && expr2.obj is ast.ConstField {
if !node.left.is_blank_ident() && expr2.obj is ast.ConstField { c.error('cannot have mutable reference to const `${expr2.name}`', expr2.pos)
c.error('cannot have mutable reference to const `${expr2.name}`', expr2.pos)
}
} }
} }
if left_value_sym.kind == .interface { if left_value_sym.kind == .interface {

View file

@ -1520,10 +1520,8 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
} }
node.args[i].typ = arg_typ node.args[i].typ = arg_typ
if c.comptime.comptime_for_field_var != '' { if c.comptime.comptime_for_field_var != '' {
if mut call_arg.expr is ast.Ident { if mut call_arg.expr is ast.Ident && call_arg.expr.obj is ast.Var {
if mut call_arg.expr.obj is ast.Var { node.args[i].typ = call_arg.expr.obj.typ
node.args[i].typ = call_arg.expr.obj.typ
}
} }
} }
arg_typ_sym := c.table.sym(arg_typ) arg_typ_sym := c.table.sym(arg_typ)

View file

@ -318,13 +318,11 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
c.error('non-bool used as for condition', node.pos) c.error('non-bool used as for condition', node.pos)
} }
} }
if mut node.cond is ast.InfixExpr { if mut node.cond is ast.InfixExpr && node.cond.op == .key_is {
if node.cond.op == .key_is { if node.cond.right is ast.TypeNode && node.cond.left in [ast.Ident, ast.SelectorExpr] {
if node.cond.right is ast.TypeNode && node.cond.left in [ast.Ident, ast.SelectorExpr] { if c.table.type_kind(node.cond.left_type) in [.sum_type, .interface] {
if c.table.type_kind(node.cond.left_type) in [.sum_type, .interface] { c.smartcast(mut node.cond.left, node.cond.left_type, node.cond.right_type, mut
c.smartcast(mut node.cond.left, node.cond.left_type, node.cond.right_type, mut node.scope, false, false)
node.scope, false, false)
}
} }
} }
} }

View file

@ -308,10 +308,8 @@ fn (mut c Checker) get_comptime_number_value(mut expr ast.Expr) ?i64 {
if mut expr is ast.IntegerLiteral { if mut expr is ast.IntegerLiteral {
return expr.val.i64() return expr.val.i64()
} }
if mut expr is ast.CastExpr { if mut expr is ast.CastExpr && expr.expr is ast.IntegerLiteral {
if mut expr.expr is ast.IntegerLiteral { return expr.expr.val.i64()
return expr.expr.val.i64()
}
} }
if mut expr is ast.Ident { if mut expr is ast.Ident {
if mut obj := c.table.global_scope.find_const(expr.full_name()) { if mut obj := c.table.global_scope.find_const(expr.full_name()) {

View file

@ -82,10 +82,8 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
return return
} }
// Handle `return unsafe { none }` // Handle `return unsafe { none }`
if mut expr is ast.UnsafeExpr { if mut expr is ast.UnsafeExpr && expr.expr is ast.None {
if mut expr.expr is ast.None { c.error('cannot return `none` in unsafe block', expr.expr.pos)
c.error('cannot return `none` in unsafe block', expr.expr.pos)
}
} }
if typ == ast.void_type { if typ == ast.void_type {
c.error('`${expr}` used as value', node.pos) c.error('`${expr}` used as value', node.pos)
@ -102,18 +100,16 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
expr_idxs << i expr_idxs << i
} }
} else { } else {
if mut expr is ast.Ident { if mut expr is ast.Ident && expr.obj is ast.Var {
if mut expr.obj is ast.Var { if expr.obj.smartcasts.len > 0 {
if expr.obj.smartcasts.len > 0 { typ = c.unwrap_generic(expr.obj.smartcasts.last())
typ = c.unwrap_generic(expr.obj.smartcasts.last()) }
} if expr.obj.ct_type_var != .no_comptime {
if expr.obj.ct_type_var != .no_comptime { typ = c.type_resolver.get_type_or_default(expr, typ)
typ = c.type_resolver.get_type_or_default(expr, typ) }
} if mut expr.obj.expr is ast.IfGuardExpr {
if mut expr.obj.expr is ast.IfGuardExpr { if var := expr.scope.find_var(expr.name) {
if var := expr.scope.find_var(expr.name) { typ = var.typ
typ = var.typ
}
} }
} }
} }

View file

@ -231,16 +231,13 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
&& expr in [ast.IndexExpr, ast.CallExpr, ast.StringLiteral, ast.StringInterLiteral] { && expr in [ast.IndexExpr, ast.CallExpr, ast.StringLiteral, ast.StringInterLiteral] {
should_clone = false should_clone = false
} }
if expr is ast.CTempVar { if expr is ast.CTempVar && expr.orig is ast.CallExpr {
if expr.orig is ast.CallExpr { should_clone = false
should_clone = false if expr.orig.or_block.kind == .propagate_option {
if expr.orig.or_block.kind == .propagate_option { should_clone = true
should_clone = true }
} if expr.orig.is_method && expr.orig.args.len == 0 && expr.orig.name == 'type_name' {
if expr.orig.is_method && expr.orig.args.len == 0 should_clone = true
&& expr.orig.name == 'type_name' {
should_clone = true
}
} }
} }
if should_clone { if should_clone {

View file

@ -34,13 +34,11 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
} }
// var.$(field.name) // var.$(field.name)
if node.expr is ast.ComptimeSelector && node.expr.is_name { if node.expr is ast.ComptimeSelector && node.expr.is_name {
if node.expr.field_expr is ast.SelectorExpr { if node.expr.field_expr is ast.SelectorExpr && node.expr.field_expr.expr is ast.Ident {
if node.expr.field_expr.expr is ast.Ident { if node.expr.field_expr.expr.name == g.comptime.comptime_for_field_var {
if node.expr.field_expr.expr.name == g.comptime.comptime_for_field_var { field, _ := g.type_resolver.get_comptime_selector_var_type(node.expr)
field, _ := g.type_resolver.get_comptime_selector_var_type(node.expr) name = g.styp(g.unwrap_generic(field.typ.clear_flags(.shared_f, .result)))
name = g.styp(g.unwrap_generic(field.typ.clear_flags(.shared_f, .result))) expr_type = field.typ
expr_type = field.typ
}
} }
} }
} else if node.expr is ast.Ident && node.expr.ct_expr { } else if node.expr is ast.Ident && node.expr.ct_expr {

View file

@ -1227,12 +1227,9 @@ fn (mut g Gen) gen_array_method_call(node ast.CallExpr, left_type ast.Type, left
array_depth := g.get_array_depth(array_info.elem_type) array_depth := g.get_array_depth(array_info.elem_type)
to_depth := if array_depth >= 0 { '_to_depth' } else { '' } to_depth := if array_depth >= 0 { '_to_depth' } else { '' }
mut is_range_slice := false mut is_range_slice := false
if node.left is ast.IndexExpr { if node.left is ast.IndexExpr && node.left.index is ast.RangeExpr
if node.left.index is ast.RangeExpr { && node.name == 'clone' {
if node.name == 'clone' { is_range_slice = true
is_range_slice = true
}
}
} }
to_static := if is_range_slice { '_static' } else { '' } to_static := if is_range_slice { '_static' } else { '' }
g.write('array_${node.name}${to_static}${to_depth}(') g.write('array_${node.name}${to_static}${to_depth}(')
@ -2072,23 +2069,21 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
typ = m.return_type typ = m.return_type
} }
} }
} else if expr is ast.Ident { } else if expr is ast.Ident && expr.obj is ast.Var {
if expr.obj is ast.Var { typ = expr.obj.typ
typ = expr.obj.typ if expr.obj.smartcasts.len > 0 {
if expr.obj.smartcasts.len > 0 { typ = g.unwrap_generic(expr.obj.smartcasts.last())
typ = g.unwrap_generic(expr.obj.smartcasts.last()) cast_sym := g.table.sym(typ)
cast_sym := g.table.sym(typ) if cast_sym.info is ast.Aggregate {
if cast_sym.info is ast.Aggregate { typ = cast_sym.info.types[g.aggregate_type_idx]
typ = cast_sym.info.types[g.aggregate_type_idx] } else if expr.obj.ct_type_var == .smartcast {
} else if expr.obj.ct_type_var == .smartcast { typ = g.unwrap_generic(g.type_resolver.get_type(expr))
typ = g.unwrap_generic(g.type_resolver.get_type(expr))
}
}
// handling println( var or { ... })
if typ.has_flag(.option) && expr.or_expr.kind != .absent {
typ = typ.clear_flag(.option)
} }
} }
// handling println( var or { ... })
if typ.has_flag(.option) && expr.or_expr.kind != .absent {
typ = typ.clear_flag(.option)
}
} }
g.gen_expr_to_string(expr, typ) g.gen_expr_to_string(expr, typ)
g.write(')') g.write(')')
@ -2744,11 +2739,9 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as
if (arg_sym.info is ast.Alias || exp_sym.info is ast.Alias) && expected_type != arg_typ { if (arg_sym.info is ast.Alias || exp_sym.info is ast.Alias) && expected_type != arg_typ {
g.expr_opt_with_alias(arg.expr, arg_typ, expected_type) g.expr_opt_with_alias(arg.expr, arg_typ, expected_type)
} else { } else {
if arg.expr is ast.Ident { if arg.expr is ast.Ident && arg.expr.obj is ast.Var {
if arg.expr.obj is ast.Var { if arg.expr.obj.smartcasts.len > 0 {
if arg.expr.obj.smartcasts.len > 0 { arg_typ = arg.expr.obj.smartcasts.last()
arg_typ = arg.expr.obj.smartcasts.last()
}
} }
} }
g.expr_with_opt(arg.expr, arg_typ, expected_type) g.expr_with_opt(arg.expr, arg_typ, expected_type)

View file

@ -80,16 +80,14 @@ fn (mut g Gen) for_c_stmt(node ast.ForCStmt) {
g.write('; ') g.write('; ')
if node.has_inc { if node.has_inc {
mut processed := false mut processed := false
if node.inc is ast.ExprStmt { if node.inc is ast.ExprStmt && node.inc.expr is ast.ConcatExpr {
if node.inc.expr is ast.ConcatExpr { for inc_expr_idx, inc_expr in node.inc.expr.vals {
for inc_expr_idx, inc_expr in node.inc.expr.vals { g.expr(inc_expr)
g.expr(inc_expr) if inc_expr_idx < node.inc.expr.vals.len - 1 {
if inc_expr_idx < node.inc.expr.vals.len - 1 { g.write(', ')
g.write(', ')
}
} }
processed = true
} }
processed = true
} }
if !processed { if !processed {
g.stmt(node.inc) g.stmt(node.inc)

View file

@ -132,10 +132,8 @@ pub fn (mut t TypeResolver) typeof_field_type(typ ast.Type, field_name string) a
// get_ct_type_var gets the comptime type of the variable (.generic_param, .key_var, etc) // get_ct_type_var gets the comptime type of the variable (.generic_param, .key_var, etc)
@[inline] @[inline]
pub fn (t &ResolverInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind { pub fn (t &ResolverInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind {
if node is ast.Ident { if node is ast.Ident && node.obj is ast.Var {
if node.obj is ast.Var { return node.obj.ct_type_var
return node.obj.ct_type_var
}
} else if node is ast.IndexExpr { } else if node is ast.IndexExpr {
return t.get_ct_type_var(node.left) return t.get_ct_type_var(node.left)
} else if node is ast.InfixExpr { } else if node is ast.InfixExpr {