What are all the different error types in Rust? - error-handling

I'm learning Rust and can't find a list of all error types. When a function is returning a Result, does the standard library have a group of predefined errors available for use?
I know custom error types can be made in Rust, is that the solution? Make all custom errors types?

It's not well defined what "an error type" would mean, so no, there is no global list of errors.
If you mean "is there a list of all the types that are used as Result::Err, the answer is still no. There are methods like slice::binary_search which return Result<usize, usize>. Is usize to be considered an error type? What if a Result::Err is constructed entirely inside of a function and never leaves it; is that type considered an error type? What about a generic type that contains a Result<i32, E>; should any concrete E be called an error type?
If you mean "is there a list of all the types that implement std::error::Error, then the answer is "kind of". See How can I get a list of structs that implement a particular trait in Rust? for details.
does the standard library have a group of predefined errors
Yes.
available for use
Sometimes. io::Error allows you to construct your own error value, but num::ParseIntError does not.
is that the solution? Make all custom errors types?
Generally, yes.
See also:
How do you define custom `Error` types in Rust?

Result types are often aliased in the standard library. If you see a function in the standard library documentation, you can click on Result, which should lead you to the aliased type (e.g. std::io::Result)
You can then see which kind of Error is used in the Result.
The documentation also has a list of all enums and structs in the standard library that implement the Error trait.

a list, although not complete, can be found at
https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/std/error/trait.Error.html

Related

Using void structs in Raku via NativeCall

I'm trying to link libzip to Raku, and it uses a void struct or a struct with no body, like this:
struct zip;
typedef struct zip zip_t;
I declare it in my Raku program in the same way:
class zip_t is repr('CStruct'){};
This fails with:
Class zip_t has no attributes, which is illegal with the CStruct representation.
Only reference I have found to that error is in this non-addressed issue in MyHTML. That might make it a regression, but I'm really not sure. Any idea?
A google for "no attributes, which is illegal with the CStruct representation" yields three matches. The third leads to the following recent bug/change for module LibZip:
- class zip is repr('CStruct') is export { }
+ class zip is repr('CPointer') is export { }
Before I publish this I see Curt Tilmes has commented to similar effect.
I know little about C. But I enjoy researching things. This answer is a guess and some notes based on googling.
The error message you've quoted is about NativeCall, which in turn means it's about the Rakudo compiler, not the Raku language. (I presume you know this, and for many folk and situations the distinction isn't typically important, but I think it worth noting in this case.)
The top SO match for a google for "empty struct" is Empty structs in C. The question asks about the semantics of empty structs and using them with a foreign language. The question and its answers seem useful; the next few points are based on excerpts from them.
"Structures with no named members [have undefined behavior]". I'd say this explains why you're getting the NativeCall error message ("no attributes, which is illegal with the CStruct representation".). NativeCall is about having a reliable portable interface to C so it presumably must summarily reject undefined aspects. (Perhaps the error message could hint at what to do instead? Probably not. It's probably better that someone must search for matches to the message, just as you have done. And then presumably they would see this SO.)
I presume you're just trying to bind with libzip's empty struct as part of passing data back and forth without reading or writing it. I suspect that that is the crux of the problem here; how do you bind given that NativeCall (quite reasonably) refuses to do it in the usual manner?
"From the point of view of writing [a foreign language] binding to a C library ... You're never going to do anything with objects of the [empty struct] type except pass them to imported C functions." I presume this is true for your situation and that anything else would be undefined behavior per the C spec and thus at least tied to a specific C compiler for both the C library and the C compiler used to compile Rakudo and quite possibly undefined even then. I presume Curt has asked about your usage in case the binding is doing or requiring something crazy, but I very much doubt that it is.

Is it a good practice to use Nothing in generics?

Like in this example:
sealed class Option<T>
object None : Option<Nothing>() // <-- like this
class Some<T> : Option<T>()
Or, if it's not a good practice, what should I use here instead?
Are there any official response/article on that? Or is there any argumentation that this is a good practice?
I know that Nothing was designed to be used as a type for return value for functions that never returns any value, so I'm not sure if using it as a generic parameter is a valid use.
I know there is an article that says that you can do that, but I'm not sure if I can trust it.
And the author of koptional uses it too, but I don't know if I can trust that either.
Also, it looks like in Scala Option is implemented similar to that, None have type Option[Nothing] and Scala's Nothing is similar to Kotlin's Nothing.
I agree with #zsmb13's comment. Using Nothing in a generic type hierarchy is perfectly valid and even gives benefits over other options:
First, Nothing is embedded in the Kotlin type system as a subtype of any other type, so it plays well with generics variance. For example, Option<Nothing> can be passed where Option<out Foo> is expected.
Second, the compiler will perform control flow checks and detect unreachable code after a Nothing-returning member call when the type is statically known.
See also: A Whirlwind Tour of the Kotlin Type Hierarchy

Precondition functions in Kotlin - good practices

Being a newbie Kotlin coder, I wonder, if there are some good practices or even language constructs for declaring pre-conditions in functions.
In Java I have been using Guava's Preconditions checking utilities:
https://github.com/google/guava/wiki/PreconditionsExplained
After some further investigation I came across the require function:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/require.html
Is this what is generally used for checking preconditions on functions?
Of course. You can find all of the preconditions in Preconditions.kt. In addition to the require function, there are requireNotNull, check & checkNotNull functions.
Since the documentation describes it poorly in Kotlin, but you can see the Objects#requireNonNull documentation in jdk as further.
Checks that the specified object reference is not null. This method is designed primarily for doing parameter validation in methods and constructors.
I use assert() and require() from the stdlib.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/assert.html
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/require.html
Actually, 'require' appears to not be inherited - that is, if a subclass overrides a function that has a 'require' statement, the 'require' in the parent function is not enforced. A true precondition would also apply in the case of a redefinition of the inherited function, so (IMO) 'require' does not truly provide full precondition-checking functionality.
(I say "appears" because, being new to kotlin, I've learned this by a simple experiment using inheritance - and it's possible I'm wrong - e.g., there's a bug in the compiler causing incorrect behavior, or I've done something wrong in compiling/setup. I don't think this possibility is likely, though.)
Yes, it seems that toolforger is right about 'require'. I just searched for "require" as a keyword at https://kotlinlang.org and couldn't find it, nor as a documented function. It appears to be undocumented (unless the doc for require is hidden somewhere I couldn't find); and, of course, that means we cannot count on it to implement the standard DBC "require" behavior, and so the logical assumption is that it is simply the equivalent to "assert" in C.

How can deserialization of polymorphic trait objects be added in Rust if at all?

I'm trying to solve the problem of serializing and deserializing Box<SomeTrait>. I know that in the case of a closed type hierarchy, the recommended way is to use an enum and there are no issues with their serialization, but in my case using enums is an inappropriate solution.
At first I tried to use Serde as it is the de-facto Rust serialization mechanism. Serde is capable of serializing Box<X> but not in the case when X is a trait. The Serialize trait can’t be implemented for trait objects because it has generic methods. This particular issue can be solved by using erased-serde so serialization of Box<SomeTrait> can work.
The main problem is deserialization. To deserialize polymorphic type you need to have some type marker in serialized data. This marker should be deserialized first and after that used to dynamically get the function that will return Box<SomeTrait>.
std::any::TypeId could be used as a marker type, but the main problem is how to dynamically get the deserialization function. I do not consider the option of registering a function for each polymorphic type that should be called manually during application initialization.
I know two possible ways to do it:
Languages that have runtime reflection like C# can use it to get
deserialization method.
In C++, the cereal library uses magic of static objects to register deserializer in a static map at the library initialization time.
But neither of these options is available in Rust. How can deserialization of polymorphic objects be added in Rust if at all?
This has been implemented by dtolnay.
The concept is quite clever ans is explained in the README:
How does it work?
We use the inventory crate to produce a registry of impls of your trait, which is built on the ctor crate to hook up initialization functions that insert into the registry. The first Box<dyn Trait> deserialization will perform the work of iterating the registry and building a map of tags to deserialization functions. Subsequent deserializations find the right deserialization function in that map. The erased-serde crate is also involved, to do this all in a way that does not break object safety.
To summarize, every implementation of the trait declared as [de]serializable is registered at compile-time, and this is resolved at runtime in case of [de]serialization of a trait object.
All your libraries could provide a registration routine, guarded by std::sync::Once, that register some identifier into a common static mut, but obviously your program must call them all.
I've no idea if TypeId yields consistent values across recompiles with different dependencies.
A library to do this should be possible. To create such a library, we would create a bidirectional mapping from TypeId to type name before using the library, and then use that for serialization/deserialization with a type marker. It would be possible to have a function for registering types that are not owned by your package, and to provide a macro annotation that automatically does this for types declared in your package.
If there's a way to access a type ID in a macro, that would be a good way to instrument the mapping between TypeId and type name at compile time rather than runtime.

Dynamic argument pasing in corba

I'm new in building corba application. Presently I'm developping a corba application in java. The problem I have is that I should write a method that receive the name of the class, the method and the arguments to pass to the corba server as a string.
Before invoking the remote method, I have to parse the string and obtain all the necessary information (class, method, arguments)
There is no problem here. But now concerning the arguments i do not now in advance the type of the arguments, so I should be able to convert an argument by getting its type and insert it into a Any bject to be sent, is it possible?
If Know in advance the type such as seq.insert_string("bum") it works but I want to do it dynamically.
Use the DynAny interfaces, if your ORB supports them. They can do exactly what you want. From CORBA Explained Simply:
If an application wants to manipulate data embedded inside an any
without being compiled with the relevant stub code then the
application must convert the any into a DynAny. There are sub-types
of DynAny for each IDL construct. For example, there are types called
DynStruct, DynUnion, DynSequence and so on.
The operations on the DynAny interfaces allow a programmer to
recursively drill down into a compound data-structure that is
contained within the DynAny and, in so doing, decompose the compound
type into its individual components that are built-in types.
Operations on the DynAny interface can also be used to recursively
build up a compound data-structure from built-in types.