Swiftの型システムを読む その11 - Typeクラス周辺のクラス図

November 23, 2017

(もはや記事のナンバリングの意味はあんまりなくなってきた気がする。。)

lib/Semaや依存するlib/AST を読むにあたっての障壁の1つとしてType関連のクラス多すぎ問題がある。

ざっと書いただけでも

  • TypeRepr
  • Type
  • TypeLoc
  • TypeBase やその派生クラスたち
  • CanType で表現されるCanonicalなType
  • 型には現れないけど InterfaceType とか DeclaredType とかなにを指しているのかイマイチよくわからないものたち
    • Type* getXXXXTypeだけでも数十種類ある

ここをクリアすべくType周辺のクラス図を作ってみた。 各クラスの解説は少しだけにして、詳細な解説はいつかやる。

TypeBase / Type / CanType

基本的には型を表すクラスはTypeではなく TypeBase を継承して作られている。

じゃあTypeクラスはなに?というとTypeBase のポインタを持ったシンプルな値型。TypeBaseからの暗黙変換?(C++的になんと呼ぶかわからない) が定義されているので、コードを追っていると突然TypeBaseからTypeになっていることがある。

CanType は「Canonical Type」の略で、シンタックスシュガー(A? -> Optional<A>) やtypealiasなどを解決し、その結果をTypeのキャッシュをしたりする。

Canonicalizeされた結果が同じなら同じポインタを返すので、そのままハッシュのキーとして使えるとか。 Sema 内でもよく type->getCanonicalType() を使ってからなにかチェックを行っていることが多いのでかなり重要なものと思われる。

CanType.svg (4.9 kB)

NominalType

一番馴染みがありそうな型たち。以前の記事でprotocolは型じゃないのでは?みたいに書いたけどProtocolType がありますね。。。ただProtocolTypeだと isExistentialType でtrueが返るので存在型を表しているのでしょう かね。。

NominalType.svg (10.0 kB)

BoundGenericType

型パラメータを持っていて、その型パラメータがすでに具体的になっている状態を「Bound」を呼ぶらしい。

BoundGenericType.svg (8.6 kB)

FunctionType

関数を表す型で、型パラメータを持つかどうかで別れている。

AnyFunction.svg (6.8 kB)

SyntaxSugarType

名前の通り [Int], Int? , Int! らへんを指すみたい。上に書いたgetCanonicalType のタイミングでデシュガーされる。

SyntaxSugar.svg (8.5 kB)

MetatypeType

String.Type とか MyProtocol.Protocol とかを指す型のよう。 Existentialかどうかで別れているんですね。

MetatypeType.svg (6.9 kB)

SubstitutableType

これもきちんと調べてないけど、Substitutable という名前から推測すると、おそらく型推論後にApplyされる型なのだろうか…? でも一番それっぽいTypeVariableTypeSubstitutableType ではないのでわからない。。

SubstitutableType.svg (6.9 kB)

BuiltinType

BuiltinType.svg (19.2 kB)

その他 TypeBase派生クラス

OtherTypes.svg (18.9 kB)

まとめ

とりあえずTypeBase とその派生クラスたちをざっと見た。 少し気になったのはthrows とかは型にあらわれていないけどどこで管理しているのだろう?と思った。 (inoutInOutType として現れているのに)

TypeLocTypeRepr周りもそのうち書くかも。

このエントリーをはてなブックマークに追加