all: nested sum types (#6913)
							parent
							
								
									c7ca1e7e13
								
							
						
					
					
						commit
						96539e43b5
					
				| 
						 | 
					@ -365,7 +365,7 @@ pub:
 | 
				
			||||||
	is_arg          bool // fn args should not be autofreed
 | 
						is_arg          bool // fn args should not be autofreed
 | 
				
			||||||
pub mut:
 | 
					pub mut:
 | 
				
			||||||
	typ             table.Type
 | 
						typ             table.Type
 | 
				
			||||||
	sum_type_cast   table.Type
 | 
						sum_type_casts  []table.Type // nested sum types require nested smart casting, for that a list of types is needed
 | 
				
			||||||
	pos             token.Position
 | 
						pos             token.Position
 | 
				
			||||||
	is_used         bool
 | 
						is_used         bool
 | 
				
			||||||
	is_changed      bool // to detect mutable vars that are never changed
 | 
						is_changed      bool // to detect mutable vars that are never changed
 | 
				
			||||||
| 
						 | 
					@ -379,7 +379,7 @@ pub:
 | 
				
			||||||
	name           string
 | 
						name           string
 | 
				
			||||||
	pos            token.Position
 | 
						pos            token.Position
 | 
				
			||||||
	typ            table.Type
 | 
						typ            table.Type
 | 
				
			||||||
	sum_type_cast table.Type
 | 
						sum_type_casts []table.Type // nested sum types require nested smart casting, for that a list of types is needed
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct GlobalField {
 | 
					pub struct GlobalField {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1801,7 +1801,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
 | 
				
			||||||
			if !prevent_sum_type_unwrapping_once {
 | 
								if !prevent_sum_type_unwrapping_once {
 | 
				
			||||||
				scope := c.file.scope.innermost(selector_expr.pos.pos)
 | 
									scope := c.file.scope.innermost(selector_expr.pos.pos)
 | 
				
			||||||
				if scope_field := scope.find_struct_field(utyp, field_name) {
 | 
									if scope_field := scope.find_struct_field(utyp, field_name) {
 | 
				
			||||||
					return scope_field.sum_type_cast
 | 
										return scope_field.sum_type_casts.last()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -3234,9 +3234,9 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
 | 
				
			||||||
						c.error('undefined variable `$ident.name` (used before declaration)',
 | 
											c.error('undefined variable `$ident.name` (used before declaration)',
 | 
				
			||||||
							ident.pos)
 | 
												ident.pos)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					is_sum_type_cast := obj.sum_type_cast != 0 && !c.prevent_sum_type_unwrapping_once
 | 
										is_sum_type_cast := obj.sum_type_casts.len != 0 && !c.prevent_sum_type_unwrapping_once
 | 
				
			||||||
					c.prevent_sum_type_unwrapping_once = false
 | 
										c.prevent_sum_type_unwrapping_once = false
 | 
				
			||||||
					mut typ := if is_sum_type_cast { obj.sum_type_cast } else { obj.typ }
 | 
										mut typ := if is_sum_type_cast { obj.sum_type_casts.last() } else { obj.typ }
 | 
				
			||||||
					if typ == 0 {
 | 
										if typ == 0 {
 | 
				
			||||||
						if mut obj.expr is ast.Ident {
 | 
											if mut obj.expr is ast.Ident {
 | 
				
			||||||
							if obj.expr.kind == .unresolved {
 | 
												if obj.expr.kind == .unresolved {
 | 
				
			||||||
| 
						 | 
					@ -3561,37 +3561,47 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
 | 
				
			||||||
				mut scope := c.file.scope.innermost(branch.pos.pos)
 | 
									mut scope := c.file.scope.innermost(branch.pos.pos)
 | 
				
			||||||
				match mut node.cond {
 | 
									match mut node.cond {
 | 
				
			||||||
					ast.SelectorExpr {
 | 
										ast.SelectorExpr {
 | 
				
			||||||
 | 
											mut is_mut := false
 | 
				
			||||||
 | 
											mut sum_type_casts := []table.Type{}
 | 
				
			||||||
						expr_sym := c.table.get_type_symbol(node.cond.expr_type)
 | 
											expr_sym := c.table.get_type_symbol(node.cond.expr_type)
 | 
				
			||||||
						field := c.table.struct_find_field(expr_sym, node.cond.field_name) or {
 | 
											if field := c.table.struct_find_field(expr_sym, node.cond.field_name) {
 | 
				
			||||||
							table.Field{}
 | 
												is_mut = field.is_mut
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if field := scope.find_struct_field(node.cond.expr_type, node.cond.field_name) {
 | 
				
			||||||
 | 
												sum_type_casts << field.sum_type_casts
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						is_mut := field.is_mut
 | 
					 | 
				
			||||||
						is_root_mut := scope.is_selector_root_mutable(c.table, node.cond)
 | 
											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
 | 
											// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
				
			||||||
						if (!is_root_mut && !is_mut) || node.is_mut {
 | 
											if (!is_root_mut && !is_mut) || node.is_mut {
 | 
				
			||||||
 | 
												sum_type_casts << expr_type
 | 
				
			||||||
							scope.register_struct_field(ast.ScopeStructField{
 | 
												scope.register_struct_field(ast.ScopeStructField{
 | 
				
			||||||
								struct_type: node.cond.expr_type
 | 
													struct_type: node.cond.expr_type
 | 
				
			||||||
								name: node.cond.field_name
 | 
													name: node.cond.field_name
 | 
				
			||||||
								typ: node.cond_type
 | 
													typ: node.cond_type
 | 
				
			||||||
								sum_type_cast: expr_type
 | 
													sum_type_casts: sum_type_casts
 | 
				
			||||||
								pos: node.cond.pos
 | 
													pos: node.cond.pos
 | 
				
			||||||
							})
 | 
												})
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					ast.Ident {
 | 
										ast.Ident {
 | 
				
			||||||
						mut is_mut := false
 | 
											mut is_mut := false
 | 
				
			||||||
 | 
											mut sum_type_casts := []table.Type{}
 | 
				
			||||||
 | 
											mut is_already_casted := false
 | 
				
			||||||
						if v := scope.find_var(node.cond.name) {
 | 
											if v := scope.find_var(node.cond.name) {
 | 
				
			||||||
							is_mut = v.is_mut
 | 
												is_mut = v.is_mut
 | 
				
			||||||
 | 
												sum_type_casts << v.sum_type_casts
 | 
				
			||||||
 | 
												is_already_casted = v.pos.pos == node.cond.pos.pos
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
											// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
				
			||||||
						if !is_mut || node.is_mut {
 | 
											if (!is_mut || node.is_mut) && !is_already_casted {
 | 
				
			||||||
 | 
												sum_type_casts << expr_type
 | 
				
			||||||
							scope.register(node.var_name, ast.Var{
 | 
												scope.register(node.var_name, ast.Var{
 | 
				
			||||||
								name: node.var_name
 | 
													name: node.var_name
 | 
				
			||||||
								typ: node.cond_type
 | 
													typ: node.cond_type
 | 
				
			||||||
								pos: node.cond.pos
 | 
													pos: node.cond.pos
 | 
				
			||||||
								is_used: true
 | 
													is_used: true
 | 
				
			||||||
								is_mut: node.is_mut
 | 
													is_mut: node.is_mut
 | 
				
			||||||
								sum_type_cast: expr_type
 | 
													sum_type_casts: sum_type_casts
 | 
				
			||||||
							})
 | 
												})
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -3823,38 +3833,46 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
 | 
				
			||||||
							mut is_mut := false
 | 
												mut is_mut := false
 | 
				
			||||||
							mut scope := c.file.scope.innermost(branch.body_pos.pos)
 | 
												mut scope := c.file.scope.innermost(branch.body_pos.pos)
 | 
				
			||||||
							if mut infix.left is ast.Ident {
 | 
												if mut infix.left is ast.Ident {
 | 
				
			||||||
 | 
													mut sum_type_casts := []table.Type{}
 | 
				
			||||||
								if v := scope.find_var(infix.left.name) {
 | 
													if v := scope.find_var(infix.left.name) {
 | 
				
			||||||
									is_mut = v.is_mut
 | 
														is_mut = v.is_mut
 | 
				
			||||||
 | 
														sum_type_casts << v.sum_type_casts
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
													// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
				
			||||||
								if (!is_mut || branch.is_mut_name) &&
 | 
													if (!is_mut || branch.is_mut_name) &&
 | 
				
			||||||
									left_sym.kind == .union_sum_type {
 | 
														left_sym.kind == .union_sum_type {
 | 
				
			||||||
 | 
														sum_type_casts << right_expr.typ
 | 
				
			||||||
									scope.register(branch.left_as_name, ast.Var{
 | 
														scope.register(branch.left_as_name, ast.Var{
 | 
				
			||||||
										name: branch.left_as_name
 | 
															name: branch.left_as_name
 | 
				
			||||||
										typ: infix.left_type
 | 
															typ: infix.left_type
 | 
				
			||||||
										sum_type_cast: right_expr.typ
 | 
															sum_type_casts: sum_type_casts
 | 
				
			||||||
										pos: infix.left.pos
 | 
															pos: infix.left.pos
 | 
				
			||||||
										is_used: true
 | 
															is_used: true
 | 
				
			||||||
										is_mut: is_mut
 | 
															is_mut: is_mut
 | 
				
			||||||
									})
 | 
														})
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							} else if mut infix.left is ast.SelectorExpr {
 | 
												} else if mut infix.left is ast.SelectorExpr {
 | 
				
			||||||
 | 
													mut sum_type_casts := []table.Type{}
 | 
				
			||||||
								expr_sym := c.table.get_type_symbol(infix.left.expr_type)
 | 
													expr_sym := c.table.get_type_symbol(infix.left.expr_type)
 | 
				
			||||||
								field := c.table.struct_find_field(expr_sym, infix.left.field_name) or {
 | 
													if field := c.table.struct_find_field(expr_sym, infix.left.field_name) {
 | 
				
			||||||
									table.Field{}
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
									is_mut = field.is_mut
 | 
														is_mut = field.is_mut
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													if field := scope.find_struct_field(infix.left.expr_type,
 | 
				
			||||||
 | 
														infix.left.field_name) {
 | 
				
			||||||
 | 
														sum_type_casts << field.sum_type_casts
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
								is_root_mut := scope.is_selector_root_mutable(c.table,
 | 
													is_root_mut := scope.is_selector_root_mutable(c.table,
 | 
				
			||||||
									infix.left)
 | 
														infix.left)
 | 
				
			||||||
								// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
													// smartcast either if the value is immutable or if the mut argument is explicitly given
 | 
				
			||||||
								if ((!is_root_mut && !is_mut) ||
 | 
													if ((!is_root_mut && !is_mut) ||
 | 
				
			||||||
									branch.is_mut_name) &&
 | 
														branch.is_mut_name) &&
 | 
				
			||||||
									left_sym.kind == .union_sum_type {
 | 
														left_sym.kind == .union_sum_type {
 | 
				
			||||||
 | 
														sum_type_casts << right_expr.typ
 | 
				
			||||||
									scope.register_struct_field(ast.ScopeStructField{
 | 
														scope.register_struct_field(ast.ScopeStructField{
 | 
				
			||||||
										struct_type: infix.left.expr_type
 | 
															struct_type: infix.left.expr_type
 | 
				
			||||||
										name: infix.left.field_name
 | 
															name: infix.left.field_name
 | 
				
			||||||
										typ: infix.left_type
 | 
															typ: infix.left_type
 | 
				
			||||||
										sum_type_cast: right_expr.typ
 | 
															sum_type_casts: sum_type_casts
 | 
				
			||||||
										pos: infix.left.pos
 | 
															pos: infix.left.pos
 | 
				
			||||||
									})
 | 
														})
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/sum_type_assign_non_variant_err.vv:11:6: error: cannot assign to `w`: expected `Stmt`, not `IfExpr`
 | 
				
			||||||
 | 
					    9 | fn main() {
 | 
				
			||||||
 | 
					   10 |     mut w := Stmt{}
 | 
				
			||||||
 | 
					   11 |     w = IfExpr{}
 | 
				
			||||||
 | 
					      |         ~~~~~~~~
 | 
				
			||||||
 | 
					   12 | }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					__type Expr = IfExpr | CallExpr | MatchExpr
 | 
				
			||||||
 | 
					struct MatchExpr {}
 | 
				
			||||||
 | 
					struct IfExpr {}
 | 
				
			||||||
 | 
					struct CallExpr {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__type Stmt = Expr | AnotherThing
 | 
				
			||||||
 | 
					struct AnotherThing {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    mut w := Stmt{}
 | 
				
			||||||
 | 
						w = IfExpr{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1301,7 +1301,7 @@ fn (mut g Gen) union_expr_with_cast(expr ast.Expr, got_type table.Type, expected
 | 
				
			||||||
				scope := g.file.scope.innermost(expr.position().pos)
 | 
									scope := g.file.scope.innermost(expr.position().pos)
 | 
				
			||||||
				if expr is ast.Ident {
 | 
									if expr is ast.Ident {
 | 
				
			||||||
					if v := scope.find_var(expr.name) {
 | 
										if v := scope.find_var(expr.name) {
 | 
				
			||||||
						if v.sum_type_cast != 0 {
 | 
											if v.sum_type_casts.len > 0 {
 | 
				
			||||||
							is_already_sum_type = true
 | 
												is_already_sum_type = true
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -2567,12 +2567,17 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
				
			||||||
						scope := g.file.scope.innermost(node.pos.pos)
 | 
											scope := g.file.scope.innermost(node.pos.pos)
 | 
				
			||||||
						if field := scope.find_struct_field(node.expr_type, node.field_name) {
 | 
											if field := scope.find_struct_field(node.expr_type, node.field_name) {
 | 
				
			||||||
							// union sum type deref
 | 
												// union sum type deref
 | 
				
			||||||
 | 
												for i, typ in field.sum_type_casts {
 | 
				
			||||||
								g.write('(*')
 | 
													g.write('(*')
 | 
				
			||||||
							cast_sym := g.table.get_type_symbol(field.sum_type_cast)
 | 
													cast_sym := g.table.get_type_symbol(typ)
 | 
				
			||||||
 | 
													if i != 0 {
 | 
				
			||||||
 | 
														sum_type_deref_field += ').'
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
								if cast_sym.info is table.Aggregate as sym_info {
 | 
													if cast_sym.info is table.Aggregate as sym_info {
 | 
				
			||||||
								sum_type_deref_field = '_${sym_info.types[g.aggregate_type_idx]}'
 | 
														sum_type_deref_field += '_${sym_info.types[g.aggregate_type_idx]}'
 | 
				
			||||||
								} else {
 | 
													} else {
 | 
				
			||||||
								sum_type_deref_field = '_$field.sum_type_cast'
 | 
														sum_type_deref_field += '_$typ'
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -3403,13 +3408,22 @@ fn (mut g Gen) ident(node ast.Ident) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		scope := g.file.scope.innermost(node.pos.pos)
 | 
							scope := g.file.scope.innermost(node.pos.pos)
 | 
				
			||||||
		if v := scope.find_var(node.name) {
 | 
							if v := scope.find_var(node.name) {
 | 
				
			||||||
			if v.sum_type_cast != 0 {
 | 
								if v.sum_type_casts.len > 0 {
 | 
				
			||||||
				if !prevent_sum_type_unwrapping_once {
 | 
									if !prevent_sum_type_unwrapping_once {
 | 
				
			||||||
					sym := g.table.get_type_symbol(v.sum_type_cast)
 | 
										for _ in v.sum_type_casts {
 | 
				
			||||||
					if sym.info is table.Aggregate as sym_info {
 | 
											g.write('(*')
 | 
				
			||||||
						g.write('(*${name}._${sym_info.types[g.aggregate_type_idx]})')
 | 
										}
 | 
				
			||||||
 | 
										for i, typ in v.sum_type_casts {
 | 
				
			||||||
 | 
											cast_sym := g.table.get_type_symbol(typ)
 | 
				
			||||||
 | 
											if i == 0 {
 | 
				
			||||||
 | 
												g.write(name)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if cast_sym.info is table.Aggregate as sym_info {
 | 
				
			||||||
 | 
												g.write('._${sym_info.types[g.aggregate_type_idx]}')
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
						g.write('(*${name}._$v.sum_type_cast)')
 | 
												g.write('._$typ')
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											g.write(')')
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -4645,7 +4659,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				g.type_definitions.writeln('typedef struct {')
 | 
									g.type_definitions.writeln('typedef struct {')
 | 
				
			||||||
				g.type_definitions.writeln('    union {')
 | 
									g.type_definitions.writeln('    union {')
 | 
				
			||||||
				for variant in g.table.get_union_sum_type_variants(it) {
 | 
									for variant in it.variants {
 | 
				
			||||||
					g.type_definitions.writeln('        ${g.typ(variant.to_ptr())} _$variant.idx();')
 | 
										g.type_definitions.writeln('        ${g.typ(variant.to_ptr())} _$variant.idx();')
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				g.type_definitions.writeln('    };')
 | 
									g.type_definitions.writeln('    };')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -853,18 +853,6 @@ pub:
 | 
				
			||||||
	variants []Type
 | 
						variants []Type
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn (table &Table) get_union_sum_type_variants(sum_type UnionSumType) []Type {
 | 
					 | 
				
			||||||
	mut variants := []Type{}
 | 
					 | 
				
			||||||
	for variant in sum_type.variants {
 | 
					 | 
				
			||||||
		sym := table.get_type_symbol(variant)
 | 
					 | 
				
			||||||
		if sym.info is UnionSumType as sym_info {
 | 
					 | 
				
			||||||
			variants << table.get_union_sum_type_variants(sym_info)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		variants << variant
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return variants
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn (table &Table) type_to_str(t Type) string {
 | 
					pub fn (table &Table) type_to_str(t Type) string {
 | 
				
			||||||
	sym := table.get_type_symbol(t)
 | 
						sym := table.get_type_symbol(t)
 | 
				
			||||||
	mut res := sym.source_name
 | 
						mut res := sym.source_name
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -738,9 +738,6 @@ pub fn (table &Table) sumtype_has_variant(parent Type, variant Type) bool {
 | 
				
			||||||
			if v.idx() == variant.idx() {
 | 
								if v.idx() == variant.idx() {
 | 
				
			||||||
				return true
 | 
									return true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if table.sumtype_has_variant(v, variant) {
 | 
					 | 
				
			||||||
				return true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,15 +106,49 @@ fn test_converting_down() {
 | 
				
			||||||
	assert res[1].name == 'three'
 | 
						assert res[1].name == 'three'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct NodeWrapper {
 | 
				
			||||||
 | 
						node Node
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_nested_sumtype_selector() {
 | 
				
			||||||
 | 
						c := NodeWrapper{Node(Expr(IfExpr{pos: 1}))}
 | 
				
			||||||
 | 
						if c.node is Expr {
 | 
				
			||||||
 | 
							if c.node is IfExpr {
 | 
				
			||||||
 | 
								assert c.node.pos == 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								assert false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							assert false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_nested_sumtype_match_selector() {
 | 
				
			||||||
 | 
						c := NodeWrapper{Node(Expr(IfExpr{pos: 1}))}
 | 
				
			||||||
 | 
						match union c.node {
 | 
				
			||||||
 | 
							Expr {
 | 
				
			||||||
 | 
								match union c.node {
 | 
				
			||||||
 | 
									IfExpr {
 | 
				
			||||||
 | 
										assert c.node.pos == 1
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										assert false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								assert false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn test_nested_sumtype() {
 | 
					fn test_nested_sumtype() {
 | 
				
			||||||
	mut a := Node{}
 | 
					 | 
				
			||||||
	mut b := Node{}
 | 
					 | 
				
			||||||
	a = StructDecl{pos: 1}
 | 
					 | 
				
			||||||
	b = IfExpr{pos: 1}
 | 
					 | 
				
			||||||
	c := Node(Expr(IfExpr{pos:1}))
 | 
						c := Node(Expr(IfExpr{pos:1}))
 | 
				
			||||||
	if c is Expr {
 | 
						if c is Expr {
 | 
				
			||||||
		if c is IfExpr {
 | 
							if c is IfExpr {
 | 
				
			||||||
			assert true
 | 
								assert c.pos == 1
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			assert false
 | 
								assert false
 | 
				
			||||||
| 
						 | 
					@ -125,6 +159,25 @@ fn test_nested_sumtype() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_nested_sumtype_match() {
 | 
				
			||||||
 | 
						c := Node(Expr(IfExpr{pos: 1}))
 | 
				
			||||||
 | 
						match union c {
 | 
				
			||||||
 | 
							Expr {
 | 
				
			||||||
 | 
								match union c {
 | 
				
			||||||
 | 
									IfExpr {
 | 
				
			||||||
 | 
										assert c.pos == 1
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										assert false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								assert false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__type Abc = int | string
 | 
					__type Abc = int | string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn test_string_cast_to_sumtype() {
 | 
					fn test_string_cast_to_sumtype() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue