Skip to content

Commit b35a587

Browse files
committed
Reviewer comments
1 parent 4ad4363 commit b35a587

File tree

4 files changed

+66
-47
lines changed

4 files changed

+66
-47
lines changed

Diff for: src/librustc/middle/expr_use_visitor.rs

+9-19
Original file line numberDiff line numberDiff line change
@@ -848,26 +848,16 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
848848

849849
self.walk_autoderefs(expr, adj.autoderefs);
850850

851-
// Weird hacky special case: AutoUnsizeUniq, which converts
852-
// from a ~T to a ~Trait etc, always comes in a stylized
853-
// fashion. In particular, we want to consume the ~ pointer
854-
// being dereferenced, not the dereferenced content (as the
855-
// content is, at least for upcasts, unsized).
856-
if let Some(ty) = adj.unsize {
857-
if let ty::ty_uniq(_) = ty.sty {
858-
assert!(adj.autoderefs == 0,
859-
format!("Expected no derefs with unsize AutoRefs, found: {}",
860-
adj.repr(self.tcx())));
861-
let cmt_unadjusted =
862-
return_if_err!(self.mc.cat_expr_unadjusted(expr));
863-
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
864-
return;
865-
}
866-
}
851+
let cmt_derefd =
852+
return_if_err!(self.mc.cat_expr_autoderefd(expr, adj.autoderefs));
867853

868-
let cmt_derefd = return_if_err!(
869-
self.mc.cat_expr_autoderefd(expr, adj.autoderefs));
870-
self.walk_autoref(expr, cmt_derefd, adj.autoref);
854+
let cmt_refd =
855+
self.walk_autoref(expr, cmt_derefd, adj.autoref);
856+
857+
if adj.unsize.is_some() {
858+
// Unsizing consumes the thin pointer and produces a fat one.
859+
self.delegate_consume(expr.id, expr.span, cmt_refd);
860+
}
871861
}
872862

873863

Diff for: src/librustc/middle/ty.rs

+52-26
Original file line numberDiff line numberDiff line change
@@ -283,58 +283,84 @@ pub enum Variance {
283283

284284
#[derive(Copy, Clone, Debug)]
285285
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
288288
AdjustDerefRef(AutoDerefRef<'tcx>),
289289
}
290290

291291
/// Represents coercing a pointer to a different kind of pointer - where 'kind'
292292
/// 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.
299293
///
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+
/// ```
306326
/// AutoDerefRef {
307327
/// autoderefs: 1, // &[i32; 4] -> [i32; 4]
308-
/// unsize: Some([i32]), // [i32; 4] -> [i32]
309328
/// autoref: Some(AutoPtr), // [i32] -> &[i32]
329+
/// unsize: Some([i32]), // [i32; 4] -> [i32]
310330
/// }
331+
/// ```
332+
///
311333
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
312334
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
313335
/// The autoderef and -ref are the same as in the above example, but the type
314336
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
315337
/// the underlying conversions from `[i32; 4]` to `[i32]`.
316338
///
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+
/// ```
320347
/// AutoDerefRef {
321348
/// autoderefs: 0,
322-
/// unsize: Some(Box<[i32]>),
323349
/// autoref: None,
350+
/// unsize: Some(Box<[i32]>),
324351
/// }
352+
/// ```
325353
#[derive(Copy, Clone, Debug)]
326354
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.
331356
pub autoderefs: usize,
332357

333-
/// Produce a pointer/reference from the value.
358+
/// Step 2. Optionally produce a pointer/reference from the value.
334359
pub autoref: Option<AutoRef<'tcx>>,
335360

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.
338364
pub unsize: Option<Ty<'tcx>>,
339365
}
340366

Diff for: src/librustc_typeck/check/method/confirm.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
143143
ty::adjust_ty_for_autoref(self.tcx(), target, Some(autoref))
144144
}))
145145
} else {
146-
// No unsizing should be performed without autoref.
146+
// No unsizing should be performed without autoref (at
147+
// least during method dispach). This is because we
148+
// currently only unsize `[T;N]` to `[T]`, and naturally
149+
// that must occur being a reference.
147150
assert!(pick.unsize.is_none());
148151
(None, None)
149152
};

Diff for: src/test/compile-fail/issue-21950.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::ops::Add;
1414

1515
fn main() {
1616
let x = &10 as
17-
//~^ ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
1817
&Add;
1918
//~^ ERROR the type parameter `RHS` must be explicitly specified in an object type because its default value `Self` references the type `Self`
19+
//~^^ ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
2020
}

0 commit comments

Comments
 (0)