The error is somewhat confusing. The problem is that nothing about the type signature of your Optional.or method constrains the type parameter of Optional.UnwrapError.
Remember that nested types capture generic parameters from the outer type, so Optional<Int>.UnwrapError and Optional<String>.UnwrapError are different types. If this is not desired behavior, you can't use a nested type.
Otherwise, you can also define another overload of or. A version taking an Optional<Wrapped>.UnwrapError would allow the caller to write Optional.UnwrapError(), and the type parameter would be inferred. But again, if the type parameter has no semantic meaning here, a nested type might not be the right solution.
Though this complicates the method signature, everything else works as expected and on the calling side there is no excess verbosity. Are there any downsides to this approach?
In a method signature, you can omit the generic parameters and it will infer them from the current scope. So Optional.UnwrapError means Optional<Wrapped>.UnwrapError. I don't really recommend using this technique, but it can help sometimes. @Douglas_Gregor hates it
Well, the obvious one is you cannot pass an Error other than Optional<Wrapped>.UnwrapError, which makes me wonder why you need to pass the error in the first place. UnwrapError carries no state, so you may as well construct it inside your method.
Perhaps you want to use a default argument, like so:
public func or(throw exception: Error = Optional.UnwrapError())
It would not read very well on the calling side, because all that remains would be try anOptional.or(). This could be solved with clever renaming ;-)
public func or(throw exception: Error = Optional.UnwrapError()) now the compiler complains about Initializer 'init()' is internal and cannot be referenced from a default argument value
Imagine you didn't have a default argument here. Then the user of the library would need to construct an UnwrapError themselves, which they would not be able to do, because its initializer is internal! Either you need to define a public init() {} inside the error struct, or perhaps the or() method itself should not be public.
The or() method expects a general Error. You could call it using an other Error type as argument. So the compiler's interpretation is very strict or do I miss something?
I'm not sure I understand the question. But yes, or will accept any instance of a type conforming to Error as an argument.
let a: Int? = 5
class Foo: Error {}
print(try a.or(throw: Foo()))
But since default struct initializers are internal, you won't be able to initialize an Optional.UnwrapError instance outside your module (to pass it as an argument). If you are still wondering why the compiler complains about exception: Error = Optional.UnwrapError(), that is because the default value (Optional.UnwrapError()) will have to be initialized when you call the function without arguments (But it can't be initialized outside the module, because the default initializer of Optional.UnwrapError is internal. In other words, the compiler is telling you that you will not be able to a.or() outside the module. (Providing a default argument guarantees that you can).