Skip to content

Commit de7cb0f

Browse files
committed
introduce DropAndReplace for translating assignments
this introduces a DropAndReplace terminator as a fix to rust-lang#30380. That terminator is suppsoed to be translated by desugaring during drop elaboration, which is not implemented in this commit, so this breaks `-Z orbit` temporarily.
1 parent 95206f4 commit de7cb0f

File tree

13 files changed

+139
-45
lines changed

13 files changed

+139
-45
lines changed

src/librustc/mir/repr.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,19 @@ pub enum TerminatorKind<'tcx> {
330330

331331
/// Drop the Lvalue
332332
Drop {
333-
value: Lvalue<'tcx>,
333+
location: Lvalue<'tcx>,
334334
target: BasicBlock,
335335
unwind: Option<BasicBlock>
336336
},
337337

338+
/// Drop the Lvalue and assign the new value over it
339+
DropAndReplace {
340+
location: Lvalue<'tcx>,
341+
value: Operand<'tcx>,
342+
target: BasicBlock,
343+
unwind: Option<BasicBlock>,
344+
},
345+
338346
/// Block ends with a call of a converging function
339347
Call {
340348
/// The function that’s being called
@@ -373,8 +381,14 @@ impl<'tcx> TerminatorKind<'tcx> {
373381
slice::ref_slice(t).into_cow(),
374382
Call { destination: None, cleanup: Some(ref c), .. } => slice::ref_slice(c).into_cow(),
375383
Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
376-
Drop { target, unwind: Some(unwind), .. } => vec![target, unwind].into_cow(),
377-
Drop { ref target, .. } => slice::ref_slice(target).into_cow(),
384+
DropAndReplace { target, unwind: Some(unwind), .. } |
385+
Drop { target, unwind: Some(unwind), .. } => {
386+
vec![target, unwind].into_cow()
387+
}
388+
DropAndReplace { ref target, unwind: None, .. } |
389+
Drop { ref target, unwind: None, .. } => {
390+
slice::ref_slice(target).into_cow()
391+
}
378392
}
379393
}
380394

@@ -393,8 +407,12 @@ impl<'tcx> TerminatorKind<'tcx> {
393407
Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
394408
Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
395409
Call { destination: None, cleanup: None, .. } => vec![],
410+
DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } |
396411
Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind],
397-
Drop { ref mut target, .. } => vec![target]
412+
DropAndReplace { ref mut target, unwind: None, .. } |
413+
Drop { ref mut target, unwind: None, .. } => {
414+
vec![target]
415+
}
398416
}
399417
}
400418
}
@@ -461,7 +479,9 @@ impl<'tcx> TerminatorKind<'tcx> {
461479
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
462480
Return => write!(fmt, "return"),
463481
Resume => write!(fmt, "resume"),
464-
Drop { ref value, .. } => write!(fmt, "drop({:?})", value),
482+
Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
483+
DropAndReplace { ref location, ref value, .. } =>
484+
write!(fmt, "replace({:?} <- {:?})", location, value),
465485
Call { ref func, ref args, ref destination, .. } => {
466486
if let Some((ref destination, _)) = *destination {
467487
write!(fmt, "{:?} = ", destination)?;
@@ -506,8 +526,12 @@ impl<'tcx> TerminatorKind<'tcx> {
506526
Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
507527
Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
508528
Call { destination: None, cleanup: None, .. } => vec![],
529+
DropAndReplace { unwind: None, .. } |
509530
Drop { unwind: None, .. } => vec!["return".into_cow()],
510-
Drop { .. } => vec!["return".into_cow(), "unwind".into_cow()],
531+
DropAndReplace { unwind: Some(_), .. } |
532+
Drop { unwind: Some(_), .. } => {
533+
vec!["return".into_cow(), "unwind".into_cow()]
534+
}
511535
}
512536
}
513537
}

src/librustc/mir/visit.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,20 @@ macro_rules! make_mir_visitor {
394394
TerminatorKind::Return => {
395395
}
396396

397-
TerminatorKind::Drop { ref $($mutability)* value,
397+
TerminatorKind::Drop { ref $($mutability)* location,
398398
target,
399399
unwind } => {
400-
self.visit_lvalue(value, LvalueContext::Drop);
400+
self.visit_lvalue(location, LvalueContext::Drop);
401+
self.visit_branch(block, target);
402+
unwind.map(|t| self.visit_branch(block, t));
403+
}
404+
405+
TerminatorKind::DropAndReplace { ref $($mutability)* location,
406+
ref $($mutability)* value,
407+
target,
408+
unwind } => {
409+
self.visit_lvalue(location, LvalueContext::Drop);
410+
self.visit_operand(value);
401411
self.visit_branch(block, target);
402412
unwind.map(|t| self.visit_branch(block, t));
403413
}

src/librustc_borrowck/borrowck/mir/dataflow/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,17 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
444444
repr::TerminatorKind::Return |
445445
repr::TerminatorKind::Resume => {}
446446
repr::TerminatorKind::Goto { ref target } |
447-
repr::TerminatorKind::Drop { ref target, value: _, unwind: None } => {
447+
repr::TerminatorKind::Drop { ref target, location: _, unwind: None } |
448+
449+
repr::TerminatorKind::DropAndReplace {
450+
ref target, value: _, location: _, unwind: None
451+
} => {
448452
self.propagate_bits_into_entry_set_for(in_out, changed, target);
449453
}
450-
repr::TerminatorKind::Drop { ref target, value: _, unwind: Some(ref unwind) } => {
454+
repr::TerminatorKind::Drop { ref target, location: _, unwind: Some(ref unwind) } |
455+
repr::TerminatorKind::DropAndReplace {
456+
ref target, value: _, location: _, unwind: Some(ref unwind)
457+
} => {
451458
self.propagate_bits_into_entry_set_for(in_out, changed, target);
452459
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
453460
}

src/librustc_borrowck/borrowck/mir/gather_moves.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,10 +671,18 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD
671671
let _ = discr;
672672
}
673673

674-
TerminatorKind::Drop { value: ref lval, target: _, unwind: _ } => {
674+
TerminatorKind::Drop { ref location, target: _, unwind: _ } => {
675675
let source = Location { block: bb,
676676
index: bb_data.statements.len() };
677-
bb_ctxt.on_move_out_lval(SK::Drop, lval, source);
677+
bb_ctxt.on_move_out_lval(SK::Drop, location, source);
678+
}
679+
TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
680+
let assigned_path = bb_ctxt.builder.move_path_for(location);
681+
bb_ctxt.path_map.fill_to(assigned_path.idx());
682+
683+
let source = Location { block: bb,
684+
index: bb_data.statements.len() };
685+
bb_ctxt.on_operand(SK::Use, value, source);
678686
}
679687
TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
680688
let source = Location { block: bb,

src/librustc_borrowck/borrowck/mir/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,15 +309,23 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
309309
Some(stmt) => match stmt.kind {
310310
repr::StatementKind::Assign(ref lvalue, _) => {
311311
debug!("drop_flag_effects: assignment {:?}", stmt);
312-
on_all_children_bits(tcx, mir, move_data,
312+
on_all_children_bits(tcx, mir, move_data,
313313
move_data.rev_lookup.find(lvalue),
314314
|moi| callback(moi, DropFlagState::Present))
315315
}
316316
},
317317
None => {
318-
// terminator - no move-ins except for function return edge
319-
let term = bb.terminator();
320-
debug!("drop_flag_effects: terminator {:?}", term);
318+
debug!("drop_flag_effects: replace {:?}", bb.terminator());
319+
match bb.terminator().kind {
320+
repr::TerminatorKind::DropAndReplace { ref location, .. } => {
321+
on_all_children_bits(tcx, mir, move_data,
322+
move_data.rev_lookup.find(location),
323+
|moi| callback(moi, DropFlagState::Present))
324+
}
325+
_ => {
326+
// other terminators do not contain move-ins
327+
}
328+
}
321329
}
322330
}
323331
}

src/librustc_mir/build/expr/stmt.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,29 +34,25 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
3434
let scope_id = this.innermost_scope_id();
3535
let lhs_span = lhs.span;
3636

37-
let lhs_ty = lhs.ty;
38-
let rhs_ty = rhs.ty;
39-
40-
let lhs_needs_drop = this.hir.needs_drop(lhs_ty);
41-
let rhs_needs_drop = this.hir.needs_drop(rhs_ty);
42-
4337
// Note: we evaluate assignments right-to-left. This
4438
// is better for borrowck interaction with overloaded
4539
// operators like x[j] = x[i].
4640

4741
// Generate better code for things that don't need to be
4842
// dropped.
49-
let rhs = if lhs_needs_drop || rhs_needs_drop {
50-
let op = unpack!(block = this.as_operand(block, rhs));
51-
Rvalue::Use(op)
43+
if this.hir.needs_drop(lhs.ty) {
44+
let rhs = unpack!(block = this.as_operand(block, rhs));
45+
let lhs = unpack!(block = this.as_lvalue(block, lhs));
46+
unpack!(block = this.build_drop_and_replace(
47+
block, lhs_span, lhs, rhs
48+
));
49+
block.unit()
5250
} else {
53-
unpack!(block = this.as_rvalue(block, rhs))
54-
};
55-
56-
let lhs = unpack!(block = this.as_lvalue(block, lhs));
57-
unpack!(block = this.build_drop(block, lhs_span, lhs.clone(), lhs_ty));
58-
this.cfg.push_assign(block, scope_id, expr_span, &lhs, rhs);
59-
block.unit()
51+
let rhs = unpack!(block = this.as_rvalue(block, rhs));
52+
let lhs = unpack!(block = this.as_lvalue(block, lhs));
53+
this.cfg.push_assign(block, scope_id, expr_span, &lhs, rhs);
54+
block.unit()
55+
}
6056
}
6157
ExprKind::AssignOp { op, lhs, rhs } => {
6258
// FIXME(#28160) there is an interesting semantics

src/librustc_mir/build/scope.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ struct DropData<'tcx> {
139139
span: Span,
140140

141141
/// lvalue to drop
142-
value: Lvalue<'tcx>,
142+
location: Lvalue<'tcx>,
143143

144144
/// The cached block for the cleanups-on-diverge path. This block
145145
/// contains code to run the current drop and all the preceding
@@ -402,7 +402,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
402402
// the drop that comes before it in the vector.
403403
scope.drops.push(DropData {
404404
span: span,
405-
value: lvalue.clone(),
405+
location: lvalue.clone(),
406406
cached_block: None
407407
});
408408
return;
@@ -497,7 +497,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
497497
pub fn build_drop(&mut self,
498498
block: BasicBlock,
499499
span: Span,
500-
value: Lvalue<'tcx>,
500+
location: Lvalue<'tcx>,
501501
ty: Ty<'tcx>) -> BlockAnd<()> {
502502
if !self.hir.needs_drop(ty) {
503503
return block.unit();
@@ -509,14 +509,35 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
509509
scope_id,
510510
span,
511511
TerminatorKind::Drop {
512-
value: value,
512+
location: location,
513513
target: next_target,
514514
unwind: diverge_target,
515515
});
516516
next_target.unit()
517517
}
518518

519519

520+
521+
pub fn build_drop_and_replace(&mut self,
522+
block: BasicBlock,
523+
span: Span,
524+
location: Lvalue<'tcx>,
525+
value: Operand<'tcx>) -> BlockAnd<()> {
526+
let scope_id = self.innermost_scope_id();
527+
let next_target = self.cfg.start_new_block();
528+
let diverge_target = self.diverge_cleanup();
529+
self.cfg.terminate(block,
530+
scope_id,
531+
span,
532+
TerminatorKind::DropAndReplace {
533+
location: location,
534+
value: value,
535+
target: next_target,
536+
unwind: diverge_target,
537+
});
538+
next_target.unit()
539+
}
540+
520541
// Panicking
521542
// =========
522543
// FIXME: should be moved into their own module
@@ -653,7 +674,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
653674
});
654675
let next = cfg.start_new_block();
655676
cfg.terminate(block, scope.id, drop_data.span, TerminatorKind::Drop {
656-
value: drop_data.value.clone(),
677+
location: drop_data.location.clone(),
657678
target: next,
658679
unwind: on_diverge
659680
});
@@ -709,7 +730,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
709730
scope.id,
710731
drop_data.span,
711732
TerminatorKind::Drop {
712-
value: drop_data.value.clone(),
733+
location: drop_data.location.clone(),
713734
target: target,
714735
unwind: None
715736
});

src/librustc_mir/transform/break_cleanup_edges.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ impl Pass for BreakCleanupEdges {}
105105
fn term_is_invoke(term: &Terminator) -> bool {
106106
match term.kind {
107107
TerminatorKind::Call { cleanup: Some(_), .. } |
108-
TerminatorKind::Drop { unwind: Some(_), .. } => true,
108+
// FIXME: not sure whether we need this one
109+
TerminatorKind::Drop { unwind: Some(_), .. } |
110+
TerminatorKind::DropAndReplace { .. } => true,
109111
_ => false
110112
}
111113
}

src/librustc_mir/transform/no_landing_pads.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
2929
TerminatorKind::SwitchInt { .. } => {
3030
/* nothing to do */
3131
},
32+
TerminatorKind::Call { cleanup: ref mut unwind, .. } |
33+
TerminatorKind::DropAndReplace { ref mut unwind, .. } |
3234
TerminatorKind::Drop { ref mut unwind, .. } => {
3335
unwind.take();
3436
},
35-
TerminatorKind::Call { ref mut cleanup, .. } => {
36-
cleanup.take();
37-
},
3837
}
3938
self.super_terminator(bb, terminator);
4039
}

src/librustc_mir/transform/promote_consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
399399
});
400400
let terminator = block.terminator_mut();
401401
match terminator.kind {
402-
TerminatorKind::Drop { value: Lvalue::Temp(index), target, .. } => {
402+
TerminatorKind::Drop { location: Lvalue::Temp(index), target, .. } => {
403403
if promoted(index) {
404404
terminator.kind = TerminatorKind::Goto {
405405
target: target

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
422422

423423
TerminatorKind::Switch {..} |
424424
TerminatorKind::SwitchInt {..} |
425+
TerminatorKind::DropAndReplace { .. } |
425426
TerminatorKind::Resume => None,
426427

427428
TerminatorKind::Return => {

src/librustc_mir/transform/type_check.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
363363
// no checks needed for these
364364
}
365365

366+
367+
TerminatorKind::DropAndReplace {
368+
ref location,
369+
ref value,
370+
..
371+
} => {
372+
let lv_ty = mir.lvalue_ty(tcx, location).to_ty(tcx);
373+
let rv_ty = mir.operand_ty(tcx, value);
374+
if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
375+
span_mirbug!(self, term, "bad DropAndReplace ({:?} = {:?}): {:?}",
376+
lv_ty, rv_ty, terr);
377+
}
378+
}
379+
366380
TerminatorKind::If { ref cond, .. } => {
367381
let cond_ty = mir.operand_ty(tcx, cond);
368382
match cond_ty.sty {

src/librustc_trans/mir/block.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
143143
})
144144
}
145145

146-
mir::TerminatorKind::Drop { ref value, target, unwind } => {
147-
let lvalue = self.trans_lvalue(&bcx, value);
146+
mir::TerminatorKind::Drop { ref location, target, unwind } => {
147+
let lvalue = self.trans_lvalue(&bcx, location);
148148
let ty = lvalue.ty.to_ty(bcx.tcx());
149149
// Double check for necessity to drop
150150
if !glue::type_needs_drop(bcx.tcx(), ty) {
@@ -177,6 +177,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
177177
}
178178
}
179179

180+
mir::TerminatorKind::DropAndReplace { .. } => {
181+
bug!("undesugared DropAndReplace in trans: {:?}", data);
182+
}
183+
180184
mir::TerminatorKind::Call { ref func, ref args, ref destination, ref cleanup } => {
181185
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
182186
let callee = self.trans_operand(&bcx, func);

0 commit comments

Comments
 (0)