checker: fixes typechecking for a sum type with an alias type (#13974)
							parent
							
								
									dc08105022
								
							
						
					
					
						commit
						48c295150f
					
				|  | @ -1280,25 +1280,54 @@ pub fn (t &Table) sumtype_has_variant(parent Type, variant Type, is_as bool) boo | ||||||
| 	if parent_sym.kind == .sum_type { | 	if parent_sym.kind == .sum_type { | ||||||
| 		parent_info := parent_sym.info as SumType | 		parent_info := parent_sym.info as SumType | ||||||
| 		var_sym := t.sym(variant) | 		var_sym := t.sym(variant) | ||||||
| 		if var_sym.kind == .aggregate { | 		match var_sym.kind { | ||||||
| 			var_info := var_sym.info as Aggregate | 			.aggregate { | ||||||
| 			for var_type in var_info.types { | 				return t.sumtype_check_aggregate_variant(parent, variant, is_as) | ||||||
| 				if !t.sumtype_has_variant(parent, var_type, is_as) { |  | ||||||
| 					return false |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 			return true | 			.alias { | ||||||
| 		} else { | 				return t.sumtype_check_alias_variant(parent, variant, is_as) | ||||||
| 			for v in parent_info.variants { | 			} | ||||||
| 				if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) { | 			else { | ||||||
| 					return true | 				return t.sumtype_check_variant_in_type(parent_info, variant, is_as) | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn (t &Table) sumtype_check_variant_in_type(parent_info SumType, variant Type, is_as bool) bool { | ||||||
|  | 	for v in parent_info.variants { | ||||||
|  | 		if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn (t &Table) sumtype_check_aggregate_variant(parent_type Type, aggregate_type &Type, is_as bool) bool { | ||||||
|  | 	aggregate_sym := t.sym(aggregate_type).info as Aggregate | ||||||
|  | 	for var_type in aggregate_sym.types { | ||||||
|  | 		if !t.sumtype_has_variant(parent_type, var_type, is_as) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn (t &Table) sumtype_check_alias_variant(parent_type Type, alias_type Type, is_as bool) bool { | ||||||
|  | 	parent_sym := t.sym(parent_type).info as SumType | ||||||
|  | 	if !t.sumtype_check_variant_in_type(parent_sym, alias_type, is_as) { | ||||||
|  | 		alias_info := t.sym(alias_type).info as Alias | ||||||
|  | 		// The alias is an alias or of the same sumtype parent, or one
 | ||||||
|  | 		// of the SumType variant. e.g: alias of another sum type.
 | ||||||
|  | 		// https://github.com/vlang/v/issues/14029
 | ||||||
|  | 		return parent_type == alias_info.parent_type | ||||||
|  | 			|| t.sumtype_has_variant(parent_type, alias_info.parent_type, is_as) | ||||||
|  | 	} | ||||||
|  | 	// the alias_type is inside one of the variant of the sum type
 | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn (t &Table) is_sumtype_or_in_variant(parent Type, typ Type) bool { | pub fn (t &Table) is_sumtype_or_in_variant(parent Type, typ Type) bool { | ||||||
| 	if typ == 0 { | 	if typ == 0 { | ||||||
| 		return false | 		return false | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | // THE END. | ||||||
|  | @ -0,0 +1,32 @@ | ||||||
|  | type ParseRes = Result<[]Token, ParseErr> | ||||||
|  | 
 | ||||||
|  | struct ParseErr {} | ||||||
|  | 
 | ||||||
|  | type Opt<T> = None<T> | Some<T> | ||||||
|  | 
 | ||||||
|  | struct None<T> {} | ||||||
|  | 
 | ||||||
|  | struct Some<T> { | ||||||
|  | 	value T | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Result<T, U> = Err<U> | Ok<T> | ||||||
|  | 
 | ||||||
|  | struct Ok<T> { | ||||||
|  | 	value T | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Err<U> { | ||||||
|  | 	value U | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  | 	r := Opt<ParseRes>(None<ParseRes>{}) | ||||||
|  | 	match r { | ||||||
|  | 		Some<ParseRes> { | ||||||
|  | 			// make possible cast fo the same type!
 | ||||||
|  | 			rx := Result<[]Token, ParseErr>(r.value) | ||||||
|  | 		} | ||||||
|  | 		None<ParseRes> {} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -1,8 +1,6 @@ | ||||||
| type ParseRes = Result<[]Token, ParseErr> | type ParseRes = Result<[]Token, ParseErr> | ||||||
| 
 | 
 | ||||||
| struct ParseErr{ | struct ParseErr {} | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| type Opt<T> = None<T> | Some<T> | type Opt<T> = None<T> | Some<T> | ||||||
| 
 | 
 | ||||||
|  | @ -26,7 +24,7 @@ fn test_report() { | ||||||
| 	r := Opt<ParseRes>(None<ParseRes>{}) | 	r := Opt<ParseRes>(None<ParseRes>{}) | ||||||
| 	match r { | 	match r { | ||||||
| 		Some<ParseRes> { | 		Some<ParseRes> { | ||||||
| 			rx := Result<[]Token, ParseErr>(r) | 			rx := Result<[]Token, ParseErr>(r.value) | ||||||
| 		} | 		} | ||||||
| 		None<ParseRes> {} | 		None<ParseRes> {} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue