Немного предыстории:
В Swift 3 были введены дополнительные типы диапазонов, что в сумме составило четыре (см., Например, Ole Begemann: Диапазоны в Swift 3 ):
Range, ClosedRange, CountableRange, CountableClosedRange
С реализацией SE-0143 Условных соответствий в Swift 4.2, «исчисляемые» варианты больше не являются отдельными типами, а являются (ограниченными) псевдонимами типа, например
public typealias CountableRange<Bound: Strideable> = Range<Bound>
where Bound.Stride : SignedInteger
и, как следствие, были удалены различные преобразования между различными типами диапазонов, такие как
init(_ other: Range<Range.Bound>)
инициализатора struct Range
.Все эти изменения являются частью [stdlib] [WIP] Elifyate (Closed) CountableRange с использованием условного соответствия (# 13342) commit.
Так вот почему
let range: Range<Index> = Range<Index>(start..<self.endIndex)
больше не компилируется.
Как исправить
Как вы уже поняли, это можно просто исправить как
let range: Range<Index> = start..<self.endIndex
или просто
let range = start..<self.endIndex
без аннотации типа.
Другой вариант - использовать односторонний диапазон (представлен в Swift 4 с SE-0172 Односторонние диапазоны ):
extension String {
func index(of aString: String, startingFrom position: Int = 0) -> String.Index? {
let start = index(startIndex, offsetBy: position)
return self[start...].range(of: aString, options: .literal)?.lowerBound
}
}
Это работает, потому что подстрока self[start...]
делит свои индексы с исходной строкой self
.