Rust-like Error Handling! [RustResult]


What is this?

RustResult is a Lua implementation inspired by Rust’s Result type, designed to represent the outcome of operations that can either succeed or fail. It provides a way to handle both success and error cases explicitly, avoiding the need for exceptions and enabling more predictable, safe, and readable error handling.

There are two possible outcomes:

  1. Ok(T): Represents a successful result containing a value of type T. This is the standard outcome when an operation completes successfully.

  2. Err(E): Represents a failure containing an error value of type E. This is used when an operation encounters an error.

Why Use RustResult?

In Lua, error handling is often done via pcall or xpcall, or sometimes just through implicit error values. RustResult provides a more structured approach that forces explicit handling of success (Ok) and error (Err) states. This leads to cleaner, more maintainable code that clearly communicates the outcome of operations.

The core benefit of RustResult is that it avoids unhandled exceptions and ensures that errors are always checked and dealt with. Rather than relying on vague error messages or silent failures, the result of an operation is encapsulated in a RustResult object that must be inspected and handled appropriately.

Example Usage

--!strict

local Modules = game.ReplicatedStorage.Modules
local RustResult = require(Modules.RustResult)
-- A function that divides two numbers
local function divide(a : number, b : number) : RustResult.ClassType<number, string>
	if b == 0 then
		return RustResult.Err("Cannot divide by zero")
	else
		return RustResult.Ok(a / b)
	end
end

-- Handling the result of division
local result = divide(10, 2)

if result:is_ok() then
	print("Success:", result:unwrap())  -- Output: Success: 5
else
	print("Error:", result:unwrap_err())
end

-- Handling division by zero
local errorResult = divide(10, 0)

if errorResult:is_err() then
	print("Error:", errorResult:unwrap_err())  -- Output: Error: Cannot divide by zero
end

When to Use RustResult

RustResult is useful when dealing with operations that can either succeed or fail (e.g., file operations, network requests, division by zero, etc.). It is especially beneficial in large projects or systems where error handling needs to be predictable, robust, and easy to follow.

By using RustResult, you make it clear that errors will be handled, improving both the reliability and maintainability of your code.

Changelog

  • Made the module !strict mode friendly
  • Updated the in-script documentation
  • Fixed or_else, and_then returning back the inner value instead of the result
  • Switched to a more dynamic compact approach
  • Statically defined all the method signatures for consistency.

If this module is received well, I might extend it with more functionality from nightly Rust.

Download

RustResult.lua (5.4 KB)

5 Likes

Absolutely the best module ever btw!
Thanks for this contribution to the community :handshake:

1 Like