Thor
Thor

Reputation: 10058

Different types shown when iterating over a String's UTF8View

I'm currently studying string in swift. I have two version of the same code

enter image description here

enter image description here

The variable in the for in loop are suppose to have the same type, but as you can see, the type is actually different?

I must be missing something here, but can't seem to figure out.

Upvotes: 1

Views: 105

Answers (1)

Hamish
Hamish

Reputation: 80811

This is merely a presentation thing – the _IndexableBase protocol (which Collection internally derives from) declares an _Element associated type as a workaround for a conformance cycle:

protocol _IndexableBase {

      // ...

      // The declaration of _Element and subscript here is a trick used to
      // break a cyclic conformance/deduction that Swift can't handle.  We
      // need something other than a Collection.Iterator.Element that can
      // be used as IndexingIterator<T>'s Element.  Here we arrange for
      // the Collection itself to have an Element type that's deducible from
      // its subscript.  Ideally we'd like to constrain this Element to be the same
      // as Collection.Iterator.Element (see below), but we have no way of
      // expressing it today.
      associatedtype _Element

      // ...
      subscript(position: Index) -> _Element { get }
      // ...
}

(Note this will all change once recursive protocol constraints are implemented)

In practice, this associated type should always be satisfied by the same type as the Collection's Iterator.Element, due to the fact that Collection has a

subscript(position: Index) -> Iterator.Element { get }

requirement. Thus when conforming to Collection, the compiler will by default deduce that Iterator.Element == _Element.

With String.UTF8View, it implements Collection with an Iterator.Element of type UTF8.CodeUnit (aka. UInt8). Therefore the types String.UTF8View._Element, String.UTF8View.Iterator.Element, UTF8.CodeUnit and UInt8 are all the same.

You can easily verify this for yourself by comparing the metatype values:

print(UInt8.self == UTF8.CodeUnit.self)                    // true
print(UInt8.self == String.UTF8View._Element.self)         // true
print(UInt8.self == String.UTF8View.Iterator.Element.self) // true

Xcode simply chooses to display different type aliases in this case. Although in Xcode 8.3 beta 4, they are both displayed as UTF8.CodeUnit.

Upvotes: 2

Related Questions