> I understand that Rust is not doing implicit conversions, but the effect for 
> the user is pretty much the same.  The try macro is converting the underlying 
> error to the type that can be propagated.  As I stated, Swift is not Rust and 
> deserves a different solution.  
> 
> Nevertheless, that does not minimize the need to solve the problem.  I 
> maintain that the problem solved by the try macro is a significant one that 
> is not addressed by the current proposal.  I would really like to see it 
> addressed one way or another.
> 
>> 
>> You could make it “nicer” by doing something like this:
>> 
>> try MyError.convertFrom(try 
>> funcThatThrowsAnErrorThatMustBeTranslatedItoMyPublishedError())
> 
> Can you elaborate on how you think this would work?  If 
> funcThatThrowsAnErrorThatMustBeTranslatedItoMyPublishedError actually throws 
> it will be propagated to the next enclosing catch clause.  
> MyError.convertFrom will not have a chance to do anything with it.

Here’s a full playground example (I’ve annotated in comments where the type of 
error could be described):

enum InternalError: ErrorType {
    case Internal(value: Int)
}

enum PublishedError: ErrorType {
    static func from<T>(@autoclosure fn: () throws -> T) throws -> T {
        do {
            return try fn()
        }
        catch InternalError.Internal(let value) {
            throw PublishedError.Converted(value: value)
        }
        catch {
            fatalError("unsupported conversion")
        }
    }
    
    case Converted(value: Int)
}


func example() {

    func bad(value: Int) throws /* InternalError */ -> Int {
        if value % 2 == 0 { throw InternalError.Internal(value: value) }
        return value
    }

    func verbose(value: Int) throws /* PublishedError */ -> Int {
        do {
            return try bad(value)
        }
        catch InternalError.Internal(let value) {
            throw PublishedError.Converted(value: value)
        }
        catch {
            fatalError("unsupported conversion")
        }
    }
    
    func convert(value: Int) throws /* PublishedError */ -> Int {
        return try PublishedError.from(try bad(value))
    }
    
    do {
        let r1 = try verbose(11)
        print("verbose: \(r1)")
        
        let r2 = try convert(9)
        print("converted: \(r2)")
    }
    catch {
        print("error: \(error)")
    }

}

example()


As you can see, the “verbose()” and the “from()” conversion are basically the 
same implementation. What I’m saying is that I believe you can simply do the 
explicit conversion yourself without much fanfare (compare the verbose() and 
convert() implementations).

In the implementation of PublishedError.from() you can use Swift’s pattern 
matching to do all of your conversions in a single place. Note that where the 
implementation of “from” is at doesn’t matter, it could be on another type or a 
free function, whatever.

> Are you willing to explore adding *explicit* syntax to convert thrown errors 
> to your proposal?  That seems like it might be a reasonable compromise 
> between implicit conversions and manual boilerplate.  

The only boiler plate I’m seeing is the explicit conversion call: 
PublishedError.from(try bad(value))

Am I misunderstanding something? 

To me, this would be much more confusing:

    func convert(value: Int) throws /* PublishedError */ -> Int {
        return try bad(value)     /* implicit conversion from InternalError -> 
PublishedError */
    }

If there were implicit type conversions, this would have to be something that 
Swift supported all up. I’d be very hesitant to make this work for only errors. 
For example, how does implicit conversion work if we can later extend this to 
async behaviors? Do we have special conversions that can take an async error 
make it a synchronous error? How about vice-versa?

I guess I wouldn’t want to go further than having explicit conversions until we 
better understood all of those answers and how implicit type conversion would 
work in Swift generally. If I recall, Swift had implicit type conversion in the 
early versions, and it has been removed in most places. 

-David

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to