@@ -249,6 +249,45 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
249249 return err_info;
250250 }
251251
252+ // Here we are considering a case of converting
253+ // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
254+ // which acts like a pointer to `U`, but carries along some extra data of type `T`:
255+ //
256+ // struct Foo<T, U> {
257+ // extra: T,
258+ // ptr: *mut U,
259+ // }
260+ //
261+ // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
262+ // to `Foo<T, [i32]>`. That impl would look like:
263+ //
264+ // impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
265+ //
266+ // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
267+ // when this coercion occurs, we would be changing the
268+ // field `ptr` from a thin pointer of type `*mut [i32;
269+ // 3]` to a fat pointer of type `*mut [i32]` (with
270+ // extra data `3`). **The purpose of this check is to
271+ // make sure that we know how to do this conversion.**
272+ //
273+ // To check if this impl is legal, we would walk down
274+ // the fields of `Foo` and consider their types with
275+ // both substitutes. We are looking to find that
276+ // exactly one (non-phantom) field has changed its
277+ // type, which we will expect to be the pointer that
278+ // is becoming fat (we could probably generalize this
279+ // to mutiple thin pointers of the same type becoming
280+ // fat, but we don't). In this case:
281+ //
282+ // - `extra` has type `T` before and type `T` after
283+ // - `ptr` has type `*mut U` before and type `*mut V` after
284+ //
285+ // Since just one field changed, we would then check
286+ // that `*mut U: CoerceUnsized<*mut V>` is implemented
287+ // (in other words, that we know how to do this
288+ // conversion). This will work out because `U:
289+ // Unsize<V>`, and we have a builtin rule that `*mut
290+ // U` can be coerced to `*mut V` if `U: Unsize<V>`.
252291 let fields = & def_a. struct_variant ( ) . fields ;
253292 let diff_fields = fields. iter ( )
254293 . enumerate ( )
@@ -260,8 +299,16 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
260299 return None ;
261300 }
262301
263- // Ignore fields that aren't significantly changed
264- if let Ok ( ok) = infcx. sub_types ( false , & cause, b, a) {
302+ // Ignore fields that aren't changed; it may
303+ // be that we could get away with subtyping or
304+ // something more accepting, but we use
305+ // equality because we want to be able to
306+ // perform this check without computing
307+ // variance where possible. (This is because
308+ // we may have to evaluate constraint
309+ // expressions in the course of execution.)
310+ // See e.g. #41936.
311+ if let Ok ( ok) = infcx. eq_types ( false , & cause, b, a) {
265312 if ok. obligations . is_empty ( ) {
266313 return None ;
267314 }
0 commit comments