トレイト解決(新)
この章では、rustc_trait_selection/solve にある新しい WIP ソルバーで
トレイト解決がどのように機能するかを説明します。必要に応じて、
現在のソルバーおよび chalk ソルバーのドキュメントも参照してください。
コア概念
トレイトシステムの目的は、与えられたトレイト境界が満たされるかどうかを確認することです。 特に、ジェネリックである可能性のある関数の本体を型チェックするときに重要です。 例:
#![allow(unused)]
fn main() {
fn uses_vec_clone<T: Clone>(x: Vec<T>) -> (Vec<T>, Vec<T>) {
(x.clone(), x)
}
}
ここで x.clone() の呼び出しでは、T: Clone が真であるという仮定のもとで、
Vec<T> が Clone を実装していることを証明する必要があります。
この関数の呼び出し元によって証明されるため、T: Clone を仮定できます。
「T: Clone を仮定して Vec<T>: Clone を証明する」という概念は Goal と呼ばれます。
Vec<T>: Clone と T: Clone はどちらも Predicate を使って表現されます。他にも述語があり、
特に関連アイテムに対する等値境界があります: <Vec<T> as IntoIterator>::Item == T。
網羅的な一覧については PredicateKind enum を参照してください。Goal は、証明する必要がある
predicate と、この述語が成立しなければならない param_env として表現されます。
与えられたゴールに対して、各可能な Candidate が適用できるかどうかを、
そのネストされたゴールを再帰的に証明することで確認し、ゴールを証明します。
例を含む可能な候補の一覧については CandidateSource を参照してください。
最も重要な候補は Impl 候補、すなわちユーザーによって書かれたトレイト実装と、
ParamEnv 候補、すなわち現在の環境における仮定です。
上記の例を見ると、Vec<T>: Clone を証明するには、まず
impl<T: Clone> Clone for Vec<T> を使用します。この impl を使用するには、
T: Clone が成立するというネストされたゴールを証明する必要があります。
これは、ネストされたゴールを持たない ParamEnv の仮定 T: Clone を使用できます。
したがって Vec<T>: Clone は成立します。
トレイトソルバーは、CanonicalResponse として成功、曖昧性、またはエラーのいずれかを返すことができます。
成功と曖昧性の場合は、推論制約とリージョン制約も返します。