Something strange with extensions

I was coding as usual and decided to extend stdlib's String type to be conforming to Error protocol:

extension String: Error {}

That worked ok, but when I needed to extend that type String: Error I found that it was impossible.

extension String where Self: Error {} //error
typealias StringError = String where Self: Error //error

My question is if I should create wrapping type for that and if it is a limitation in type system.

What are you expecting those last two statements to do?

The first statement makes all Strings conform to Error. Thus, extension String where Self: Error is meaningless: all Strings conform to Error. The same applies to the typealias (though additionally you cannot place where clauses on non-generic typealias statements).

I don't know what you're trying to do, but neither of the things you did here are "limitations of the type system": they are correctly stating that your refinements don't make any sense.

You can imagine that extension String: Error is declared in one module. Now I want to extend that subtype, which has both properties of string and error. How would you do it from another module? Do you think it is possible to do redeclaration?

No subtype exists.

extension String: Error says that all strings are now Errors, not that there is a subtype of String that is an Error.

I think you meant

extension Error where Self == String {}

String does not have Self generic parameter.

You cannot attach a where clause in a non-generic typealias right now.

This is not strictly true as you could do that even before SE-0267, but not in a way that would produce a new existential type.

typealias IntResult<E> = Result<Int, E> where E: Error

where cause is allowed to align generic type constraints.

Yeah, I edited my post before your reply (sorry I typed in a hurry!)

1 Like