Extending enum defined in one crate in another crate

I have an enum MyError defined in crate1

crate1
enum MyError
{
  CommonErr1,
  CommonErr2,
}

and I want to extend this enum in another crate crate2.

Crate2
enum MyError
{
  crateBerr1,
  crateBerr2,
}
  • Why I want to extend the enum?
    1.With this crate2 will have both "common Errors" & its own errors. i.e
crate2
enum MyError
{
  CommonErr1,
  CommonErr2,
  crateBerr1,
  crateBerr2,
}

  1. With this I will have a common Enum type MyError which can be accessed in both the crates. this is required because I have a function in crate2 ( fun2() )which returns Result<_, MyError> and this function is used as a closure argument to a function present in crate1 (fun1()). and this function ( (fun1()) handles some of the common error handling like below. having common Error type will help me to handle common errors in crate1::fun1() thrown by crate2::fun2(). note that I cant have crate2 as a dependency in crate1 due to some restriction.
crate 1
fn fun1(arg:F) where F:Fn(arg1,arg2)->Result<_,MyError) {
    ...
    ...
  match arg {
  Err(MyError::CommonErr1) => do something,
  Err(MyError::CommonErr2) => do something,
  ...
  ...
  }
}

crate 2
fn fun2(arg1,arg2)->Result<Sometype,MyError)
{
  ...
  ...
}

fn main() {
  ...
  ...
  crate1::fun1(fun2);
  ...
  ...
}

my idea is if I can extend the enum defined in one crate in another crate then above problem can be easily solved.my question is

  1. is it possible to extend the enum like this
  2. if not what's the best way to solve the above problem considering i don't have the access to crate2 from crate1

Note: i just used the chatgpt to check is it possible to extend the enum from one crate in another crate. it answered me saying it is possible and gave me a piece of code as well.

Question: extending enum defined in one crate in another rust
Answer by ChatGpt :
To extend an enum defined in one Rust crate in another crate, you can use the use statement to bring the enum into scope and then add new variants to it using the pub keyword.
Here's an example:

In the crate where the enum is defined (my_enum_crate):

// define the enum
pub enum MyEnum {
    Variant1,
    Variant2,
}

In the crate where you want to extend the enum (my_extension_crate), you can use the use statement to bring the enum into scope:

use my_enum_crate::MyEnum;

Then you can add new variants to the enum using the pub keyword:

// extend the enum
pub enum MyEnum {
    Variant3,
    Variant4,
}

Now the MyEnum type in my_extension_crate will have four variants: Variant1, Variant2, Variant3, and Variant4.

Note that this approach only works if both crates are part of the same Rust project and are compiled together. If the two crates are separate projects, you will need to make the enum part of a shared library or crate that both projects depend on, and then use that shared crate in both projects.

It is not possible to extend enums, if by that you mean adding variants outside its original definition. I don't know what "like this" refers to. Your example code is severely lacking context, and the names are non-descriptive, so it's hard to tell exactly what you are after.

I'm curious what kind of code it produced, and whether it compiles/runs/is correct/does what you want/is doing what it says it is doing.

2 Likes

The normal pattern for error enums, which has explicit support in thiserror via the #[from] marking and #[error(transparent)], is to have a per-crate error enum, one variant of which is the common errors.

Something like the following code:

crate common {
    pub enum Errors {
        Error1,
        Error2
    }
{
crate a {
    pub enum MyError {
        Error1,
        CommonError(common::Errors),
    }
}
crate b {
    pub enum MyError {
        Error1,
        Error2,
        CrateAError(a::MyErrror),
        CommonError(common::Errors),
    }
}

If you're using thiserror, you'd mark it up similar to the following, so that "common" errors appear as-if they were additional variants on your local error:

crate common {
    #[derive(Error, Debug)]
    pub enum Errors {
        #[error("This is the first common error")]
        Error1,
        #[error("This is the second common error")]
        Error2
    }
{
crate a {
    pub enum MyError {
        #[error("This is crate A's first error")]
        Error1,
        #[error(transparent)]
        CommonError(#[from] common::Errors),
    }
}
crate b {
    pub enum MyError {
        #[error("This is crate B's first error")]
        Error1,
        #[error("This is crate B's second error")]
        Error2,
        #[error("This is crate B forwarding a crate A error")]
        CrateAError(#[from] a::MyErrror),
        #[error(transparent)]
        CommonError(#[from] common::Errors),
    }
}
2 Likes

I have updated the question. if you dont mind could you please have a look

Off-topic: This is a great example of chatgpt spewing convincing nonsense.

On-topic: What's the expected behavior of crate1 when it encounters crateBerr1? Just panic or throw a new error? Either way, I think you can change your callback closure's signature from F: Fn(arg1,arg2)->Result<_,MyError> to F: Fn(arg1,arg2)->Result<_, E>, E: TryInto<MyError>. Then call try_into when error.

4 Likes

behavior of crate1 when it encounters common error would be printing the warning message or returning from the function depending upon the error type.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.