checker: minor cleanup of assign_stmt() (#10314)
							parent
							
								
									86d70fade7
								
							
						
					
					
						commit
						fedf07ddd8
					
				| 
						 | 
					@ -3216,50 +3216,50 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
					pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
 | 
				
			||||||
	c.expected_type = ast.none_type // TODO a hack to make `x := if ... work`
 | 
						c.expected_type = ast.none_type // TODO a hack to make `x := if ... work`
 | 
				
			||||||
	defer {
 | 
						defer {
 | 
				
			||||||
		c.expected_type = ast.void_type
 | 
							c.expected_type = ast.void_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	right_first := assign_stmt.right[0]
 | 
						right_first := node.right[0]
 | 
				
			||||||
	mut right_len := assign_stmt.right.len
 | 
						mut right_len := node.right.len
 | 
				
			||||||
	mut right_type0 := ast.void_type
 | 
						mut right_type0 := ast.void_type
 | 
				
			||||||
	for i, right in assign_stmt.right {
 | 
						for i, right in node.right {
 | 
				
			||||||
		if right is ast.CallExpr || right is ast.IfExpr || right is ast.LockExpr
 | 
							if right is ast.CallExpr || right is ast.IfExpr || right is ast.LockExpr
 | 
				
			||||||
			|| right is ast.MatchExpr {
 | 
								|| right is ast.MatchExpr {
 | 
				
			||||||
			right_type := c.expr(right)
 | 
								right_type := c.expr(right)
 | 
				
			||||||
			if i == 0 {
 | 
								if i == 0 {
 | 
				
			||||||
				right_type0 = right_type
 | 
									right_type0 = right_type
 | 
				
			||||||
				assign_stmt.right_types = [
 | 
									node.right_types = [
 | 
				
			||||||
					c.check_expr_opt_call(right, right_type0),
 | 
										c.check_expr_opt_call(right, right_type0),
 | 
				
			||||||
				]
 | 
									]
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			right_type_sym := c.table.get_type_symbol(right_type)
 | 
								right_type_sym := c.table.get_type_symbol(right_type)
 | 
				
			||||||
			if right_type_sym.kind == .multi_return {
 | 
								if right_type_sym.kind == .multi_return {
 | 
				
			||||||
				if assign_stmt.right.len > 1 {
 | 
									if node.right.len > 1 {
 | 
				
			||||||
					c.error('cannot use multi-value $right_type_sym.name in single-value context',
 | 
										c.error('cannot use multi-value $right_type_sym.name in single-value context',
 | 
				
			||||||
						right.position())
 | 
											right.position())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				assign_stmt.right_types = right_type_sym.mr_info().types
 | 
									node.right_types = right_type_sym.mr_info().types
 | 
				
			||||||
				right_len = assign_stmt.right_types.len
 | 
									right_len = node.right_types.len
 | 
				
			||||||
			} else if right_type == ast.void_type {
 | 
								} else if right_type == ast.void_type {
 | 
				
			||||||
				right_len = 0
 | 
									right_len = 0
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if assign_stmt.left.len != right_len {
 | 
						if node.left.len != right_len {
 | 
				
			||||||
		if right_first is ast.CallExpr {
 | 
							if right_first is ast.CallExpr {
 | 
				
			||||||
			c.error('assignment mismatch: $assign_stmt.left.len variable(s) but `${right_first.name}()` returns $right_len value(s)',
 | 
								c.error('assignment mismatch: $node.left.len variable(s) but `${right_first.name}()` returns $right_len value(s)',
 | 
				
			||||||
				assign_stmt.pos)
 | 
									node.pos)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			c.error('assignment mismatch: $assign_stmt.left.len variable(s) $right_len value(s)',
 | 
								c.error('assignment mismatch: $node.left.len variable(s) $right_len value(s)',
 | 
				
			||||||
				assign_stmt.pos)
 | 
									node.pos)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	is_decl := assign_stmt.op == .decl_assign
 | 
						is_decl := node.op == .decl_assign
 | 
				
			||||||
	for i, left in assign_stmt.left {
 | 
						for i, left in node.left {
 | 
				
			||||||
		if left is ast.CallExpr {
 | 
							if left is ast.CallExpr {
 | 
				
			||||||
			c.error('cannot call function `${left.name}()` on the left side of an assignment',
 | 
								c.error('cannot call function `${left.name}()` on the left side of an assignment',
 | 
				
			||||||
				left.pos)
 | 
									left.pos)
 | 
				
			||||||
| 
						 | 
					@ -3274,13 +3274,13 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			c.expected_type = c.unwrap_generic(left_type)
 | 
								c.expected_type = c.unwrap_generic(left_type)
 | 
				
			||||||
			// `map = {}`
 | 
								// `map = {}`
 | 
				
			||||||
			sym := c.table.get_type_symbol(left_type)
 | 
								sym := c.table.get_type_symbol(left_type)
 | 
				
			||||||
			if sym.kind == .map && assign_stmt.right[i] is ast.StructInit {
 | 
								if sym.kind == .map && node.right[i] is ast.StructInit {
 | 
				
			||||||
				c.warn('assigning a struct literal to a map is deprecated - use `map{}` instead',
 | 
									c.warn('assigning a struct literal to a map is deprecated - use `map{}` instead',
 | 
				
			||||||
					assign_stmt.right[i].position())
 | 
										node.right[i].position())
 | 
				
			||||||
				assign_stmt.right[i] = ast.MapInit{}
 | 
									node.right[i] = ast.MapInit{}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if assign_stmt.right_types.len < assign_stmt.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 left is ast.Ident {
 | 
								if left is ast.Ident {
 | 
				
			||||||
				if left.info is ast.IdentVar {
 | 
									if left.info is ast.IdentVar {
 | 
				
			||||||
| 
						 | 
					@ -3288,16 +3288,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			c.inside_decl_rhs = is_decl
 | 
								c.inside_decl_rhs = is_decl
 | 
				
			||||||
			right_type := c.expr(assign_stmt.right[i])
 | 
								right_type := c.expr(node.right[i])
 | 
				
			||||||
			c.inside_decl_rhs = false
 | 
								c.inside_decl_rhs = false
 | 
				
			||||||
			c.inside_ref_lit = old_inside_ref_lit
 | 
								c.inside_ref_lit = old_inside_ref_lit
 | 
				
			||||||
			if assign_stmt.right_types.len == i {
 | 
								if node.right_types.len == i {
 | 
				
			||||||
				assign_stmt.right_types << c.check_expr_opt_call(assign_stmt.right[i],
 | 
									node.right_types << c.check_expr_opt_call(node.right[i], right_type)
 | 
				
			||||||
					right_type)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		right := if i < assign_stmt.right.len { assign_stmt.right[i] } else { assign_stmt.right[0] }
 | 
							right := if i < node.right.len { node.right[i] } else { node.right[0] }
 | 
				
			||||||
		mut right_type := assign_stmt.right_types[i]
 | 
							mut right_type := node.right_types[i]
 | 
				
			||||||
		if is_decl {
 | 
							if is_decl {
 | 
				
			||||||
			// check generic struct init and return unwrap generic struct type
 | 
								// check generic struct init and return unwrap generic struct type
 | 
				
			||||||
			if right is ast.StructInit {
 | 
								if right is ast.StructInit {
 | 
				
			||||||
| 
						 | 
					@ -3351,13 +3350,13 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		assign_stmt.left_types << left_type
 | 
							node.left_types << left_type
 | 
				
			||||||
		match mut left {
 | 
							match mut left {
 | 
				
			||||||
			ast.Ident {
 | 
								ast.Ident {
 | 
				
			||||||
				if left.kind == .blank_ident {
 | 
									if left.kind == .blank_ident {
 | 
				
			||||||
					left_type = right_type
 | 
										left_type = right_type
 | 
				
			||||||
					assign_stmt.left_types[i] = right_type
 | 
										node.left_types[i] = right_type
 | 
				
			||||||
					if assign_stmt.op !in [.assign, .decl_assign] {
 | 
										if node.op !in [.assign, .decl_assign] {
 | 
				
			||||||
						c.error('cannot modify blank `_` identifier', left.pos)
 | 
											c.error('cannot modify blank `_` identifier', left.pos)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else if left.info !is ast.IdentVar {
 | 
									} else if left.info !is ast.IdentVar {
 | 
				
			||||||
| 
						 | 
					@ -3381,7 +3380,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
					if ident_var_info.share == .atomic_t {
 | 
										if ident_var_info.share == .atomic_t {
 | 
				
			||||||
						left_type = left_type.set_flag(.atomic_f)
 | 
											left_type = left_type.set_flag(.atomic_f)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					assign_stmt.left_types[i] = left_type
 | 
										node.left_types[i] = left_type
 | 
				
			||||||
					ident_var_info.typ = left_type
 | 
										ident_var_info.typ = left_type
 | 
				
			||||||
					left.info = ident_var_info
 | 
										left.info = ident_var_info
 | 
				
			||||||
					if left_type != 0 {
 | 
										if left_type != 0 {
 | 
				
			||||||
| 
						 | 
					@ -3418,7 +3417,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				if left.op == .mul {
 | 
									if left.op == .mul {
 | 
				
			||||||
					if !c.inside_unsafe {
 | 
										if !c.inside_unsafe {
 | 
				
			||||||
						c.error('modifying variables via dereferencing can only be done in `unsafe` blocks',
 | 
											c.error('modifying variables via dereferencing can only be done in `unsafe` blocks',
 | 
				
			||||||
							assign_stmt.pos)
 | 
												node.pos)
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						// mark `p` in `*p = val` as used:
 | 
											// mark `p` in `*p = val` as used:
 | 
				
			||||||
						match mut left.right {
 | 
											match mut left.right {
 | 
				
			||||||
| 
						 | 
					@ -3463,15 +3462,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			// TODO replace all c.pref.translated checks with `$if !translated` for performance
 | 
								// TODO replace all c.pref.translated checks with `$if !translated` for performance
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if left_sym.kind == .array && !c.inside_unsafe && assign_stmt.op in [.assign, .decl_assign]
 | 
							if left_sym.kind == .array && !c.inside_unsafe && node.op in [.assign, .decl_assign]
 | 
				
			||||||
			&& right_sym.kind == .array && (left is ast.Ident && !left.is_blank_ident())
 | 
								&& right_sym.kind == .array && (left is ast.Ident && !left.is_blank_ident())
 | 
				
			||||||
			&& right is ast.Ident {
 | 
								&& right is ast.Ident {
 | 
				
			||||||
			// Do not allow `a = b`, only `a = b.clone()`
 | 
								// Do not allow `a = b`, only `a = b.clone()`
 | 
				
			||||||
			c.error('use `array2 $assign_stmt.op.str() array1.clone()` instead of `array2 $assign_stmt.op.str() array1` (or use `unsafe`)',
 | 
								c.error('use `array2 $node.op.str() array1.clone()` instead of `array2 $node.op.str() array1` (or use `unsafe`)',
 | 
				
			||||||
				assign_stmt.pos)
 | 
									node.pos)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if left_sym.kind == .map && assign_stmt.op in [.assign, .decl_assign]
 | 
							if left_sym.kind == .map && node.op in [.assign, .decl_assign] && right_sym.kind == .map
 | 
				
			||||||
			&& right_sym.kind == .map && ((right is ast.Ident && right.is_auto_deref_var())
 | 
								&& ((right is ast.Ident && right.is_auto_deref_var())
 | 
				
			||||||
			|| !right_type.is_ptr()) && !left.is_blank_ident() && right.is_lvalue() {
 | 
								|| !right_type.is_ptr()) && !left.is_blank_ident() && right.is_lvalue() {
 | 
				
			||||||
			// Do not allow `a = b`
 | 
								// Do not allow `a = b`
 | 
				
			||||||
			c.error('cannot copy map: call `move` or `clone` method (or use a reference)',
 | 
								c.error('cannot copy map: call `move` or `clone` method (or use a reference)',
 | 
				
			||||||
| 
						 | 
					@ -3479,12 +3478,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
 | 
							left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
 | 
				
			||||||
		if left_is_ptr && !left.is_auto_deref_var() {
 | 
							if left_is_ptr && !left.is_auto_deref_var() {
 | 
				
			||||||
			if !c.inside_unsafe && assign_stmt.op !in [.assign, .decl_assign] {
 | 
								if !c.inside_unsafe && node.op !in [.assign, .decl_assign] {
 | 
				
			||||||
				// ptr op=
 | 
									// ptr op=
 | 
				
			||||||
				c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
 | 
									c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			right_is_ptr := right_type.is_ptr() || right_sym.is_pointer()
 | 
								right_is_ptr := right_type.is_ptr() || right_sym.is_pointer()
 | 
				
			||||||
			if !right_is_ptr && assign_stmt.op == .assign && right_type_unwrapped.is_number() {
 | 
								if !right_is_ptr && node.op == .assign && right_type_unwrapped.is_number() {
 | 
				
			||||||
				c.error('cannot assign to `$left`: ' +
 | 
									c.error('cannot assign to `$left`: ' +
 | 
				
			||||||
					c.expected_msg(right_type_unwrapped, left_type_unwrapped), right.position())
 | 
										c.expected_msg(right_type_unwrapped, left_type_unwrapped), right.position())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -3496,29 +3495,29 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
					rtype = rtype.deref()
 | 
										rtype = rtype.deref()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				right_name := c.table.type_to_str(rtype)
 | 
									right_name := c.table.type_to_str(rtype)
 | 
				
			||||||
				c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
 | 
									c.error('mismatched types `$left_name` and `$right_name`', node.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Single side check
 | 
							// Single side check
 | 
				
			||||||
		match assign_stmt.op {
 | 
							match node.op {
 | 
				
			||||||
			.assign {} // No need to do single side check for =. But here put it first for speed.
 | 
								.assign {} // No need to do single side check for =. But here put it first for speed.
 | 
				
			||||||
			.plus_assign, .minus_assign {
 | 
								.plus_assign, .minus_assign {
 | 
				
			||||||
				if left_type == ast.string_type {
 | 
									if left_type == ast.string_type {
 | 
				
			||||||
					if assign_stmt.op != .plus_assign {
 | 
										if node.op != .plus_assign {
 | 
				
			||||||
						c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`',
 | 
											c.error('operator `$node.op` not defined on left operand type `$left_sym.name`',
 | 
				
			||||||
							left.position())
 | 
												left.position())
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if right_type != ast.string_type {
 | 
										if right_type != ast.string_type {
 | 
				
			||||||
						c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name',
 | 
											c.error('invalid right operand: $left_sym.name $node.op $right_sym.name',
 | 
				
			||||||
							right.position())
 | 
												right.position())
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else if !left_sym.is_number()
 | 
									} else if !left_sym.is_number()
 | 
				
			||||||
					&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
 | 
										&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
 | 
				
			||||||
					c.error('operator `$assign_stmt.op` not defined on left operand type `$left_sym.name`',
 | 
										c.error('operator `$node.op` not defined on left operand type `$left_sym.name`',
 | 
				
			||||||
						left.position())
 | 
											left.position())
 | 
				
			||||||
				} else if !right_sym.is_number()
 | 
									} else if !right_sym.is_number()
 | 
				
			||||||
					&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
 | 
										&& left_sym.kind !in [.byteptr, .charptr, .struct_, .alias] {
 | 
				
			||||||
					c.error('invalid right operand: $left_sym.name $assign_stmt.op $right_sym.name',
 | 
										c.error('invalid right operand: $left_sym.name $node.op $right_sym.name',
 | 
				
			||||||
						right.position())
 | 
											right.position())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -3526,12 +3525,12 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				if !left_sym.is_number()
 | 
									if !left_sym.is_number()
 | 
				
			||||||
					&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
 | 
										&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
 | 
				
			||||||
					&& left_sym.kind !in [.struct_, .alias] {
 | 
										&& left_sym.kind !in [.struct_, .alias] {
 | 
				
			||||||
					c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
 | 
										c.error('operator $node.op.str() not defined on left operand type `$left_sym.name`',
 | 
				
			||||||
						left.position())
 | 
											left.position())
 | 
				
			||||||
				} else if !right_sym.is_number()
 | 
									} else if !right_sym.is_number()
 | 
				
			||||||
					&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
 | 
										&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int()
 | 
				
			||||||
					&& left_sym.kind !in [.struct_, .alias] {
 | 
										&& left_sym.kind !in [.struct_, .alias] {
 | 
				
			||||||
					c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
 | 
										c.error('operator $node.op.str() not defined on right operand type `$right_sym.name`',
 | 
				
			||||||
						right.position())
 | 
											right.position())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -3539,26 +3538,26 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			.right_shift_assign {
 | 
								.right_shift_assign {
 | 
				
			||||||
				if !left_sym.is_int()
 | 
									if !left_sym.is_int()
 | 
				
			||||||
					&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int() {
 | 
										&& !c.table.get_final_type_symbol(left_type_unwrapped).is_int() {
 | 
				
			||||||
					c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
 | 
										c.error('operator $node.op.str() not defined on left operand type `$left_sym.name`',
 | 
				
			||||||
						left.position())
 | 
											left.position())
 | 
				
			||||||
				} else if !right_sym.is_int()
 | 
									} else if !right_sym.is_int()
 | 
				
			||||||
					&& !c.table.get_final_type_symbol(right_type_unwrapped).is_int() {
 | 
										&& !c.table.get_final_type_symbol(right_type_unwrapped).is_int() {
 | 
				
			||||||
					c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
 | 
										c.error('operator $node.op.str() not defined on right operand type `$right_sym.name`',
 | 
				
			||||||
						right.position())
 | 
											right.position())
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else {}
 | 
								else {}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if assign_stmt.op in [.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign]
 | 
							if node.op in [.plus_assign, .minus_assign, .mod_assign, .mult_assign, .div_assign]
 | 
				
			||||||
			&& ((left_sym.kind == .struct_ && right_sym.kind == .struct_)
 | 
								&& ((left_sym.kind == .struct_ && right_sym.kind == .struct_)
 | 
				
			||||||
			|| left_sym.kind == .alias) {
 | 
								|| left_sym.kind == .alias) {
 | 
				
			||||||
			left_name := c.table.type_to_str(left_type)
 | 
								left_name := c.table.type_to_str(left_type)
 | 
				
			||||||
			right_name := c.table.type_to_str(right_type)
 | 
								right_name := c.table.type_to_str(right_type)
 | 
				
			||||||
			parent_sym := c.table.get_final_type_symbol(left_type)
 | 
								parent_sym := c.table.get_final_type_symbol(left_type)
 | 
				
			||||||
			if left_sym.kind == .alias && right_sym.kind != .alias {
 | 
								if left_sym.kind == .alias && right_sym.kind != .alias {
 | 
				
			||||||
				c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
 | 
									c.error('mismatched types `$left_name` and `$right_name`', node.pos)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			extracted_op := match assign_stmt.op {
 | 
								extracted_op := match node.op {
 | 
				
			||||||
				.plus_assign { '+' }
 | 
									.plus_assign { '+' }
 | 
				
			||||||
				.minus_assign { '-' }
 | 
									.minus_assign { '-' }
 | 
				
			||||||
				.div_assign { '/' }
 | 
									.div_assign { '/' }
 | 
				
			||||||
| 
						 | 
					@ -3569,18 +3568,18 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			if method := left_sym.find_method(extracted_op) {
 | 
								if method := left_sym.find_method(extracted_op) {
 | 
				
			||||||
				if method.return_type != left_type {
 | 
									if method.return_type != left_type {
 | 
				
			||||||
					c.error('operator `$extracted_op` must return `$left_name` to be used as an assignment operator',
 | 
										c.error('operator `$extracted_op` must return `$left_name` to be used as an assignment operator',
 | 
				
			||||||
						assign_stmt.pos)
 | 
											node.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if parent_sym.is_primitive() {
 | 
									if parent_sym.is_primitive() {
 | 
				
			||||||
					c.error('cannot use operator methods on type alias for `$parent_sym.name`',
 | 
										c.error('cannot use operator methods on type alias for `$parent_sym.name`',
 | 
				
			||||||
						assign_stmt.pos)
 | 
											node.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if left_name == right_name {
 | 
									if left_name == right_name {
 | 
				
			||||||
					c.error('undefined operation `$left_name` $extracted_op `$right_name`',
 | 
										c.error('undefined operation `$left_name` $extracted_op `$right_name`',
 | 
				
			||||||
						assign_stmt.pos)
 | 
											node.pos)
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
 | 
										c.error('mismatched types `$left_name` and `$right_name`', node.pos)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3590,10 +3589,10 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
			c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
 | 
								c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
 | 
				
			||||||
				// allow for ptr += 2
 | 
									// allow for ptr += 2
 | 
				
			||||||
				if left_type_unwrapped.is_ptr() && right_type_unwrapped.is_int()
 | 
									if left_type_unwrapped.is_ptr() && right_type_unwrapped.is_int()
 | 
				
			||||||
					&& assign_stmt.op in [.plus_assign, .minus_assign] {
 | 
										&& node.op in [.plus_assign, .minus_assign] {
 | 
				
			||||||
					if !c.inside_unsafe {
 | 
										if !c.inside_unsafe {
 | 
				
			||||||
						c.warn('pointer arithmetic is only allowed in `unsafe` blocks',
 | 
											c.warn('pointer arithmetic is only allowed in `unsafe` blocks',
 | 
				
			||||||
							assign_stmt.pos)
 | 
												node.pos)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					c.error('cannot assign to `$left`: $err.msg', right.position())
 | 
										c.error('cannot assign to `$left`: $err.msg', right.position())
 | 
				
			||||||
| 
						 | 
					@ -3608,8 +3607,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
	// so that ident.obj is set
 | 
						// so that ident.obj is set
 | 
				
			||||||
	// Check `x := &y` and `mut x := <-ch`
 | 
						// Check `x := &y` and `mut x := <-ch`
 | 
				
			||||||
	if right_first is ast.PrefixExpr {
 | 
						if right_first is ast.PrefixExpr {
 | 
				
			||||||
		node := right_first
 | 
							right_node := right_first
 | 
				
			||||||
		left_first := assign_stmt.left[0]
 | 
							left_first := node.left[0]
 | 
				
			||||||
		if left_first is ast.Ident {
 | 
							if left_first is ast.Ident {
 | 
				
			||||||
			assigned_var := left_first
 | 
								assigned_var := left_first
 | 
				
			||||||
			mut is_shared := false
 | 
								mut is_shared := false
 | 
				
			||||||
| 
						 | 
					@ -3617,41 +3616,40 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
 | 
				
			||||||
				is_shared = left_first.info.share == .shared_t
 | 
									is_shared = left_first.info.share == .shared_t
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			old_inside_ref_lit := c.inside_ref_lit
 | 
								old_inside_ref_lit := c.inside_ref_lit
 | 
				
			||||||
			c.inside_ref_lit = (c.inside_ref_lit || node.op == .amp || is_shared)
 | 
								c.inside_ref_lit = (c.inside_ref_lit || right_node.op == .amp || is_shared)
 | 
				
			||||||
			c.expr(node.right)
 | 
								c.expr(right_node.right)
 | 
				
			||||||
			c.inside_ref_lit = old_inside_ref_lit
 | 
								c.inside_ref_lit = old_inside_ref_lit
 | 
				
			||||||
			if node.op == .amp {
 | 
								if right_node.op == .amp {
 | 
				
			||||||
				if node.right is ast.Ident {
 | 
									if right_node.right is ast.Ident {
 | 
				
			||||||
					if node.right.obj is ast.Var {
 | 
										if right_node.right.obj is ast.Var {
 | 
				
			||||||
						v := node.right.obj
 | 
											v := right_node.right.obj
 | 
				
			||||||
						right_type0 = v.typ
 | 
											right_type0 = v.typ
 | 
				
			||||||
						if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
 | 
											if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
 | 
				
			||||||
							c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
 | 
												c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
 | 
				
			||||||
								node.pos)
 | 
													right_node.pos)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else if node.right.obj is ast.ConstField {
 | 
										} else if right_node.right.obj is ast.ConstField {
 | 
				
			||||||
						if assigned_var.is_mut && !c.inside_unsafe {
 | 
											if assigned_var.is_mut && !c.inside_unsafe {
 | 
				
			||||||
							c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
 | 
												c.error('`$right_node.right.name` is immutable, cannot have a mutable reference to it',
 | 
				
			||||||
								node.pos)
 | 
													right_node.pos)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if node.op == .arrow {
 | 
								if right_node.op == .arrow {
 | 
				
			||||||
				if assigned_var.is_mut {
 | 
									if assigned_var.is_mut {
 | 
				
			||||||
					right_sym := c.table.get_type_symbol(right_type0)
 | 
										right_sym := c.table.get_type_symbol(right_type0)
 | 
				
			||||||
					if right_sym.kind == .chan {
 | 
										if right_sym.kind == .chan {
 | 
				
			||||||
						chan_info := right_sym.chan_info()
 | 
											chan_info := right_sym.chan_info()
 | 
				
			||||||
						if chan_info.elem_type.is_ptr() && !chan_info.is_mut {
 | 
											if chan_info.elem_type.is_ptr() && !chan_info.is_mut {
 | 
				
			||||||
							c.error('cannot have a mutable reference to object from `$right_sym.name`',
 | 
												c.error('cannot have a mutable reference to object from `$right_sym.name`',
 | 
				
			||||||
								node.pos)
 | 
													right_node.pos)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// right_sym := c.table.get_type_symbol(right_type_unwrapped)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn scope_register_it(mut s ast.Scope, pos token.Position, typ ast.Type) {
 | 
					fn scope_register_it(mut s ast.Scope, pos token.Position, typ ast.Type) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue