diff options
| author | Ralf Jung <post@ralfj.de> | 2017-07-20 15:27:03 -0700 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2017-07-30 01:11:59 -0700 |
| commit | 511b88cdce696d04522aa27a741c4033d54e0bef (patch) | |
| tree | 88a7306c30bad4b8d800c258d993fe2e7dc02e2d /src | |
| parent | 24a2ac9e468a18913e5238475db57f7404a37bc5 (diff) | |
| download | rust-511b88cdce696d04522aa27a741c4033d54e0bef.tar.gz rust-511b88cdce696d04522aa27a741c4033d54e0bef.zip | |
only emit Suspend validation for mutable paths
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/transform/add_validation.rs | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs index dacc267612f..b79c1a2d6fd 100644 --- a/src/librustc_mir/transform/add_validation.rs +++ b/src/librustc_mir/transform/add_validation.rs @@ -20,6 +20,33 @@ use rustc::mir::transform::{MirPass, MirSource}; pub struct AddValidation; + +fn is_lvalue_shared<'a, 'tcx, D>(lval: &Lvalue<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool + where D: HasLocalDecls<'tcx> +{ + use rustc::mir::Lvalue::*; + + match *lval { + Local { .. } => false, + Static(_) => true, + Projection(ref proj) => { + // If the base is shared, things stay shared + if is_lvalue_shared(&proj.base, local_decls, tcx) { + return true; + } + // A Deref projection may make things shared + match proj.elem { + ProjectionElem::Deref => { + // Computing the inside the recursion makes this quadratic. We don't expect deep paths though. + let ty = proj.base.ty(local_decls, tcx).to_ty(tcx); + !ty.is_mutable_pointer() + } + _ => false, + } + } + } +} + impl MirPass for AddValidation { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -117,18 +144,20 @@ impl MirPass for AddValidation { }; block_data.statements.insert(i+1, acquire_stmt); - // The source is released until the region of the borrow ends. - let src_ty = src_lval.ty(&local_decls, tcx).to_ty(tcx); - let op = match re { - &RegionKind::ReScope(ce) => ValidationOp::Suspend(ce), - &RegionKind::ReErased => bug!("AddValidation pass must be run before erasing lifetimes"), - _ => ValidationOp::Release, - }; - let release_stmt = Statement { - source_info: block_data.statements[i].source_info, - kind: StatementKind::Validate(op, vec![(src_ty, src_lval)]), - }; - block_data.statements.insert(i, release_stmt); + // The source is released until the region of the borrow ends -- but not if it is shared. + if !is_lvalue_shared(&src_lval, &local_decls, tcx) { + let src_ty = src_lval.ty(&local_decls, tcx).to_ty(tcx); + let op = match re { + &RegionKind::ReScope(ce) => ValidationOp::Suspend(ce), + &RegionKind::ReErased => bug!("AddValidation pass must be run before erasing lifetimes"), + _ => ValidationOp::Release, + }; + let release_stmt = Statement { + source_info: block_data.statements[i].source_info, + kind: StatementKind::Validate(op, vec![(src_ty, src_lval)]), + }; + block_data.statements.insert(i, release_stmt); + } } } } |
