@@ -290,51 +290,77 @@ pub enum AutoAdjustment<'tcx> {
290
290
291
291
/// Represents coercing a pointer to a different kind of pointer - where 'kind'
292
292
/// here means either or both of raw vs borrowed vs unique and fat vs thin.
293
- /// The simplest cases are where the pointer is not adjusted fat vs thin. Here
294
- /// the pointer will be dereferenced N times (where a dereference can happen to
295
- /// to raw or borrowed pointers or any smart pointer which implements Deref,
296
- /// including Box<_>). The number of dereferences is given by `autoderefs`.
297
- /// It can then be auto-referenced zero or one times, indicated by `autoref`, to
293
+ /// We transform pointers by following the following steps in order:
294
+ /// 1. Deref the pointer `self.autoderefs` times (may be 0).
295
+ /// 2. If `autoref` is `Some(_)`, then take the address and produce either a
296
+ /// `&` or `*` pointer.
297
+ /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
298
+ /// which will do things like convert thin pointers to fat
299
+ /// pointers, or convert structs containing thin pointers to
300
+ /// structs containing fat pointers, or convert between fat
301
+ /// pointers. We don't store the details of how the transform is
302
+ /// done (in fact, we don't know that, because it might depend on
303
+ /// the precise type parameters). We just store the target
304
+ /// type. Trans figures out what has to be done at monomorphization
305
+ /// time based on the precise source/target type at hand.
306
+ ///
307
+ /// To make that more concrete, here are some common scenarios:
308
+ ///
309
+ /// 1. The simplest cases are where the pointer is not adjusted fat vs
310
+ /// thin. Here the pointer will be dereferenced N times (where a
311
+ /// dereference can happen to to raw or borrowed pointers or any smart
312
+ /// pointer which implements Deref, including Box<_>). The number of
313
+ /// dereferences is given by `autoderefs`. It can then be
314
+ /// auto-referenced zero or one times, indicated by `autoref`, to
298
315
/// either a raw or borrowed pointer. In these cases unsize is None.
299
316
///
300
- /// A DST coercon involves unsizing the underlying data. We start with a thin
317
+ /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start with a thin
301
318
/// pointer, deref a number of times, unsize the underlying data, then autoref.
302
319
/// The 'unsize' phase may change a fixed length array to a dynamically sized one,
303
320
/// a concrete object to a trait object, or statically sized struct to a dyncamically
304
- /// sized one.
305
- /// E.g., &[i32; 4] -> &[i32] is represented by:
321
+ /// sized one. E.g., &[i32; 4] -> &[i32] is represented by:
322
+ ///
323
+ /// ```
306
324
/// AutoDerefRef {
307
325
/// autoderefs: 1, // &[i32; 4] -> [i32; 4]
308
- /// unsize: Some([i32]), // [i32; 4] -> [i32]
309
326
/// autoref: Some(AutoPtr), // [i32] -> &[i32]
327
+ /// unsize: Some([i32]), // [i32; 4] -> [i32]
310
328
/// }
311
- /// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
312
- /// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
313
- /// The autoderef and -ref are the same as in the above example, but the type
314
- /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
315
- /// the underlying conversions from `[i32; 4]` to `[i32]`.
329
+ /// ```
316
330
///
317
- /// Box pointers are treated somewhat differently, the last deref is not counted,
318
- /// nor is the 'ref' to a `Box<_>`. Imagine them more like structs.
319
- /// E.g., Box<[i32; 4]> -> Box<[i32]> is represented by:
331
+ /// Note that for a struct, the 'deep' unsizing of the struct is not
332
+ /// recorded. E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32;
333
+ /// 4]> to &Foo<[i32]> The autoderef and -ref are the same as in the
334
+ /// above example, but the type stored in `unsize` is `Foo<[i32]>`, we
335
+ /// don't store any further detail about the underlying conversions
336
+ /// from `[i32; 4]` to `[i32]`.
337
+ ///
338
+ /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special
339
+ /// case. In that case, we have the pointer we need coming in, so
340
+ /// there are no autoderefs, and no autoref. Instead we just do the
341
+ /// `Unsize` transformation. At some point, of course, `Box` should
342
+ /// move out of the compiler, in which case this is analogous to
343
+ /// transformating a struct. E.g., Box<[i32; 4]> -> Box<[i32]> is
344
+ /// represented by:
345
+ ///
346
+ /// ```
320
347
/// AutoDerefRef {
321
348
/// autoderefs: 0,
322
- /// unsize: Some(Box<[i32]>),
323
349
/// autoref: None,
350
+ /// unsize: Some(Box<[i32]>),
324
351
/// }
352
+ /// ```
325
353
#[ derive( Copy , Clone , Debug ) ]
326
354
pub struct AutoDerefRef < ' tcx > {
327
- // FIXME with more powerful date structures we could have a better design
328
- // here.
329
-
330
- /// Apply a number of dereferences, producing an lvalue.
355
+ /// Step 1. Apply a number of dereferences, producing an lvalue.
331
356
pub autoderefs : usize ,
332
357
333
- /// Produce a pointer/reference from the value.
358
+ /// Step 2. Optionally produce a pointer/reference from the value.
334
359
pub autoref : Option < AutoRef < ' tcx > > ,
335
360
336
- /// Unsize a pointer/reference value, e.g. &[T; n] to &[T].
337
- /// The stored type is the target pointer type.
361
+ /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
362
+ /// `&[T]`. The stored type is the target pointer type. Note that
363
+ /// the source could be a thin or fat pointer.
338
364
pub unsize : Option < Ty < ' tcx > > ,
339
365
}
340
366
@@ -5831,6 +5857,7 @@ pub fn struct_lockstep_tails<'tcx>(cx: &ctxt<'tcx>,
5831
5857
source : Ty < ' tcx > ,
5832
5858
target : Ty < ' tcx > )
5833
5859
-> ( Ty < ' tcx > , Ty < ' tcx > ) {
5860
+ // NIT: Maybe move `struct_lockstep_tails` into trans, since it is only used there?
5834
5861
let ( mut a, mut b) = ( source, target) ;
5835
5862
while let ( & ty_struct( a_did, a_substs) , & ty_struct( b_did, b_substs) ) = ( & a. sty , & b. sty ) {
5836
5863
if a_did != b_did {
0 commit comments