Browse Source

Merge pull request #1802 from odin-lang/remove-maybe-tag

Merge functionality of `#maybe` with the standard 'union' functionality
gingerBill 3 years ago
parent
commit
a31d23a32a

+ 1 - 1
core/encoding/json/unmarshal.odin

@@ -209,7 +209,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
 		variant := u.variants[0]
 		v.id = variant.id
 		ti = reflect.type_info_base(variant)
-		if !(u.maybe && reflect.is_pointer(variant)) {
+		if !reflect.is_pointer_internally(variant) {
 			tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id}
 			assign_int(tag, 1)
 		}

+ 1 - 1
core/reflect/reflect.odin

@@ -654,7 +654,7 @@ union_variant_type_info :: proc(a: any) -> ^Type_Info {
 }
 
 type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool {
-	return info.maybe && len(info.variants) == 1 && is_pointer(info.variants[0])
+	return len(info.variants) == 1 && is_pointer(info.variants[0])
 }
 
 union_variant_typeid :: proc(a: any) -> typeid {

+ 13 - 3
core/reflect/types.odin

@@ -256,6 +256,17 @@ is_multi_pointer :: proc(info: ^Type_Info) -> bool {
 	_, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer)
 	return ok
 }
+is_pointer_internally :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false }
+	#partial switch v in info.variant {
+	case Type_Info_Pointer, Type_Info_Multi_Pointer,
+	     Type_Info_Procedure:
+		return true
+	case Type_Info_String:
+		return v.is_cstring
+	}
+	return false
+}
 is_procedure :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false }
 	_, ok := type_info_base(info).variant.(Type_Info_Procedure)
@@ -531,9 +542,8 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
 
 	case Type_Info_Union:
 		io.write_string(w, "union ", &n) or_return
-		if info.maybe {
-			io.write_string(w, "#maybe ", &n) or_return
-		}
+		if info.no_nil     { io.write_string(w, "#no_nil ", &n)     or_return }
+		if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return }
 		if info.custom_align {
 			io.write_string(w, "#align ",      &n) or_return
 			io.write_i64(w, i64(ti.align), 10, &n) or_return

+ 0 - 1
core/runtime/core.odin

@@ -135,7 +135,6 @@ Type_Info_Union :: struct {
 
 	custom_align: bool,
 	no_nil:       bool,
-	maybe:        bool,
 	shared_nil:   bool,
 }
 Type_Info_Enum :: struct {

+ 1 - 1
core/runtime/core_builtin.odin

@@ -3,7 +3,7 @@ package runtime
 import "core:intrinsics"
 
 @builtin
-Maybe :: union($T: typeid) #maybe {T}
+Maybe :: union($T: typeid) {T}
 
 
 @builtin

+ 4 - 2
examples/demo/demo.odin

@@ -1977,15 +1977,17 @@ constant_literal_expressions :: proc() {
 }
 
 union_maybe :: proc() {
-	fmt.println("\n#union #maybe")
+	fmt.println("\n#union based maybe")
 
 	// NOTE: This is already built-in, and this is just a reimplementation to explain the behaviour
-	Maybe :: union($T: typeid) #maybe {T}
+	Maybe :: union($T: typeid) {T}
 
 	i: Maybe(u8)
 	p: Maybe(^u8) // No tag is stored for pointers, nil is the sentinel value
 
+	// Tag size will be as small as needed for the number of variants
 	#assert(size_of(i) == size_of(u8) + size_of(u8))
+	// No need to store a tag here, the `nil` state is shared with the variant's `nil`
 	#assert(size_of(p) == size_of(^u8))
 
 	i = 123

+ 0 - 1
src/check_expr.cpp

@@ -10065,7 +10065,6 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
 			str = gb_string_appendc(str, ") ");
 		}
 		switch (st->kind) {
-		case UnionType_maybe:      str = gb_string_appendc(str, "#maybe ");      break;
 		case UnionType_no_nil:     str = gb_string_appendc(str, "#no_nil ");     break;
 		case UnionType_shared_nil: str = gb_string_appendc(str, "#shared_nil "); break;
 		}

+ 0 - 1
src/docs_writer.cpp

@@ -620,7 +620,6 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
 		doc_type.kind = OdinDocType_Union;
 		if (type->Union.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Union_polymorphic; }
 		switch (type->Union.kind) {
-		case UnionType_maybe:      doc_type.flags |= OdinDocTypeFlag_Union_maybe;      break;
 		case UnionType_no_nil:     doc_type.flags |= OdinDocTypeFlag_Union_no_nil;     break;
 		case UnionType_shared_nil: doc_type.flags |= OdinDocTypeFlag_Union_shared_nil; break;
 		}

+ 2 - 3
src/llvm_backend_type.cpp

@@ -641,7 +641,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 			tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_union_ptr);
 
 			{
-				LLVMValueRef vals[8] = {};
+				LLVMValueRef vals[7] = {};
 
 				isize variant_count = gb_max(0, t->Union.variants.count);
 				lbValue memory_types = lb_type_info_member_types_offset(p, variant_count);
@@ -676,8 +676,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 
 				vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value;
 				vals[5] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_no_nil).value;
-				vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_maybe).value;
-				vals[7] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value;
+				vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value;
 
 				for (isize i = 0; i < gb_count_of(vals); i++) {
 					if (vals[i] == nullptr) {

+ 1 - 0
src/parser.cpp

@@ -2529,6 +2529,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
 
 		if (maybe) {
 			union_kind = UnionType_maybe;
+			syntax_error(f->curr_token, "#maybe functionality has now been merged with standard 'union' functionality");
 		} else if (no_nil) {
 			union_kind = UnionType_no_nil;
 		} else if (shared_nil) {

+ 1 - 1
src/parser.hpp

@@ -332,7 +332,7 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
 
 enum UnionTypeKind : u8 {
 	UnionType_Normal     = 0,
-	UnionType_maybe      = 1,
+	UnionType_maybe      = 1, // removed
 	UnionType_no_nil     = 2,
 	UnionType_shared_nil = 3,
 };

+ 7 - 12
src/types.cpp

@@ -1685,11 +1685,9 @@ bool is_type_map(Type *t) {
 
 bool is_type_union_maybe_pointer(Type *t) {
 	t = base_type(t);
-	if (t->kind == Type_Union && t->Union.kind == UnionType_maybe) {
-		if (t->Union.variants.count == 1) {
-			Type *v = t->Union.variants[0];
-			return is_type_pointer(v) || is_type_multi_pointer(v);
-		}
+	if (t->kind == Type_Union && t->Union.variants.count == 1) {
+		Type *v = t->Union.variants[0];
+		return is_type_internally_pointer_like(v);
 	}
 	return false;
 }
@@ -1697,12 +1695,10 @@ bool is_type_union_maybe_pointer(Type *t) {
 
 bool is_type_union_maybe_pointer_original_alignment(Type *t) {
 	t = base_type(t);
-	if (t->kind == Type_Union && t->Union.kind == UnionType_maybe) {
-		if (t->Union.variants.count == 1) {
-			Type *v = t->Union.variants[0];
-			if (is_type_pointer(v) || is_type_multi_pointer(v)) {
-				return type_align_of(v) == type_align_of(t);
-			}
+	if (t->kind == Type_Union && t->Union.variants.count == 1) {
+		Type *v = t->Union.variants[0];
+		if (is_type_internally_pointer_like(v)) {
+			return type_align_of(v) == type_align_of(t);
 		}
 	}
 	return false;
@@ -4054,7 +4050,6 @@ gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) {
 	case Type_Union:
 		str = gb_string_appendc(str, "union");
 		switch (type->Union.kind) {
-		case UnionType_maybe:      str = gb_string_appendc(str, " #maybe");      break;
 		case UnionType_no_nil:     str = gb_string_appendc(str, " #no_nil");     break;
 		case UnionType_shared_nil: str = gb_string_appendc(str, " #shared_nil"); break;
 		}