Ответ 1
Немного предыстории:
В 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] Eliminate (Closed) CountableRange с использованием фиксации условного соответствия (# 13342).
Так вот почему
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
.