@@ -70,6 +70,72 @@ pub(crate) fn compare_impl_method<'tcx>(
7070 }
7171}
7272
73+ /// This function is best explained by example. Consider a trait:
74+ ///
75+ /// trait Trait<'t, T> {
76+ /// // `trait_m`
77+ /// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
78+ /// }
79+ ///
80+ /// And an impl:
81+ ///
82+ /// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
83+ /// // `impl_m`
84+ /// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
85+ /// }
86+ ///
87+ /// We wish to decide if those two method types are compatible.
88+ /// For this we have to show that, assuming the bounds of the impl hold, the
89+ /// bounds of `trait_m` imply the bounds of `impl_m`.
90+ ///
91+ /// We start out with `trait_to_impl_substs`, that maps the trait
92+ /// type parameters to impl type parameters. This is taken from the
93+ /// impl trait reference:
94+ ///
95+ /// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
96+ ///
97+ /// We create a mapping `dummy_substs` that maps from the impl type
98+ /// parameters to fresh types and regions. For type parameters,
99+ /// this is the identity transform, but we could as well use any
100+ /// placeholder types. For regions, we convert from bound to free
101+ /// regions (Note: but only early-bound regions, i.e., those
102+ /// declared on the impl or used in type parameter bounds).
103+ ///
104+ /// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
105+ ///
106+ /// Now we can apply `placeholder_substs` to the type of the impl method
107+ /// to yield a new function type in terms of our fresh, placeholder
108+ /// types:
109+ ///
110+ /// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
111+ ///
112+ /// We now want to extract and substitute the type of the *trait*
113+ /// method and compare it. To do so, we must create a compound
114+ /// substitution by combining `trait_to_impl_substs` and
115+ /// `impl_to_placeholder_substs`, and also adding a mapping for the method
116+ /// type parameters. We extend the mapping to also include
117+ /// the method parameters.
118+ ///
119+ /// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
120+ ///
121+ /// Applying this to the trait method type yields:
122+ ///
123+ /// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
124+ ///
125+ /// This type is also the same but the name of the bound region (`'a`
126+ /// vs `'b`). However, the normal subtyping rules on fn types handle
127+ /// this kind of equivalency just fine.
128+ ///
129+ /// We now use these substitutions to ensure that all declared bounds are
130+ /// satisfied by the implementation's method.
131+ ///
132+ /// We do this by creating a parameter environment which contains a
133+ /// substitution corresponding to `impl_to_placeholder_substs`. We then build
134+ /// `trait_to_placeholder_substs` and use it to convert the predicates contained
135+ /// in the `trait_m` generics to the placeholder form.
136+ ///
137+ /// Finally we register each of these predicates as an obligation and check that
138+ /// they hold.
73139fn compare_predicate_entailment < ' tcx > (
74140 tcx : TyCtxt < ' tcx > ,
75141 impl_m : & ty:: AssocItem ,
@@ -96,69 +162,6 @@ fn compare_predicate_entailment<'tcx>(
96162 } ,
97163 ) ;
98164
99- // This code is best explained by example. Consider a trait:
100- //
101- // trait Trait<'t, T> {
102- // fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
103- // }
104- //
105- // And an impl:
106- //
107- // impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
108- // fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
109- // }
110- //
111- // We wish to decide if those two method types are compatible.
112- //
113- // We start out with trait_to_impl_substs, that maps the trait
114- // type parameters to impl type parameters. This is taken from the
115- // impl trait reference:
116- //
117- // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
118- //
119- // We create a mapping `dummy_substs` that maps from the impl type
120- // parameters to fresh types and regions. For type parameters,
121- // this is the identity transform, but we could as well use any
122- // placeholder types. For regions, we convert from bound to free
123- // regions (Note: but only early-bound regions, i.e., those
124- // declared on the impl or used in type parameter bounds).
125- //
126- // impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
127- //
128- // Now we can apply placeholder_substs to the type of the impl method
129- // to yield a new function type in terms of our fresh, placeholder
130- // types:
131- //
132- // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
133- //
134- // We now want to extract and substitute the type of the *trait*
135- // method and compare it. To do so, we must create a compound
136- // substitution by combining trait_to_impl_substs and
137- // impl_to_placeholder_substs, and also adding a mapping for the method
138- // type parameters. We extend the mapping to also include
139- // the method parameters.
140- //
141- // trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
142- //
143- // Applying this to the trait method type yields:
144- //
145- // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
146- //
147- // This type is also the same but the name of the bound region ('a
148- // vs 'b). However, the normal subtyping rules on fn types handle
149- // this kind of equivalency just fine.
150- //
151- // We now use these substitutions to ensure that all declared bounds are
152- // satisfied by the implementation's method.
153- //
154- // We do this by creating a parameter environment which contains a
155- // substitution corresponding to impl_to_placeholder_substs. We then build
156- // trait_to_placeholder_substs and use it to convert the predicates contained
157- // in the trait_m.generics to the placeholder form.
158- //
159- // Finally we register each of these predicates as an obligation in
160- // a fresh FulfillmentCtxt, and invoke select_all_or_error.
161-
162165 // Create mapping from impl to placeholder.
163166 let impl_to_placeholder_substs = InternalSubsts :: identity_for_item ( tcx, impl_m. def_id ) ;
164167
0 commit comments