Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
990aba5
Add `provide` method
TimDiekmann Jun 2, 2022
1559d74
Fix intra-doc links
TimDiekmann Jun 3, 2022
ad30fe4
Fix miri
TimDiekmann Jun 3, 2022
4fb53b9
Rename `FutureWithProvided` to `FutureWithProvidedRef`
TimDiekmann Jun 3, 2022
ff63749
Combine `attach_message` and `provide`
TimDiekmann Jun 3, 2022
a9a4b15
Apply changes to hEngine
TimDiekmann Jun 3, 2022
55a8db8
Test the new feature
TimDiekmann Jun 3, 2022
610c0cf
Improve documentation on `FrameObject`
TimDiekmann Jun 3, 2022
4d18139
Fix downcasting
TimDiekmann Jun 3, 2022
b72ba37
Remove `SingleProvider`
TimDiekmann Jun 3, 2022
74b6b3b
Merge branch 'main' into td/provide-directly
TimDiekmann Jun 3, 2022
8bdd064
Rework attaching and context
TimDiekmann Jun 3, 2022
18d2b9c
Update packages/engine/lib/error/src/frame.rs
TimDiekmann Jun 3, 2022
e9473b5
Update packages/engine/lib/error/src/frame.rs
TimDiekmann Jun 3, 2022
6fc1721
Update packages/engine/lib/error/src/report.rs
TimDiekmann Jun 3, 2022
31a543b
Update packages/engine/lib/error/src/result.rs
TimDiekmann Jun 3, 2022
725a303
Simplify `Frame` implementation by removing `Unerased`
TimDiekmann Jun 3, 2022
3277be6
Clean up code
TimDiekmann Jun 3, 2022
35ecbb1
Clarify documentation on `Frame`
TimDiekmann Jun 6, 2022
028ccfe
Clarify documentation on trace capturing
TimDiekmann Jun 6, 2022
b2bc61e
Mention the feature flags section on [`Report`]
TimDiekmann Jun 6, 2022
7900847
Fix tests
TimDiekmann Jun 6, 2022
f0280b9
Clarified `Frame` docs more
TimDiekmann Jun 6, 2022
e8dbd74
Clarified `Frame` docs more
TimDiekmann Jun 6, 2022
ea43ccc
Fix clippy on no-default-features
TimDiekmann Jun 6, 2022
069bb52
Clarify retrieving of the backtrace/spantrace
TimDiekmann Jun 6, 2022
7e5d08c
Add note on backtrace and spantrace to `Report::new`
TimDiekmann Jun 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/engine/bin/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async fn main() -> Result<(), CliError> {
&format!("cli-{now}-texray"),
)
.report()
.attach_message("Failed to initialize the logger")
.attach("Failed to initialize the logger")
.change_context(CliError)?;

let nng_listen_url = format!("ipc://hash-orchestrator-{now}");
Expand All @@ -115,14 +115,14 @@ async fn main() -> Result<(), CliError> {
.project
.canonicalize()
.report()
.attach_message_lazy(|| format!("Could not canonicalize project path: {:?}", args.project))
.attach_lazy(|| format!("Could not canonicalize project path: {:?}", args.project))
.change_context(CliError)?;
let manifest = Manifest::from_local(&absolute_project_path)
.attach_message_lazy(|| format!("Could not read local project {absolute_project_path:?}"))
.attach_lazy(|| format!("Could not read local project {absolute_project_path:?}"))
.change_context(CliError)?;
let experiment_run = manifest
.read(args.r#type.into())
.attach_message("Could not read manifest")
.attach("Could not read manifest")
.change_context(CliError)?;

let experiment = Experiment::new(args.experiment_config);
Expand Down
8 changes: 4 additions & 4 deletions packages/engine/bin/hash_engine/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ async fn main() -> Result<(), EngineError> {
&format!("experiment-{}-texray", args.experiment_id),
)
.report()
.attach_message("Failed to initialize the logger")
.attach("Failed to initialize the logger")
.change_context(EngineError)?;

let mut env = env::<ExperimentRun>(&args)
.await
.report()
.attach_message("Could not create environment for experiment")
.attach("Could not create environment for experiment")
.change_context(EngineError)?;
// Fetch all dependencies of the experiment run such as datasets
env.experiment
.fetch_deps()
.await
.report()
.attach_message("Could not fetch dependencies for experiment")
.attach("Could not fetch dependencies for experiment")
.change_context(EngineError)?;
// Generate the configuration for packages from the environment
let config = experiment_config(&args, &env)
Expand All @@ -62,7 +62,7 @@ async fn main() -> Result<(), EngineError> {
let experiment_result = run_experiment(config, env)
.await
.report()
.attach_message("Could not run experiment")
.attach("Could not run experiment")
.change_context(EngineError);

cleanup_experiment(args.experiment_id);
Expand Down
5 changes: 2 additions & 3 deletions packages/engine/lib/error/examples/contextual_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ fn parse_config(config: &HashMap<&str, u64>) -> Result<u64, LookupError> {
let key = "abcd-efgh";

// `ResultExt` provides different methods for adding additional information to the `Report`
let value =
lookup_key(config, key).attach_message_lazy(|| format!("Could not lookup key {key:?}"))?;
let value = lookup_key(config, key).attach_lazy(|| format!("Could not lookup key {key:?}"))?;

Ok(value)
}

fn main() -> Result<(), LookupError> {
let config = HashMap::default();
let _config_value = parse_config(&config).attach_message("Unable to parse config")?;
let _config_value = parse_config(&config).attach("Unable to parse config")?;

Ok(())
}
4 changes: 2 additions & 2 deletions packages/engine/lib/error/examples/json_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ fn main() -> Result<(), MapError> {
let mut config = HashMap::default();

// Create an entry with "foo" as key
create_new_entry(&mut config, "foo", 1).attach_message("Could not create new entry")?;
create_new_entry(&mut config, "foo", 1).attach("Could not create new entry")?;

// Purposefully cause an error by attempting to create another entry with "foo" as key
let creation_result =
create_new_entry(&mut config, "foo", 2).attach_message("Could not create new entry");
create_new_entry(&mut config, "foo", 2).attach("Could not create new entry");

assert_eq!(
format!("{:?}", creation_result.unwrap_err()),
Expand Down
112 changes: 112 additions & 0 deletions packages/engine/lib/error/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use core::fmt;

#[cfg(nightly)]
use crate::provider::Demand;
#[cfg(all(nightly, any(feature = "std", feature = "spantrace")))]
use crate::provider::Provider;
use crate::Report;

/// Defines the current context of a [`Report`].
///
/// When in a `std` environment, every [`Error`] is a valid `Context`. This trait is not limited to
/// [`Error`]s and can also be manually implemented for custom objects.
///
/// [`Error`]: std::error::Error
///
/// ## Example
///
/// Used for creating a [`Report`] or for switching the [`Report`]'s context:
///
/// ```rust
/// # #![cfg_attr(any(not(feature = "std"), miri), allow(unused_imports))]
/// use std::{fmt, fs, io};
///
/// use error::{Context, IntoReport, Result, ResultExt};
///
/// # type Config = ();
/// #[derive(Debug)]
/// pub enum ConfigError {
/// ParseError,
/// }
///
/// impl fmt::Display for ConfigError {
/// # #[allow(unused_variables)]
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
/// # const _: &str = stringify! {
/// ...
/// # }; Ok(())
/// }
/// }
///
/// // In this scenario, `Error` is not implemented for `ConfigError` for some reason, so implement
/// // `Context` manually.
/// impl Context for ConfigError {}
///
/// # #[cfg(any(not(feature = "std"), miri))]
/// # pub fn read_file(_: &str) -> Result<String, ConfigError> { error::bail!(ConfigError::ParseError) }
/// # #[cfg(all(feature = "std", not(miri)))]
/// pub fn read_file(path: &str) -> Result<String, io::Error> {
/// // Creates a `Report` from `io::Error`, the current context is `io::Error`
/// fs::read_to_string(path).report()
/// }
///
/// pub fn parse_config(path: &str) -> Result<Config, ConfigError> {
/// // The return type of `parse_config` requires another context. By calling `change_context`
/// // the context may be changed.
/// read_file(path).change_context(ConfigError::ParseError)?;
///
/// # const _: &str = stringify! {
/// ...
/// # }; Ok(())
/// }
/// # let err = parse_config("invalid-path").unwrap_err();
/// # #[cfg(all(feature = "std", not(miri)))]
/// # assert!(err.contains::<io::Error>());
/// # assert!(err.contains::<ConfigError>());
/// # assert_eq!(err.frames().count(), 2);
/// ```
pub trait Context: fmt::Display + fmt::Debug + Send + Sync + 'static {
/// Provide values which can then be requested by [`Report`].
#[cfg(nightly)]
#[allow(unused_variables)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {}
}

impl<C> From<C> for Report<C>
where
C: Context,
{
#[track_caller]
#[inline]
fn from(context: C) -> Self {
Self::new(context)
}
}

/// Turns a [`Context`] into a temporary [`Provider`].
///
/// To enable the usage of the [`Provider`] trait without implementing [`Provider`] for [`Context`]
/// this function wraps a reference to a [`Context`] inside of a [`Provider`]
// We can't implement `Provider` on Context as `Error` will implement `Provider` and `Context` will
// be implemented on `Error`. For `request`ing a type from `Context`, we need a `Provider`
// implementation however.
#[cfg(all(nightly, any(feature = "std", feature = "spantrace")))]
pub fn temporary_provider(context: &impl Context) -> impl Provider + '_ {
struct ProviderImpl<'a, C>(&'a C);
impl<C: Context> Provider for ProviderImpl<'_, C> {
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
self.0.provide(demand);
}
}
ProviderImpl(context)
}

#[cfg(feature = "std")]
impl<C: std::error::Error + Send + Sync + 'static> Context for C {
#[cfg(nightly)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
if let Some(backtrace) = self.backtrace() {
demand.provide_ref(backtrace);
}
}
}
15 changes: 0 additions & 15 deletions packages/engine/lib/error/src/error.rs

This file was deleted.

Loading