ast, checker, cgen: fix aggregations type check (#14066)
							parent
							
								
									090a9755db
								
							
						
					
					
						commit
						0d4d4ffc2d
					
				| 
						 | 
					@ -937,6 +937,7 @@ pub struct Aggregate {
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
	fields []StructField // used for faster lookup inside the module
 | 
						fields []StructField // used for faster lookup inside the module
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
 | 
						sum_type Type
 | 
				
			||||||
	types    []Type
 | 
						types    []Type
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1013,6 +1013,10 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
 | 
				
			||||||
				if typ_sym.kind == .placeholder {
 | 
									if typ_sym.kind == .placeholder {
 | 
				
			||||||
					c.error('$op: type `$typ_sym.name` does not exist', right_expr.pos())
 | 
										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] {
 | 
									if left_sym.kind !in [.interface_, .sum_type] {
 | 
				
			||||||
					c.error('`$op` can only be used with interfaces and sum types', node.pos)
 | 
										c.error('`$op` can only be used with interfaces and sum types', node.pos)
 | 
				
			||||||
				} else if mut left_sym.info is ast.SumType {
 | 
									} 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) {
 | 
								if right_type != ast.Type(0) {
 | 
				
			||||||
				left_sym := c.table.sym(node.left_type)
 | 
									left_sym := c.table.sym(node.left_type)
 | 
				
			||||||
				right_sym := c.table.sym(right_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 left_sym.kind == .interface_ {
 | 
				
			||||||
					if right_sym.kind != .interface_ {
 | 
										if right_sym.kind != .interface_ {
 | 
				
			||||||
						c.type_implements(right_type, expr_type, node.pos)
 | 
											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
 | 
												kind: .aggregate
 | 
				
			||||||
							mod: c.mod
 | 
												mod: c.mod
 | 
				
			||||||
							info: ast.Aggregate{
 | 
												info: ast.Aggregate{
 | 
				
			||||||
 | 
													sum_type: node.cond_type
 | 
				
			||||||
								types: expr_types.map(it.typ)
 | 
													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`
 | 
					// infix_expr_is_op generates code for `is` and `!is`
 | 
				
			||||||
fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
 | 
					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)
 | 
						right_sym := g.table.sym(node.right_type)
 | 
				
			||||||
	if sym.kind == .interface_ && right_sym.kind == .interface_ {
 | 
						if sym.kind == .interface_ && right_sym.kind == .interface_ {
 | 
				
			||||||
		g.gen_interface_is_op(node)
 | 
							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 { '!=' }
 | 
						cmp_op := if node.op == .key_is { '==' } else { '!=' }
 | 
				
			||||||
	g.write('(')
 | 
						g.write('(')
 | 
				
			||||||
 | 
						if is_aggregate {
 | 
				
			||||||
 | 
							g.write('$node.left')
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		g.expr(node.left)
 | 
							g.expr(node.left)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	g.write(')')
 | 
						g.write(')')
 | 
				
			||||||
	if node.left_type.is_ptr() {
 | 
						if node.left_type.is_ptr() {
 | 
				
			||||||
		g.write('->')
 | 
							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