@@ -283,58 +283,84 @@ pub enum Variance {
283
283
284
284
#[ derive( Copy , Clone , Debug ) ]
285
285
pub enum AutoAdjustment < ' tcx > {
286
- AdjustReifyFnPointer , // go from a fn-item type to a fn-pointer type
287
- AdjustUnsafeFnPointer , // go from a safe fn pointer to an unsafe fn pointer
286
+ AdjustReifyFnPointer , // go from a fn-item type to a fn-pointer type
287
+ AdjustUnsafeFnPointer , // go from a safe fn pointer to an unsafe fn pointer
288
288
AdjustDerefRef ( AutoDerefRef < ' tcx > ) ,
289
289
}
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
298
- /// either a raw or borrowed pointer. In these cases unsize is None.
299
293
///
300
- /// A DST coercon involves unsizing the underlying data. We start with a thin
301
- /// pointer, deref a number of times, unsize the underlying data, then autoref.
302
- /// The 'unsize' phase may change a fixed length array to a dynamically sized one,
303
- /// 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:
294
+ /// We transform pointers by following the following steps in order:
295
+ /// 1. Deref the pointer `self.autoderefs` times (may be 0).
296
+ /// 2. If `autoref` is `Some(_)`, then take the address and produce either a
297
+ /// `&` or `*` pointer.
298
+ /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
299
+ /// which will do things like convert thin pointers to fat
300
+ /// pointers, or convert structs containing thin pointers to
301
+ /// structs containing fat pointers, or convert between fat
302
+ /// pointers. We don't store the details of how the transform is
303
+ /// done (in fact, we don't know that, because it might depend on
304
+ /// the precise type parameters). We just store the target
305
+ /// type. Trans figures out what has to be done at monomorphization
306
+ /// time based on the precise source/target type at hand.
307
+ ///
308
+ /// To make that more concrete, here are some common scenarios:
309
+ ///
310
+ /// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
311
+ /// Here the pointer will be dereferenced N times (where a dereference can
312
+ /// happen to to raw or borrowed pointers or any smart pointer which implements
313
+ /// Deref, including Box<_>). The number of dereferences is given by
314
+ /// `autoderefs`. It can then be auto-referenced zero or one times, indicated
315
+ /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
316
+ /// None.
317
+ ///
318
+ /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
319
+ /// with a thin pointer, deref a number of times, unsize the underlying data,
320
+ /// then autoref. The 'unsize' phase may change a fixed length array to a
321
+ /// dynamically sized one, a concrete object to a trait object, or statically
322
+ /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
323
+ /// represented by:
324
+ ///
325
+ /// ```
306
326
/// AutoDerefRef {
307
327
/// autoderefs: 1, // &[i32; 4] -> [i32; 4]
308
- /// unsize: Some([i32]), // [i32; 4] -> [i32]
309
328
/// autoref: Some(AutoPtr), // [i32] -> &[i32]
329
+ /// unsize: Some([i32]), // [i32; 4] -> [i32]
310
330
/// }
331
+ /// ```
332
+ ///
311
333
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
312
334
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
313
335
/// The autoderef and -ref are the same as in the above example, but the type
314
336
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
315
337
/// the underlying conversions from `[i32; 4]` to `[i32]`.
316
338
///
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:
339
+ /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
340
+ /// that case, we have the pointer we need coming in, so there are no
341
+ /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
342
+ /// At some point, of course, `Box` should move out of the compiler, in which
343
+ /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
344
+ /// Box<[i32]> is 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
0 commit comments