Skip to content

Commit 08364a4

Browse files
committed
Optimise a particularly clown shoes example of DST codegen
1 parent 52ef462 commit 08364a4

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

src/librustc/middle/trans/expr.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -193,24 +193,46 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
193193
datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
194194
}
195195
AutoDerefRef(ref adj) => {
196-
// Extracting a value from a box counts as a deref, but if we are
197-
// just converting Box<[T, ..n]> to Box<[T]> we aren't really doing
198-
// a deref (and wouldn't if we could treat Box like a normal struct).
199-
let autoderefs = match adj.autoref {
200-
Some(ty::AutoUnsizeUniq(..)) => adj.autoderefs - 1,
201-
_ => adj.autoderefs
196+
let (autoderefs, use_autoref) = match adj.autoref {
197+
// Extracting a value from a box counts as a deref, but if we are
198+
// just converting Box<[T, ..n]> to Box<[T]> we aren't really doing
199+
// a deref (and wouldn't if we could treat Box like a normal struct).
200+
Some(ty::AutoUnsizeUniq(..)) => (adj.autoderefs - 1, true),
201+
// We are a bit paranoid about adjustments and thus might have a re-
202+
// borrow here which merely derefs and then refs again (it might have
203+
// a different region or mutability, but we don't care here. It might
204+
// also be just in case we need to unsize. But if there are no nested
205+
// adjustments then it should be a no-op).
206+
Some(ty::AutoPtr(_, _, None)) if adj.autoderefs == 1 => {
207+
match ty::get(datum.ty).sty {
208+
// Don't skip a conversion from Box<T> to &T, etc.
209+
ty::ty_rptr(..) => {
210+
let method_call = MethodCall::autoderef(expr.id, adj.autoderefs-1);
211+
let method = bcx.tcx().method_map.borrow().find(&method_call).is_some();
212+
if method {
213+
// Don't skip an overloaded deref.
214+
(adj.autoderefs, true)
215+
} else {
216+
(adj.autoderefs - 1, false)
217+
}
218+
}
219+
_ => (adj.autoderefs, true),
220+
}
221+
}
222+
_ => (adj.autoderefs, true)
202223
};
203224

204225
if autoderefs > 0 {
205-
let lval = unpack_datum!(bcx,
206-
datum.to_lvalue_datum(bcx, "auto_deref", expr.id));
207-
226+
// Schedule cleanup.
227+
let lval = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "auto_deref", expr.id));
208228
datum = unpack_datum!(
209229
bcx, deref_multiple(bcx, expr, lval.to_expr_datum(), autoderefs));
210230
}
211231

212-
match adj.autoref {
213-
Some(ref a) => {
232+
// (You might think there is a more elegant way to do this than a
233+
// use_autoref bool, but then you remember that the borrow checker exists).
234+
match (use_autoref, &adj.autoref) {
235+
(true, &Some(ref a)) => {
214236
datum = unpack_datum!(bcx, apply_autoref(a,
215237
bcx,
216238
expr,
@@ -221,7 +243,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
221243
}
222244
}
223245
debug!("after adjustments, datum={}", datum.to_string(bcx.ccx()));
224-
return DatumBlock {bcx: bcx, datum: datum};
246+
return DatumBlock::new(bcx, datum);
225247

226248
fn apply_autoref<'a>(autoref: &ty::AutoRef,
227249
bcx: &'a Block<'a>,

0 commit comments

Comments
 (0)