Skip to content

Commit 841f0e7

Browse files
authored
Rollup merge of rust-lang#78577 - tmiasko:validate-aliasing, r=jonas-schievink
validator: Extend aliasing check to a call terminator
2 parents c0f356d + b816e5d commit 841f0e7

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

compiler/rustc_mir/src/transform/validate.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::mir::{
1010
visit::{PlaceContext, Visitor},
1111
};
1212
use rustc_middle::mir::{
13-
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
14-
SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
13+
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
14+
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
1515
};
1616
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
1717
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
@@ -46,8 +46,16 @@ impl<'tcx> MirPass<'tcx> for Validator {
4646
.iterate_to_fixpoint()
4747
.into_results_cursor(body);
4848

49-
TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness }
50-
.visit_body(body);
49+
TypeChecker {
50+
when: &self.when,
51+
body,
52+
tcx,
53+
param_env,
54+
mir_phase,
55+
storage_liveness,
56+
place_cache: Vec::new(),
57+
}
58+
.visit_body(body);
5159
}
5260
}
5361

@@ -150,6 +158,7 @@ struct TypeChecker<'a, 'tcx> {
150158
param_env: ParamEnv<'tcx>,
151159
mir_phase: MirPhase,
152160
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
161+
place_cache: Vec<PlaceRef<'tcx>>,
153162
}
154163

155164
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
@@ -391,7 +400,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
391400
self.check_edge(location, *unwind, EdgeKind::Unwind);
392401
}
393402
}
394-
TerminatorKind::Call { func, destination, cleanup, .. } => {
403+
TerminatorKind::Call { func, args, destination, cleanup, .. } => {
395404
let func_ty = func.ty(&self.body.local_decls, self.tcx);
396405
match func_ty.kind() {
397406
ty::FnPtr(..) | ty::FnDef(..) => {}
@@ -406,6 +415,32 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
406415
if let Some(cleanup) = cleanup {
407416
self.check_edge(location, *cleanup, EdgeKind::Unwind);
408417
}
418+
419+
// The call destination place and Operand::Move place used as an argument might be
420+
// passed by a reference to the callee. Consequently they must be non-overlapping.
421+
// Currently this simply checks for duplicate places.
422+
self.place_cache.clear();
423+
if let Some((destination, _)) = destination {
424+
self.place_cache.push(destination.as_ref());
425+
}
426+
for arg in args {
427+
if let Operand::Move(place) = arg {
428+
self.place_cache.push(place.as_ref());
429+
}
430+
}
431+
let all_len = self.place_cache.len();
432+
self.place_cache.sort_unstable();
433+
self.place_cache.dedup();
434+
let has_duplicates = all_len != self.place_cache.len();
435+
if has_duplicates {
436+
self.fail(
437+
location,
438+
format!(
439+
"encountered overlapping memory in `Call` terminator: {:?}",
440+
terminator.kind,
441+
),
442+
);
443+
}
409444
}
410445
TerminatorKind::Assert { cond, target, cleanup, .. } => {
411446
let cond_ty = cond.ty(&self.body.local_decls, self.tcx);

0 commit comments

Comments
 (0)