Быстрый отказоустойчивый инициализатор, вызывающий инициализатор ExpressibleByStringLiteral

#swift #initialization

Вопрос:

Это самая странная проблема, с которой я сталкивался в swift, и она сводит меня с ума, пытаясь ее решить.

У меня есть структура , которая называется Algorithm соответствующей LosslessStringConvertible , поэтому у нее есть сбой инициализации. Просто чтобы проверить это, он всегда возвращает ноль:

 init?(_ description: String) {
    return nil
}
 

Algorithm также соответствует ExpressibleByStringLiteral , используя предыдущую инициализацию:

 extension Algorithm: ExpressibleByStringLiteral {
    init(stringLiteral value: String) {
        self.init(value)!
    }
}
 

Но когда я создаю экземпляр Algorithm с первого инициализации, я вижу в Xcode, что он не является необязательным

 let a = Algorithm("test")
a // a: Algorithm
 

А затем я запускаю приведенный выше код, он вылетает в строке self.init(value)! , начиная с ExpressibleByStringLiteral инициализации.

Я ни за что на свете не могу понять, почему это происходит. Я вызываю один инициализатор, а запускается совершенно другой.

Есть какие-нибудь идеи, почему это происходит?

Спасибо!

Комментарии:

1. Воспроизведено. Интересная часть заключается в том, что Algorithm.init("test") или Algorithm(String("test")) устранит проблему. Я предполагаю, что это что-то, как ExpressibleByStringLiteral это реализовано компилятором.

Ответ №1:

Об этой проблеме уже сообщалось в SR-10259, и, похоже, это ожидаемое поведение, возникающее в результате буквальной инициализации с помощью принуждения (SE-0213)

Возможные обходные пути:

 Algorithm.init("test") // don't coerce, call initializer
 
 Algorithm(String("test")) // convert literal to a `String` first