Browse Source

Use `union #shared_nil` for `os.Error`

gingerBill 1 year ago
parent
commit
9f9abb8fb3

+ 2 - 2
core/crypto/rand_windows.odin

@@ -8,8 +8,8 @@ HAS_RAND_BYTES :: true
 
 @(private)
 _rand_bytes :: proc(dst: []byte) {
-	ret := (os.Errno)(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
-	if ret != os.ERROR_NONE {
+	ret := os.Platform_Error(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
+	if ret != nil {
 		#partial switch ret {
 		case os.ERROR_INVALID_HANDLE:
 			// The handle to the first parameter is invalid.

+ 2 - 2
core/os/dir_windows.odin

@@ -88,7 +88,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
 	find_data := &win32.WIN32_FIND_DATAW{}
 	find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
 	if find_handle == win32.INVALID_HANDLE_VALUE {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 		return dfi[:], err
 	}
 	defer win32.FindClose(find_handle)
@@ -101,7 +101,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
 		}
 
 		if !win32.FindNextFileW(find_handle, find_data) {
-			e := Errno(win32.GetLastError())
+			e := Platform_Error(win32.GetLastError())
 			if e == ERROR_NO_MORE_FILES {
 				break
 			}

+ 2 - 2
core/os/env_windows.odin

@@ -50,7 +50,7 @@ set_env :: proc(key, value: string) -> Errno {
 	v := win32.utf8_to_wstring(value)
 
 	if !win32.SetEnvironmentVariableW(k, v) {
-		return Errno(win32.GetLastError())
+		return Platform_Error(win32.GetLastError())
 	}
 	return 0
 }
@@ -59,7 +59,7 @@ set_env :: proc(key, value: string) -> Errno {
 unset_env :: proc(key: string) -> Errno {
 	k := win32.utf8_to_wstring(key)
 	if !win32.SetEnvironmentVariableW(k, nil) {
-		return Errno(win32.GetLastError())
+		return Platform_Error(win32.GetLastError())
 	}
 	return 0
 }

+ 19 - 20
core/os/file_windows.odin

@@ -55,20 +55,20 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errn
 		return handle, ERROR_NONE
 	}
 
-	err := Errno(win32.GetLastError())
+	err := Platform_Error(win32.GetLastError())
 	return INVALID_HANDLE, err
 }
 
 close :: proc(fd: Handle) -> Errno {
 	if !win32.CloseHandle(win32.HANDLE(fd)) {
-		return Errno(win32.GetLastError())
+		return Platform_Error(win32.GetLastError())
 	}
 	return ERROR_NONE
 }
 
 flush :: proc(fd: Handle) -> (err: Errno) {
 	if !win32.FlushFileBuffers(win32.HANDLE(fd)) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }
@@ -90,7 +90,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 
 		e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil)
 		if single_write_length <= 0 || !e {
-			err := Errno(win32.GetLastError())
+			err := Platform_Error(win32.GetLastError())
 			return int(total_write), err
 		}
 		total_write += i64(single_write_length)
@@ -118,7 +118,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
 		single_read_length: u32
 		ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil)
 		if !ok {
-			err = Errno(win32.GetLastError())
+			err = Platform_Error(win32.GetLastError())
 		}
 
 		buf8_len := utf16.decode_to_utf8(buf8[:], buf16[:single_read_length])
@@ -180,7 +180,7 @@ read :: proc(fd: Handle, data: []byte) -> (total_read: int, err: Errno) {
 				return int(bytes_read), ERROR_NONE
 			}
 		} else {
-			return 0, Errno(win32.GetLastError())
+			return 0, Platform_Error(win32.GetLastError())
 		}
 	}
 	return total_read, ERROR_NONE
@@ -202,7 +202,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 
 	dw_ptr := win32.SetFilePointer(win32.HANDLE(fd), lo, &hi, w)
 	if dw_ptr == win32.INVALID_SET_FILE_POINTER {
-		err := Errno(win32.GetLastError())
+		err := Platform_Error(win32.GetLastError())
 		return 0, err
 	}
 	return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE
@@ -212,7 +212,7 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
 	length: win32.LARGE_INTEGER
 	err: Errno
 	if !win32.GetFileSizeEx(win32.HANDLE(fd), &length) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return i64(length), err
 }
@@ -220,7 +220,6 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
 
 @(private)
 MAX_RW :: 1<<30
-ERROR_EOF :: 38
 
 @(private)
 pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
@@ -241,7 +240,7 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 	done: win32.DWORD
 	e: Errno
 	if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
-		e = Errno(win32.GetLastError())
+		e = Platform_Error(win32.GetLastError())
 		done = 0
 	}
 	return int(done), e
@@ -263,7 +262,7 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 	done: win32.DWORD
 	e: Errno
 	if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
-		e = Errno(win32.GetLastError())
+		e = Platform_Error(win32.GetLastError())
 		done = 0
 	}
 	return int(done), e
@@ -400,7 +399,7 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
 	win32.AcquireSRWLockExclusive(&cwd_lock)
 
 	if !win32.SetCurrentDirectoryW(wstr) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 
 	win32.ReleaseSRWLockExclusive(&cwd_lock)
@@ -415,7 +414,7 @@ make_directory :: proc(path: string, mode: u32 = 0) -> (err: Errno) {
 	wpath := win32.utf8_to_wstring(path, context.temp_allocator)
 
 	if !win32.CreateDirectoryW(wpath, nil) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }
@@ -426,7 +425,7 @@ remove_directory :: proc(path: string) -> (err: Errno) {
 	wpath := win32.utf8_to_wstring(path, context.temp_allocator)
 
 	if !win32.RemoveDirectoryW(wpath) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }
@@ -498,7 +497,7 @@ link :: proc(old_name, new_name: string) -> (err: Errno) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	n := win32.utf8_to_wstring(fix_long_path(new_name))
 	o := win32.utf8_to_wstring(fix_long_path(old_name))
-	return Errno(win32.CreateHardLinkW(n, o, nil))
+	return Platform_Error(win32.CreateHardLinkW(n, o, nil))
 }
 
 unlink :: proc(path: string) -> (err: Errno) {
@@ -506,7 +505,7 @@ unlink :: proc(path: string) -> (err: Errno) {
 	wpath := win32.utf8_to_wstring(path, context.temp_allocator)
 
 	if !win32.DeleteFileW(wpath) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }
@@ -519,7 +518,7 @@ rename :: proc(old_path, new_path: string) -> (err: Errno) {
 	to := win32.utf8_to_wstring(new_path, context.temp_allocator)
 
 	if !win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }
@@ -537,7 +536,7 @@ ftruncate :: proc(fd: Handle, length: i64) -> (err: Errno) {
 	}
 	ok := win32.SetEndOfFile(win32.HANDLE(fd))
 	if !ok {
-		return Errno(win32.GetLastError())
+		return Platform_Error(win32.GetLastError())
 	}
 	return ERROR_NONE
 }
@@ -588,7 +587,7 @@ remove :: proc(name: string) -> Errno {
 		}
 	}
 
-	return Errno(err)
+	return Platform_Error(err)
 }
 
 
@@ -597,7 +596,7 @@ pipe :: proc() -> (r, w: Handle, err: Errno) {
 	sa.nLength = size_of(win32.SECURITY_ATTRIBUTES)
 	sa.bInheritHandle = true
 	if !win32.CreatePipe((^win32.HANDLE)(&r), (^win32.HANDLE)(&w), &sa, 0) {
-		err = Errno(win32.GetLastError())
+		err = Platform_Error(win32.GetLastError())
 	}
 	return
 }

+ 13 - 4
core/os/os.odin

@@ -1,5 +1,6 @@
 package os
 
+import "base:intrinsics"
 import "base:runtime"
 import "core:strconv"
 import "core:unicode/utf8"
@@ -14,10 +15,18 @@ SEEK_CUR :: 1
 SEEK_END :: 2
 
 Platform_Error :: _Platform_Error
-Error :: Platform_Error
-Errno :: Error // alias
+#assert(size_of(Platform_Error) <= 4)
+#assert(intrinsics.type_has_nil(Platform_Error))
 
-ERROR_NONE :: Errno(0)
+Errno :: Error // alias for legacy use
+
+Error :: union #shared_nil {
+	Platform_Error,
+	runtime.Allocator_Error,
+}
+#assert(size_of(Error) <= 8)
+
+ERROR_NONE :: Error{}
 
 write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
 	return write(fd, transmute([]byte)str)
@@ -67,7 +76,7 @@ write_encoded_rune :: proc(fd: Handle, r: rune) {
 
 read_at_least :: proc(fd: Handle, buf: []byte, min: int) -> (n: int, err: Errno) {
 	if len(buf) < min {
-		return 0, -1
+		return 0, Platform_Error(~intrinsics.type_core_type(Platform_Error)(0)) // TODO(bill): replace this error
 	}
 	nn := max(int)
 	for nn > 0 && n < min && err == 0 {

+ 5 - 5
core/os/os_darwin.odin

@@ -636,7 +636,7 @@ foreign dl {
 }
 
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__error()^)
+	return Platform_Error(__error()^)
 }
 
 get_last_error_string :: proc() -> string {
@@ -678,11 +678,11 @@ open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno
 }
 
 fchmod :: proc(fd: Handle, mode: u16) -> Errno {
-	return cast(Errno)_unix_fchmod(fd, mode)
+	return cast(Platform_Error)_unix_fchmod(fd, mode)
 }
 
 close :: proc(fd: Handle) -> Errno {
-	return cast(Errno)_unix_close(fd)
+	return cast(Platform_Error)_unix_close(fd)
 }
 
 // If you read or write more than `SSIZE_MAX` bytes, most darwin implementations will return `EINVAL`
@@ -756,7 +756,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 
 	final_offset := i64(_unix_lseek(fd, int(offset), c.int(whence)))
 	if final_offset == -1 {
-		return 0, 1
+		return 0, Platform_Error.EPERM
 	}
 	return final_offset, 0
 }
@@ -1011,7 +1011,7 @@ access :: proc(path: string, mask: int) -> bool {
 }
 
 flush :: proc(fd: Handle) -> Errno {
-	return cast(Errno)_unix_fsync(fd)
+	return cast(Platform_Error)_unix_fsync(fd)
 }
 
 lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {

+ 1 - 1
core/os/os_freebsd.odin

@@ -420,7 +420,7 @@ is_path_separator :: proc(r: rune) -> bool {
 }
 
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__errno_location()^)
+	return Platform_Error(__errno_location()^)
 }
 
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {

+ 1 - 1
core/os/os_haiku.odin

@@ -182,7 +182,7 @@ is_path_separator :: proc(r: rune) -> bool {
 }
 
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__error()^)
+	return Platform_Error(__error()^)
 }
 
 fork :: proc() -> (Pid, Errno) {

+ 3 - 3
core/os/os_linux.odin

@@ -514,14 +514,14 @@ is_path_separator :: proc(r: rune) -> bool {
 @private
 _get_errno :: proc(res: int) -> Errno {
 	if res < 0 && res > -4096 {
-		return Errno(-res)
+		return Platform_Error(-res)
 	}
-	return 0
+	return nil
 }
 
 // get errno from libc
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__errno_location()^)
+	return Platform_Error(__errno_location()^)
 }
 
 personality :: proc(persona: u64) -> (Errno) {

+ 1 - 1
core/os/os_netbsd.odin

@@ -478,7 +478,7 @@ is_path_separator :: proc(r: rune) -> bool {
 }
 
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__errno_location()^)
+	return Platform_Error(__errno_location()^)
 }
 
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {

+ 1 - 1
core/os/os_openbsd.odin

@@ -393,7 +393,7 @@ is_path_separator :: proc(r: rune) -> bool {
 }
 
 get_last_error :: proc "contextless" () -> Error {
-	return Error(__error()^)
+	return Platform_Error(__error()^)
 }
 
 fork :: proc() -> (Pid, Errno) {

+ 9 - 11
core/os/os_wasi.odin

@@ -4,9 +4,7 @@ import "core:sys/wasm/wasi"
 import "base:runtime"
 
 Handle :: distinct i32
-_Platform_Error :: enum i32 {
-	NONE = 0,
-}
+_Platform_Error :: wasi.errno_t
 
 INVALID_HANDLE :: -1
 
@@ -150,22 +148,22 @@ wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
 write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	iovs := wasi.ciovec_t(data)
 	n, err := wasi.fd_write(wasi.fd_t(fd), {iovs})
-	return int(n), Errno(err)
+	return int(n), Platform_Error(err)
 }
 read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
 	iovs := wasi.iovec_t(data)
 	n, err := wasi.fd_read(wasi.fd_t(fd), {iovs})
-	return int(n), Errno(err)
+	return int(n), Platform_Error(err)
 }
 write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 	iovs := wasi.ciovec_t(data)
 	n, err := wasi.fd_pwrite(wasi.fd_t(fd), {iovs}, wasi.filesize_t(offset))
-	return int(n), Errno(err)
+	return int(n), Platform_Error(err)
 }
 read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
 	iovs := wasi.iovec_t(data)
 	n, err := wasi.fd_pread(wasi.fd_t(fd), {iovs}, wasi.filesize_t(offset))
-	return int(n), Errno(err)
+	return int(n), Platform_Error(err)
 }
 open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
 	oflags: wasi.oflags_t
@@ -203,15 +201,15 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errn
 	}
 
 	fd, err := wasi.path_open(dir_fd, {.SYMLINK_FOLLOW}, relative, oflags, rights, {}, fdflags)
-	return Handle(fd), Errno(err)
+	return Handle(fd), Platform_Error(err)
 }
 close :: proc(fd: Handle) -> Errno {
 	err := wasi.fd_close(wasi.fd_t(fd))
-	return Errno(err)
+	return Platform_Error(err)
 }
 seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 	n, err := wasi.fd_seek(wasi.fd_t(fd), wasi.filedelta_t(offset), wasi.whence_t(whence))
-	return i64(n), Errno(err)
+	return i64(n), Platform_Error(err)
 }
 current_thread_id :: proc "contextless" () -> int {
 	return 0
@@ -224,7 +222,7 @@ _processor_core_count :: proc() -> int {
 file_size :: proc(fd: Handle) -> (i64, Errno) {
 	stat, err := wasi.fd_filestat_get(wasi.fd_t(fd))
 	if err != nil {
-		return 0, Errno(err)
+		return 0, Platform_Error(err)
 	}
 	return i64(stat.size), 0
 }

+ 6 - 4
core/os/os_windows.odin

@@ -35,6 +35,7 @@ ERROR_INVALID_HANDLE      :: _Platform_Error(6)
 ERROR_NOT_ENOUGH_MEMORY   :: _Platform_Error(8)
 ERROR_NO_MORE_FILES       :: _Platform_Error(18)
 ERROR_HANDLE_EOF          :: _Platform_Error(38)
+ERROR_EOF                 :: ERROR_HANDLE_EOF
 ERROR_NETNAME_DELETED     :: _Platform_Error(64)
 ERROR_FILE_EXISTS         :: _Platform_Error(80)
 ERROR_INVALID_PARAMETER   :: _Platform_Error(87)
@@ -62,14 +63,15 @@ ERROR_NEGATIVE_OFFSET     :: _Platform_Error(1<<29 + 2)
 // "Argv" arguments converted to Odin strings
 args := _alloc_command_line_arguments()
 
-
-
+get_last_error :: proc "contextless" () -> Error {
+	return Platform_Error(win32.GetLastError())
+}
 
 
 last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
 	file_info: win32.BY_HANDLE_FILE_INFORMATION
 	if !win32.GetFileInformationByHandle(win32.HANDLE(fd), &file_info) {
-		return 0, Errno(win32.GetLastError())
+		return 0, Platform_Error(win32.GetLastError())
 	}
 	lo := File_Time(file_info.ftLastWriteTime.dwLowDateTime)
 	hi := File_Time(file_info.ftLastWriteTime.dwHighDateTime)
@@ -81,7 +83,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
 
 	wide_path := win32.utf8_to_wstring(name)
 	if !win32.GetFileAttributesExW(wide_path, win32.GetFileExInfoStandard, &data) {
-		return 0, Errno(win32.GetLastError())
+		return 0, Platform_Error(win32.GetLastError())
 	}
 
 	l := File_Time(data.ftLastWriteTime.dwLowDateTime)

+ 8 - 8
core/os/stat_windows.odin

@@ -19,7 +19,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa
 	for {
 		n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
 		if n == 0 {
-			return "", Errno(win32.GetLastError())
+			return "", Platform_Error(win32.GetLastError())
 		}
 		if n <= u32(len(buf)) {
 			return win32.utf16_to_utf8(buf[:n], allocator) or_else "", ERROR_NONE
@@ -54,7 +54,7 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al
 		fd: win32.WIN32_FIND_DATAW
 		sh := win32.FindFirstFileW(wname, &fd)
 		if sh == win32.INVALID_HANDLE_VALUE {
-			e = Errno(win32.GetLastError())
+			e = Platform_Error(win32.GetLastError())
 			return
 		}
 		win32.FindClose(sh)
@@ -64,7 +64,7 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al
 
 	h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil)
 	if h == win32.INVALID_HANDLE_VALUE {
-		e = Errno(win32.GetLastError())
+		e = Platform_Error(win32.GetLastError())
 		return
 	}
 	defer win32.CloseHandle(h)
@@ -151,7 +151,7 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> (
 
 	n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0)
 	if n == 0 {
-		return nil, Errno(win32.GetLastError())
+		return nil, Platform_Error(win32.GetLastError())
 	}
 	buf := make([]u16, max(n, win32.DWORD(260))+1, allocator)
 	buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0)
@@ -273,16 +273,16 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string)
 file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) {
 	d: win32.BY_HANDLE_FILE_INFORMATION
 	if !win32.GetFileInformationByHandle(h, &d) {
-		err := Errno(win32.GetLastError())
+		err := Platform_Error(win32.GetLastError())
 		return {}, err
 
 	}
 
 	ti: win32.FILE_ATTRIBUTE_TAG_INFO
 	if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) {
-		err := win32.GetLastError()
-		if err != u32(ERROR_INVALID_PARAMETER) {
-			return {}, Errno(err)
+		err := Platform_Error(win32.GetLastError())
+		if err != ERROR_INVALID_PARAMETER {
+			return {}, err
 		}
 		// Indicate this is a symlink on FAT file systems
 		ti.ReparseTag = 0

+ 2 - 2
core/path/filepath/path_windows.odin

@@ -63,14 +63,14 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) {
 	p := win32.utf8_to_utf16(name, ta)
 	n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
 	if n == 0 {
-		return "", os.Errno(win32.GetLastError())
+		return "", os.Platform_Error(win32.GetLastError())
 	}
 
 	buf := make([]u16, n, ta)
 	n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil)
 	if n == 0 {
 		delete(buf)
-		return "", os.Errno(win32.GetLastError())
+		return "", os.Platform_Error(win32.GetLastError())
 	}
 
 	return win32.utf16_to_utf8(buf[:n], ta) or_else "", os.ERROR_NONE

+ 1 - 1
core/prof/spall/spall_windows.odin

@@ -25,7 +25,7 @@ _write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Errno) #n
 
 		e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil)
 		if single_write_length <= 0 || !e {
-			err := os.Errno(win32.GetLastError())
+			err := os.Platform_Error(win32.GetLastError())
 			return int(total_write), err
 		}
 		total_write += i64(single_write_length)

+ 1 - 0
core/sys/wasm/wasi/wasi_api.odin

@@ -16,6 +16,7 @@ CLOCK_REALTIME           :: clockid_t(2)
 CLOCK_THREAD_CPUTIME_ID  :: clockid_t(3)
 
 errno_t :: enum u16 {
+	NONE = 0,
 	// No error occurred. System call completed successfully.
 	SUCCESS = 0,
 	// Argument list too long.

+ 16 - 19
src/check_expr.cpp

@@ -4366,25 +4366,6 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
 	}
 
 	switch (t->kind) {
-	// IMPORTANT NOTE HACK(bill): This is just to allow for comparisons against `0` with the `os.Error` type
-	// as a kind of transition period
-	case Type_Enum:
-		if (operand->mode == Addressing_Constant &&
-		    target_type->kind == Type_Named &&
-		    target_type->Named.name == "Error") {
-			Entity *e = target_type->Named.type_name;
-			if (e->pkg && e->pkg->name == "os") {
-				if (is_exact_value_zero(operand->value)) {
-					check_is_expressible(c, operand, t);
-					if (operand->mode == Addressing_Invalid) {
-						return;
-					}
-					update_untyped_expr_value(c, operand->expr, operand->value);
-				}
-			}
-		}
-		break;
-
 	case Type_Basic:
 		if (operand->mode == Addressing_Constant) {
 			check_is_expressible(c, operand, t);
@@ -4478,6 +4459,22 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
 		
 
 	case Type_Union:
+		// IMPORTANT NOTE HACK(bill): This is just to allow for comparisons against `0` with the `os.Error` type
+		// as a kind of transition period
+		if (operand->mode == Addressing_Constant &&
+		    target_type->kind == Type_Named &&
+		    target_type->Named.name == "Error") {
+			Entity *e = target_type->Named.type_name;
+			if (e->pkg && e->pkg->name == "os") {
+				if (is_exact_value_zero(operand->value) &&
+				    (operand->value.kind == ExactValue_Integer ||
+				     operand->value.kind == ExactValue_Float)) {
+					update_untyped_expr_value(c, operand->expr, empty_exact_value);
+					break;
+				}
+			}
+		}
+		// "fallthrough"
 		if (!is_operand_nil(*operand) && !is_operand_uninit(*operand)) {
 			TEMPORARY_ALLOCATOR_GUARD();