Document `Error`

I didn't yet document *everything* there is to say (in particular, how
exactly custom Rust errors can be passed through Lua), but I've some
changes to this type in mind that I'll do next.
This commit is contained in:
Jonas Schievink 2017-07-28 12:50:30 +02:00
parent d415455ccb
commit ad6cf21921
2 changed files with 74 additions and 18 deletions

View File

@ -3,6 +3,7 @@ use std::sync::Arc;
use std::error::Error as StdError; use std::error::Error as StdError;
use std::result::Result as StdResult; use std::result::Result as StdResult;
/// Error type returned by rlua methods.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Error { pub enum Error {
/// Lua syntax error, aka `LUA_ERRSYNTAX` that is NOT an incomplete statement. /// Lua syntax error, aka `LUA_ERRSYNTAX` that is NOT an incomplete statement.
@ -10,29 +11,73 @@ pub enum Error {
/// Lua syntax error that IS an incomplete statement. Useful for implementing a REPL. /// Lua syntax error that IS an incomplete statement. Useful for implementing a REPL.
IncompleteStatement(String), IncompleteStatement(String),
/// Lua runtime error, aka `LUA_ERRRUN`. /// Lua runtime error, aka `LUA_ERRRUN`.
///
/// The Lua VM returns this error when a builtin operation is performed on incompatible typed.
/// Among other things, this includes invoking operators on wrong types (such as calling or
/// indexing a `nil` value).
RuntimeError(String), RuntimeError(String),
/// Lua error from inside an error handler, aka `LUA_ERRERR`. /// Lua error from inside an error handler, aka `LUA_ERRERR`.
///
/// To prevent an infinite recursion when invoking an error handler, this error will be returned
/// instead of invoking the error handler.
ErrorError(String), ErrorError(String),
/// A generic Rust -> Lua conversion error. /// A Rust value could not be converted to a Lua value.
ToLuaConversionError(String), ToLuaConversionError(String),
/// A generic Lua -> Rust conversion error. /// A Lua value could not be converted to the expected Rust type.
FromLuaConversionError(String), FromLuaConversionError(String),
/// A `Thread` was resumed and the coroutine was no longer active. /// [`Thread::resume`] was called on an inactive coroutine.
///
/// A coroutine is inactive if its main function has returned or if an error has occured inside
/// the coroutine.
///
/// [`Thread::status`] can be used to check if the coroutine can be resumed without causing this
/// error.
///
/// [`Thread::resume`]: struct.Thread.html#method.resume
/// [`Thread::status`]: struct.Thread.html#method.status
CoroutineInactive, CoroutineInactive,
/// An `AnyUserData` is not the expected type in a borrow. /// An [`AnyUserData`] is not the expected type in a borrow.
///
/// This error can only happen when manually using [`AnyUserData`], or when implementing
/// metamethods for binary operators. Refer to the documentation of [`UserDataMethods`] for
/// details.
///
/// [`AnyUserData`]: struct.AnyUserData.html
/// [`UserDataMethods`]: struct.UserDataMethods.html
UserDataTypeMismatch, UserDataTypeMismatch,
/// An `AnyUserData` immutable borrow failed because it is already borrowed mutably. /// An [`AnyUserData`] immutable borrow failed because it is already borrowed mutably.
///
/// This error can occur when a method on a [`UserData`] type calls back into Lua, which then
/// tries to call a method on the same [`UserData`] type. Consider restructuring your API to
/// prevent these errors.
///
/// [`AnyUserData`]: struct.AnyUserData.html
/// [`UserData`]: trait.UserData.html
UserDataBorrowError, UserDataBorrowError,
/// An `AnyUserData` mutable borrow failed because it is already borrowed. /// An [`AnyUserData`] mutable borrow failed because it is already borrowed.
///
/// This error can occur when a method on a [`UserData`] type calls back into Lua, which then
/// tries to call a method on the same [`UserData`] type. Consider restructuring your API to
/// prevent these errors.
///
/// [`AnyUserData`]: struct.AnyUserData.html
/// [`UserData`]: trait.UserData.html
UserDataBorrowMutError, UserDataBorrowMutError,
/// Lua error that originated as a Error in a callback. The first field is the lua error as /// A Rust callback returned `Err`, raising the contained `Error` as a Lua error.
/// a string, the second field is the Arc holding the original Error. ///
/// The first field is the Lua traceback, the second field holds the original error.
CallbackError(String, Arc<Error>), CallbackError(String, Arc<Error>),
/// Any custom external error type, mostly useful for returning external error types from /// A custom error.
/// callbacks. ///
/// This can be used for returning user-defined errors from callbacks.
///
/// Returning `Err(ExternalError(...))` from a Rust callback will raise the error as a Lua
/// error. The Rust code that originally invoked the Lua code then receives a `CallbackError`,
/// from which the original error (and a stack traceback) can be recovered.
ExternalError(Arc<StdError + Send + Sync>), ExternalError(Arc<StdError + Send + Sync>),
} }
/// A specialized `Result` type used by rlua's API.
pub type Result<T> = StdResult<T, Error>; pub type Result<T> = StdResult<T, Error>;
impl fmt::Display for Error { impl fmt::Display for Error {

View File

@ -766,16 +766,18 @@ impl<'lua> Function<'lua> {
} }
/// Status of a Lua thread (or coroutine). /// Status of a Lua thread (or coroutine).
///
/// A `Thread` is `Active` before the coroutine function finishes, Dead after it finishes, and in
/// Error state if error has been called inside the coroutine.
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ThreadStatus { pub enum ThreadStatus {
/// The thread has finished executing. /// The thread has finished executing.
Dead, Dead,
/// The thread is currently running or suspended because it has called `coroutine.yield`. /// The thread was just created, is currently running or is suspended because it has called
/// `coroutine.yield`.
///
/// If a thread is in this state, it can be resumed by calling [`Thread::resume`].
///
/// [`Thread::resume`]: struct.Thread.html#method.resume
Active, Active,
/// The thread has thrown an error during execution. /// The thread has raised a Lua error during execution.
Error, Error,
} }
@ -1161,13 +1163,22 @@ pub trait UserData: 'static + Sized {
fn add_methods(_methods: &mut UserDataMethods<Self>) {} fn add_methods(_methods: &mut UserDataMethods<Self>) {}
} }
/// Handle to an internal Lua userdata for any type that implements `UserData`. /// Handle to an internal Lua userdata for any type that implements [`UserData`].
/// ///
/// Similar to `std::any::Any`, this provides an interface for dynamic type checking via the `is` /// Similar to `std::any::Any`, this provides an interface for dynamic type checking via the [`is`]
/// and `borrow` methods. /// and [`borrow`] methods.
/// ///
/// Internally, instances are stored in a `RefCell`, to best match the mutable semantics of the Lua /// Internally, instances are stored in a `RefCell`, to best match the mutable semantics of the Lua
/// language. /// language.
///
/// # Note
///
/// This API should only be used when necessary. Implementing [`UserData`] already allows defining
/// methods which check the type and acquire a borrow behind the scenes.
///
/// [`UserData`]: trait.UserData.html
/// [`is`]: #method.is
/// [`borrow`]: #method.borrow
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct AnyUserData<'lua>(LuaRef<'lua>); pub struct AnyUserData<'lua>(LuaRef<'lua>);