ast, checker, cgen: fix aggregations type check (#14066)
							parent
							
								
									775c4c34b5
								
							
						
					
					
						commit
						fe371845da
					
				| 
						 | 
				
			
			@ -937,7 +937,8 @@ pub struct Aggregate {
 | 
			
		|||
mut:
 | 
			
		||||
	fields []StructField // used for faster lookup inside the module
 | 
			
		||||
pub:
 | 
			
		||||
	types []Type
 | 
			
		||||
	sum_type Type
 | 
			
		||||
	types    []Type
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Array {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1013,6 +1013,10 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
 | 
			
		|||
				if typ_sym.kind == .placeholder {
 | 
			
		||||
					c.error('$op: type `$typ_sym.name` does not exist', right_expr.pos())
 | 
			
		||||
				}
 | 
			
		||||
				if left_sym.kind == .aggregate {
 | 
			
		||||
					parent_left_type := (left_sym.info as ast.Aggregate).sum_type
 | 
			
		||||
					left_sym = c.table.sym(parent_left_type)
 | 
			
		||||
				}
 | 
			
		||||
				if left_sym.kind !in [.interface_, .sum_type] {
 | 
			
		||||
					c.error('`$op` can only be used with interfaces and sum types', node.pos)
 | 
			
		||||
				} else if mut left_sym.info is ast.SumType {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -296,7 +296,10 @@ fn (mut c Checker) smartcast_if_conds(node ast.Expr, mut scope ast.Scope) {
 | 
			
		|||
			if right_type != ast.Type(0) {
 | 
			
		||||
				left_sym := c.table.sym(node.left_type)
 | 
			
		||||
				right_sym := c.table.sym(right_type)
 | 
			
		||||
				expr_type := c.unwrap_generic(c.expr(node.left))
 | 
			
		||||
				mut expr_type := c.unwrap_generic(c.expr(node.left))
 | 
			
		||||
				if left_sym.kind == .aggregate {
 | 
			
		||||
					expr_type = (left_sym.info as ast.Aggregate).sum_type
 | 
			
		||||
				}
 | 
			
		||||
				if left_sym.kind == .interface_ {
 | 
			
		||||
					if right_sym.kind != .interface_ {
 | 
			
		||||
						c.type_implements(right_type, expr_type, node.pos)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -282,6 +282,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
 | 
			
		|||
							kind: .aggregate
 | 
			
		||||
							mod: c.mod
 | 
			
		||||
							info: ast.Aggregate{
 | 
			
		||||
								sum_type: node.cond_type
 | 
			
		||||
								types: expr_types.map(it.typ)
 | 
			
		||||
							}
 | 
			
		||||
						})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -495,7 +495,12 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, right ast.ArrayInit) {
 | 
			
		|||
 | 
			
		||||
// infix_expr_is_op generates code for `is` and `!is`
 | 
			
		||||
fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
 | 
			
		||||
	sym := g.table.sym(node.left_type)
 | 
			
		||||
	mut sym := g.table.sym(node.left_type)
 | 
			
		||||
	is_aggregate := sym.kind == .aggregate
 | 
			
		||||
	if is_aggregate {
 | 
			
		||||
		parent_left_type := (sym.info as ast.Aggregate).sum_type
 | 
			
		||||
		sym = g.table.sym(parent_left_type)
 | 
			
		||||
	}
 | 
			
		||||
	right_sym := g.table.sym(node.right_type)
 | 
			
		||||
	if sym.kind == .interface_ && right_sym.kind == .interface_ {
 | 
			
		||||
		g.gen_interface_is_op(node)
 | 
			
		||||
| 
						 | 
				
			
			@ -504,7 +509,11 @@ fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
 | 
			
		|||
 | 
			
		||||
	cmp_op := if node.op == .key_is { '==' } else { '!=' }
 | 
			
		||||
	g.write('(')
 | 
			
		||||
	g.expr(node.left)
 | 
			
		||||
	if is_aggregate {
 | 
			
		||||
		g.write('$node.left')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.expr(node.left)
 | 
			
		||||
	}
 | 
			
		||||
	g.write(')')
 | 
			
		||||
	if node.left_type.is_ptr() {
 | 
			
		||||
		g.write('->')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
type Abc = bool | int | string
 | 
			
		||||
 | 
			
		||||
fn test_aggregate_is_nodetype() {
 | 
			
		||||
	x := Abc('test')
 | 
			
		||||
 | 
			
		||||
	match x {
 | 
			
		||||
		string, int {
 | 
			
		||||
			if x is string {
 | 
			
		||||
				println('it is a string')
 | 
			
		||||
				assert true
 | 
			
		||||
			} else {
 | 
			
		||||
				assert false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue