Skip to content

Commit 91d603a

Browse files
committed
rustc: move autoref and unsize from Adjust::DerefRef to Adjustment.
1 parent 4a754f2 commit 91d603a

File tree

15 files changed

+290
-304
lines changed

15 files changed

+290
-304
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,14 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Ad
100100
ty::adjustment::Adjust::UnsafeFnPointer |
101101
ty::adjustment::Adjust::ClosureFnPointer |
102102
ty::adjustment::Adjust::MutToConstPointer => {}
103-
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
103+
ty::adjustment::Adjust::Deref(ref autoderefs) => {
104104
autoderefs.hash_stable(hcx, hasher);
105-
autoref.hash_stable(hcx, hasher);
106-
unsize.hash_stable(hcx, hasher);
107105
}
108106
}
109107
}
110108
}
111109

112-
impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
110+
impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, autoref, unsize, target });
113111
impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl, target });
114112
impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
115113
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });

src/librustc/middle/expr_use_visitor.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -707,9 +707,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
707707
let infcx = self.mc.infcx;
708708
//NOTE(@jroesch): mixed RefCell borrow causes crash
709709
let adj = infcx.tables.borrow().adjustments.get(&expr.id).cloned();
710-
let cmt_unadjusted =
711-
return_if_err!(self.mc.cat_expr_unadjusted(expr));
710+
let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr));
712711
if let Some(adjustment) = adj {
712+
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
713713
match adjustment.kind {
714714
adjustment::Adjust::NeverToAny |
715715
adjustment::Adjust::ReifyFnPointer |
@@ -718,23 +718,20 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
718718
adjustment::Adjust::MutToConstPointer => {
719719
// Creating a closure/fn-pointer or unsizing consumes
720720
// the input and stores it into the resulting rvalue.
721-
debug!("walk_adjustment: trivial adjustment");
722-
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
721+
self.delegate_consume(expr.id, expr.span, cmt);
722+
assert!(adjustment.autoref.is_none() && !adjustment.unsize);
723+
return;
723724
}
724-
adjustment::Adjust::DerefRef { ref autoderefs, autoref, unsize } => {
725-
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
726-
727-
let cmt_derefd =
728-
return_if_err!(self.walk_autoderefs(expr, cmt_unadjusted, autoderefs));
725+
adjustment::Adjust::Deref(ref autoderefs) => {
726+
cmt = return_if_err!(self.walk_autoderefs(expr, cmt, autoderefs));
727+
}
728+
}
729729

730-
let cmt_refd =
731-
self.walk_autoref(expr, cmt_derefd, autoref);
730+
cmt = self.walk_autoref(expr, cmt, adjustment.autoref);
732731

733-
if unsize {
734-
// Unsizing consumes the thin pointer and produces a fat one.
735-
self.delegate_consume(expr.id, expr.span, cmt_refd);
736-
}
737-
}
732+
if adjustment.unsize {
733+
// Unsizing consumes the thin pointer and produces a fat one.
734+
self.delegate_consume(expr.id, expr.span, cmt);
738735
}
739736
}
740737
}

src/librustc/middle/mem_categorization.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,11 +475,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
475475
Some(adjustment) => {
476476
debug!("cat_expr({:?}): {:?}", adjustment, expr);
477477
match adjustment.kind {
478-
adjustment::Adjust::DerefRef {
479-
ref autoderefs,
480-
autoref: None,
481-
unsize: false
482-
} => {
478+
adjustment::Adjust::Deref(ref autoderefs)
479+
if adjustment.autoref.is_none() && !adjustment.unsize => {
483480
// Equivalent to *expr or something similar.
484481
let mut cmt = self.cat_expr_unadjusted(expr)?;
485482
debug!("cat_expr: autoderefs={:?}, cmt={:?}",
@@ -499,7 +496,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
499496
adjustment::Adjust::UnsafeFnPointer |
500497
adjustment::Adjust::ClosureFnPointer |
501498
adjustment::Adjust::MutToConstPointer |
502-
adjustment::Adjust::DerefRef {..} => {
499+
adjustment::Adjust::Deref(_) => {
503500
// Result is an rvalue.
504501
let expr_ty = self.expr_ty_adjusted(expr)?;
505502
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))

src/librustc/ty/adjustment.rs

Lines changed: 82 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,83 @@ use hir::def_id::DefId;
1313
use ty::{self, Ty, TyCtxt, TypeAndMut};
1414
use ty::subst::Substs;
1515

16+
17+
/// Represents coercing a value to a different type of value.
18+
///
19+
/// We transform values by following the following steps in order:
20+
/// 1. Apply a step of `Adjust` (see its variants for details).
21+
/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
22+
/// `&` or `*` pointer.
23+
/// 3. If `unsize` is `true`, then apply the unsize transformation,
24+
/// which will do things like convert thin pointers to fat
25+
/// pointers, or convert structs containing thin pointers to
26+
/// structs containing fat pointers, or convert between fat
27+
/// pointers. We don't store the details of how the transform is
28+
/// done (in fact, we don't know that, because it might depend on
29+
/// the precise type parameters). We just store the target
30+
/// type. Trans figures out what has to be done at monomorphization
31+
/// time based on the precise source/target type at hand.
32+
///
33+
/// To make that more concrete, here are some common scenarios:
34+
///
35+
/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
36+
/// Here the pointer will be dereferenced N times (where a dereference can
37+
/// happen to raw or borrowed pointers or any smart pointer which implements
38+
/// Deref, including Box<_>). The types of dereferences is given by
39+
/// `autoderefs`. It can then be auto-referenced zero or one times, indicated
40+
/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
41+
/// `false`.
42+
///
43+
/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
44+
/// with a thin pointer, deref a number of times, unsize the underlying data,
45+
/// then autoref. The 'unsize' phase may change a fixed length array to a
46+
/// dynamically sized one, a concrete object to a trait object, or statically
47+
/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
48+
/// represented by:
49+
///
50+
/// ```
51+
/// Adjustment {
52+
/// kind: Adjust::Deref(vec![None]),// &[i32; 4] -> [i32; 4]
53+
/// autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
54+
/// unsize: true, // &[i32; 4] -> &[i32]
55+
/// target: `[i32]`,
56+
/// }
57+
/// ```
58+
///
59+
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
60+
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
61+
/// The autoderef and -ref are the same as in the above example, but the type
62+
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
63+
/// the underlying conversions from `[i32; 4]` to `[i32]`.
64+
///
65+
/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
66+
/// that case, we have the pointer we need coming in, so there are no
67+
/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
68+
/// At some point, of course, `Box` should move out of the compiler, in which
69+
/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
70+
/// Box<[i32]> is represented by:
71+
///
72+
/// ```
73+
/// Adjustment {
74+
/// kind: Adjust::Deref(vec![]),
75+
/// autoref: None,
76+
/// unsize: true,
77+
/// target: `Box<[i32]>`,
78+
/// }
79+
/// ```
1680
#[derive(Clone, RustcEncodable, RustcDecodable)]
1781
pub struct Adjustment<'tcx> {
82+
/// Step 1.
1883
pub kind: Adjust<'tcx>,
19-
pub target: Ty<'tcx>
84+
85+
/// Step 2. Optionally produce a pointer/reference from the value.
86+
pub autoref: Option<AutoBorrow<'tcx>>,
87+
88+
/// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
89+
/// `&[T]`. Note that the source could be a thin or fat pointer.
90+
pub unsize: bool,
91+
92+
pub target: Ty<'tcx>,
2093
}
2194

2295
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
@@ -36,103 +109,25 @@ pub enum Adjust<'tcx> {
36109
/// Go from a mut raw pointer to a const raw pointer.
37110
MutToConstPointer,
38111

39-
/// Represents coercing a pointer to a different kind of pointer - where 'kind'
40-
/// here means either or both of raw vs borrowed vs unique and fat vs thin.
41-
///
42-
/// We transform pointers by following the following steps in order:
43-
/// 1. Deref the pointer through `self.autoderefs` steps (may be no steps).
44-
/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
45-
/// `&` or `*` pointer.
46-
/// 3. If `unsize` is `true`, then apply the unsize transformation,
47-
/// which will do things like convert thin pointers to fat
48-
/// pointers, or convert structs containing thin pointers to
49-
/// structs containing fat pointers, or convert between fat
50-
/// pointers. We don't store the details of how the transform is
51-
/// done (in fact, we don't know that, because it might depend on
52-
/// the precise type parameters). We just store the target
53-
/// type. Trans figures out what has to be done at monomorphization
54-
/// time based on the precise source/target type at hand.
55-
///
56-
/// To make that more concrete, here are some common scenarios:
57-
///
58-
/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
59-
/// Here the pointer will be dereferenced N times (where a dereference can
60-
/// happen to raw or borrowed pointers or any smart pointer which implements
61-
/// Deref, including Box<_>). The types of dereferences is given by
62-
/// `autoderefs`. It can then be auto-referenced zero or one times, indicated
63-
/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
64-
/// `false`.
65-
///
66-
/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
67-
/// with a thin pointer, deref a number of times, unsize the underlying data,
68-
/// then autoref. The 'unsize' phase may change a fixed length array to a
69-
/// dynamically sized one, a concrete object to a trait object, or statically
70-
/// sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
71-
/// represented by:
72-
///
73-
/// ```
74-
/// Adjustment {
75-
/// kind: Adjust::DerefRef {
76-
/// autoderefs: vec![None], // &[i32; 4] -> [i32; 4]
77-
/// autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
78-
/// unsize: true, // &[i32; 4] -> &[i32]
79-
/// },
80-
/// target: `[i32]`,
81-
/// }
82-
/// ```
83-
///
84-
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
85-
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
86-
/// The autoderef and -ref are the same as in the above example, but the type
87-
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
88-
/// the underlying conversions from `[i32; 4]` to `[i32]`.
89-
///
90-
/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
91-
/// that case, we have the pointer we need coming in, so there are no
92-
/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
93-
/// At some point, of course, `Box` should move out of the compiler, in which
94-
/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
95-
/// Box<[i32]> is represented by:
96-
///
97-
/// ```
98-
/// Adjustment {
99-
/// Adjust::DerefRef {
100-
/// autoderefs: vec![],
101-
/// autoref: None,
102-
/// unsize: true,
103-
/// },
104-
/// target: `Box<[i32]>`,
105-
/// }
106-
/// ```
107-
DerefRef {
108-
/// Step 1. Apply a number of dereferences, producing an lvalue.
109-
autoderefs: Vec<Option<OverloadedDeref<'tcx>>>,
110-
111-
/// Step 2. Optionally produce a pointer/reference from the value.
112-
autoref: Option<AutoBorrow<'tcx>>,
113-
114-
/// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
115-
/// `&[T]`. Note that the source could be a thin or fat pointer.
116-
unsize: bool,
117-
}
112+
/// Apply a number of dereferences, producing an lvalue,
113+
/// if there are more than 0 dereferences.
114+
Deref(Vec<Option<OverloadedDeref<'tcx>>>),
118115
}
119116

120117
impl<'tcx> Adjustment<'tcx> {
121118
pub fn is_identity(&self) -> bool {
119+
if self.autoref.is_some() || self.unsize {
120+
return false;
121+
}
122122
match self.kind {
123123
Adjust::NeverToAny => self.target.is_never(),
124124

125-
Adjust::DerefRef {
126-
ref autoderefs,
127-
autoref: None,
128-
unsize: false
129-
} if autoderefs.is_empty() => true,
125+
Adjust::Deref(ref autoderefs) => autoderefs.is_empty(),
130126

131127
Adjust::ReifyFnPointer |
132128
Adjust::UnsafeFnPointer |
133129
Adjust::ClosureFnPointer |
134-
Adjust::MutToConstPointer |
135-
Adjust::DerefRef {..} => false,
130+
Adjust::MutToConstPointer => false,
136131
}
137132
}
138133
}

src/librustc/ty/structural_impls.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjustment<'a> {
224224
type Lifted = ty::adjustment::Adjustment<'tcx>;
225225
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
226226
tcx.lift(&self.kind).and_then(|kind| {
227-
tcx.lift(&self.target).map(|target| {
228-
ty::adjustment::Adjustment { kind, target }
227+
tcx.lift(&(self.autoref, self.target)).map(|(autoref, target)| {
228+
ty::adjustment::Adjustment {
229+
kind,
230+
autoref,
231+
unsize: self.unsize,
232+
target,
233+
}
229234
})
230235
})
231236
}
@@ -245,12 +250,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
245250
Some(ty::adjustment::Adjust::ClosureFnPointer),
246251
ty::adjustment::Adjust::MutToConstPointer =>
247252
Some(ty::adjustment::Adjust::MutToConstPointer),
248-
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
249-
tcx.lift(autoderefs).and_then(|autoderefs| {
250-
tcx.lift(autoref).map(|autoref| {
251-
ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize }
252-
})
253-
})
253+
ty::adjustment::Adjust::Deref(ref autoderefs) => {
254+
tcx.lift(autoderefs).map(ty::adjustment::Adjust::Deref)
254255
}
255256
}
256257
}
@@ -684,12 +685,16 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
684685
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
685686
ty::adjustment::Adjustment {
686687
kind: self.kind.fold_with(folder),
688+
autoref: self.autoref.fold_with(folder),
689+
unsize: self.unsize,
687690
target: self.target.fold_with(folder),
688691
}
689692
}
690693

691694
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
692-
self.kind.visit_with(visitor) || self.target.visit_with(visitor)
695+
self.kind.visit_with(visitor) ||
696+
self.autoref.visit_with(visitor) ||
697+
self.target.visit_with(visitor)
693698
}
694699
}
695700

@@ -701,12 +706,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
701706
ty::adjustment::Adjust::UnsafeFnPointer |
702707
ty::adjustment::Adjust::ClosureFnPointer |
703708
ty::adjustment::Adjust::MutToConstPointer => self.clone(),
704-
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
705-
ty::adjustment::Adjust::DerefRef {
706-
autoderefs: autoderefs.fold_with(folder),
707-
autoref: autoref.fold_with(folder),
708-
unsize,
709-
}
709+
ty::adjustment::Adjust::Deref(ref autoderefs) => {
710+
ty::adjustment::Adjust::Deref(autoderefs.fold_with(folder))
710711
}
711712
}
712713
}
@@ -718,8 +719,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
718719
ty::adjustment::Adjust::UnsafeFnPointer |
719720
ty::adjustment::Adjust::ClosureFnPointer |
720721
ty::adjustment::Adjust::MutToConstPointer => false,
721-
ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize: _ } => {
722-
autoderefs.visit_with(visitor) || autoref.visit_with(visitor)
722+
ty::adjustment::Adjust::Deref(ref autoderefs) => {
723+
autoderefs.visit_with(visitor)
723724
}
724725
}
725726
}

src/librustc_lint/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
890890

891891
// Check for overloaded autoderef method calls.
892892
if let Some(&Adjustment {
893-
kind: Adjust::DerefRef { ref autoderefs, .. }, ..
893+
kind: Adjust::Deref(ref autoderefs), ..
894894
}) = cx.tables.adjustments.get(&id) {
895895
let mut source = cx.tables.expr_ty(expr);
896896
for &overloaded in autoderefs {

0 commit comments

Comments
 (0)