Skip to content

Commit 111324e

Browse files
committed
Prevent registration inside references if target is !Freeze
1 parent 4478a87 commit 111324e

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed

compiler/rustc_middle/src/ty/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ impl<'tcx> Ty<'tcx> {
849849
///
850850
/// Returning true means the type is known to be `Freeze`. Returning
851851
/// `false` means nothing -- could be `Freeze`, might not be.
852-
pub fn is_trivially_freeze(self) -> bool {
852+
fn is_trivially_freeze(self) -> bool {
853853
match self.kind() {
854854
ty::Int(_)
855855
| ty::Uint(_)

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ use rustc_index::vec::IndexVec;
7272
use rustc_middle::mir::tcx::PlaceTy;
7373
use rustc_middle::mir::*;
7474
use rustc_middle::ty::{self, Ty, TyCtxt};
75+
use rustc_span::DUMMY_SP;
7576
use rustc_target::abi::VariantIdx;
7677

7778
use crate::{
@@ -550,7 +551,7 @@ pub struct Map {
550551
}
551552

552553
impl Map {
553-
pub fn new() -> Self {
554+
fn new() -> Self {
554555
Self {
555556
locals: IndexVec::new(),
556557
projections: FxHashMap::default(),
@@ -559,23 +560,35 @@ impl Map {
559560
}
560561
}
561562

562-
/// Register all places with suitable types up to a certain derefence depth (to prevent cycles).
563-
pub fn register_with_filter<'tcx>(
563+
/// Register all suitable places with matching types (up to a certain depth).
564+
pub fn from_filter<'tcx>(
565+
tcx: TyCtxt<'tcx>,
566+
body: &Body<'tcx>,
567+
filter: impl FnMut(Ty<'tcx>) -> bool,
568+
) -> Self {
569+
let mut map = Self::new();
570+
map.register_with_filter(tcx, body, 3, filter);
571+
map
572+
}
573+
574+
fn register_with_filter<'tcx>(
564575
&mut self,
565576
tcx: TyCtxt<'tcx>,
566-
source: &impl HasLocalDecls<'tcx>,
577+
body: &Body<'tcx>,
567578
max_derefs: u32,
568579
mut filter: impl FnMut(Ty<'tcx>) -> bool,
569580
) {
581+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
570582
let mut projection = Vec::new();
571-
for (local, decl) in source.local_decls().iter_enumerated() {
583+
for (local, decl) in body.local_decls.iter_enumerated() {
572584
self.register_with_filter_rec(
573585
tcx,
574586
max_derefs,
575587
local,
576588
&mut projection,
577589
decl.ty,
578590
&mut filter,
591+
param_env,
579592
);
580593
}
581594
}
@@ -588,16 +601,28 @@ impl Map {
588601
projection: &mut Vec<PlaceElem<'tcx>>,
589602
ty: Ty<'tcx>,
590603
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
604+
param_env: ty::ParamEnv<'tcx>,
591605
) {
592606
if filter(ty) {
593607
// This might fail if `ty` is not scalar.
594608
let _ = self.register_with_ty(local, projection, ty);
595609
}
596610
if max_derefs > 0 {
597-
if let Some(ty::TypeAndMut { ty, .. }) = ty.builtin_deref(false) {
598-
projection.push(PlaceElem::Deref);
599-
self.register_with_filter_rec(tcx, max_derefs - 1, local, projection, ty, filter);
600-
projection.pop();
611+
if let Some(ty::TypeAndMut { ty: deref_ty, .. }) = ty.builtin_deref(false) {
612+
// References can only be tracked if the target is `!Freeze`.
613+
if deref_ty.is_freeze(tcx.at(DUMMY_SP), param_env) {
614+
projection.push(PlaceElem::Deref);
615+
self.register_with_filter_rec(
616+
tcx,
617+
max_derefs - 1,
618+
local,
619+
projection,
620+
deref_ty,
621+
filter,
622+
param_env,
623+
);
624+
projection.pop();
625+
}
601626
}
602627
}
603628
iter_fields(ty, tcx, |variant, field, ty| {
@@ -606,7 +631,9 @@ impl Map {
606631
return;
607632
}
608633
projection.push(PlaceElem::Field(field, ty));
609-
self.register_with_filter_rec(tcx, max_derefs, local, projection, ty, filter);
634+
self.register_with_filter_rec(
635+
tcx, max_derefs, local, projection, ty, filter, param_env,
636+
);
610637
projection.pop();
611638
});
612639
}
@@ -639,7 +666,8 @@ impl Map {
639666
Ok(index)
640667
}
641668

642-
pub fn register<'tcx>(
669+
#[allow(unused)]
670+
fn register<'tcx>(
643671
&mut self,
644672
local: Local,
645673
projection: &[PlaceElem<'tcx>],
@@ -671,12 +699,6 @@ impl Map {
671699
return Err(());
672700
}
673701

674-
if !ty.is_trivially_freeze() {
675-
// Due to the way we deal with shared references, only `Freeze` types may be tracked.
676-
// We are a little bit to restrictive here by only allowing trivially `Freeze` types.
677-
return Err(());
678-
}
679-
680702
let place = self.make_place(local, projection)?;
681703

682704
// Allocate a value slot if it doesn't have one.

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
2121

2222
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
2323
// Decide which places to track during the analysis.
24-
let mut map = Map::new();
25-
map.register_with_filter(tcx, body, 3, |ty| ty.is_scalar() && !ty.is_unsafe_ptr());
24+
let map = Map::from_filter(tcx, body, |ty| ty.is_scalar() && !ty.is_unsafe_ptr());
2625

2726
// Perform the actual dataflow analysis.
2827
let analysis = ConstAnalysis::new(tcx, body, map);

0 commit comments

Comments
 (0)