Skip to content

Commit d94a901

Browse files
Implement a non-dataflow, temp-only Qualif resolver
1 parent 808bede commit d94a901

File tree

1 file changed

+114
-30
lines changed

1 file changed

+114
-30
lines changed

src/librustc_mir/transform/qualify_consts.rs

+114-30
Original file line numberDiff line numberDiff line change
@@ -697,16 +697,16 @@ macro_rules! define_qualifs {
697697
( $( $Q:ident, $field:ident );* $(;)? ) => {
698698
$(
699699
impl Index<$Q> for Resolvers<'mir, 'tcx> {
700-
type Output = FlowSensitiveResolver<'mir, 'tcx, $Q>;
700+
type Output = dyn 'mir + QualifResolver<'tcx, $Q>;
701701

702702
fn index(&self, _: $Q) -> &Self::Output {
703-
&self.$field
703+
&*self.$field
704704
}
705705
}
706706

707707
impl IndexMut<$Q> for Resolvers<'mir, 'tcx> {
708708
fn index_mut(&mut self, _: $Q) -> &mut Self::Output {
709-
&mut self.$field
709+
&mut *self.$field
710710
}
711711
}
712712
)*
@@ -840,10 +840,10 @@ trait QualifResolver<'tcx, Q>: Visitor<'tcx> {
840840
/// `resolvers[NeedsDrop]`). This chicanery makes the use of macros like `for_each_qualif` more
841841
/// convenient.
842842
pub struct Resolvers<'mir, 'tcx> {
843-
needs_drop: FlowSensitiveResolver<'mir, 'tcx, NeedsDrop>,
844-
has_mut_interior: FlowSensitiveResolver<'mir, 'tcx, HasMutInterior>,
845-
is_not_promotable: FlowSensitiveResolver<'mir, 'tcx, IsNotPromotable>,
846-
is_not_implicitly_promotable: FlowSensitiveResolver<'mir, 'tcx, IsNotImplicitlyPromotable>,
843+
needs_drop: Box<dyn 'mir + QualifResolver<'tcx, NeedsDrop>>,
844+
has_mut_interior: Box<dyn 'mir + QualifResolver<'tcx, HasMutInterior>>,
845+
is_not_promotable: Box<dyn 'mir + QualifResolver<'tcx, IsNotPromotable>>,
846+
is_not_implicitly_promotable: Box<dyn 'mir + QualifResolver<'tcx, IsNotImplicitlyPromotable>>,
847847
}
848848

849849
impl Resolvers<'mir, 'tcx> {
@@ -867,34 +867,52 @@ impl Resolvers<'mir, 'tcx> {
867867
let borrowed_locals = dataflow::DataflowResultsCursor::new(borrowed_locals, cx.body);
868868
let borrowed_locals = Rc::new(RefCell::new(borrowed_locals));
869869

870-
let needs_drop = FlowSensitiveResolver::new(
871-
NeedsDrop,
872-
cx,
873-
borrowed_locals.clone(),
874-
temp_promotion_state,
875-
&dead_unwinds,
876-
);
877-
let has_mut_interior = FlowSensitiveResolver::new(
878-
HasMutInterior,
879-
cx,
880-
borrowed_locals.clone(),
881-
temp_promotion_state,
882-
&dead_unwinds,
883-
);
884-
let is_not_promotable = FlowSensitiveResolver::new(
870+
let needs_drop = if cx.mode == Mode::NonConstFn {
871+
Box::new(TempOnlyResolver::new(
872+
NeedsDrop,
873+
cx,
874+
borrowed_locals.clone(),
875+
temp_promotion_state,
876+
)) as Box<_>
877+
} else {
878+
Box::new(FlowSensitiveResolver::new(
879+
NeedsDrop,
880+
cx,
881+
borrowed_locals.clone(),
882+
temp_promotion_state,
883+
&dead_unwinds,
884+
)) as Box<_>
885+
};
886+
887+
let has_mut_interior = if cx.mode == Mode::NonConstFn {
888+
Box::new(TempOnlyResolver::new(
889+
HasMutInterior,
890+
cx,
891+
borrowed_locals.clone(),
892+
temp_promotion_state,
893+
)) as Box<_>
894+
} else {
895+
Box::new(FlowSensitiveResolver::new(
896+
HasMutInterior,
897+
cx,
898+
borrowed_locals.clone(),
899+
temp_promotion_state,
900+
&dead_unwinds,
901+
)) as Box<_>
902+
};
903+
904+
let is_not_promotable = Box::new(TempOnlyResolver::new(
885905
IsNotPromotable,
886906
cx,
887907
borrowed_locals.clone(),
888908
temp_promotion_state,
889-
&dead_unwinds,
890-
);
891-
let is_not_implicitly_promotable = FlowSensitiveResolver::new(
909+
));
910+
let is_not_implicitly_promotable = Box::new(TempOnlyResolver::new(
892911
IsNotImplicitlyPromotable,
893912
cx,
894913
borrowed_locals.clone(),
895914
temp_promotion_state,
896-
&dead_unwinds,
897-
);
915+
));
898916

899917
Resolvers {
900918
needs_drop,
@@ -905,6 +923,72 @@ impl Resolvers<'mir, 'tcx> {
905923
}
906924
}
907925

926+
struct TempOnlyResolver<'mir, 'tcx, Q> {
927+
cx: ConstCx<'mir, 'tcx>,
928+
borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>,
929+
per_local: BitSet<Local>,
930+
_qualif: PhantomData<Q>,
931+
}
932+
933+
impl<Q> TempOnlyResolver<'mir, 'tcx, Q>
934+
where
935+
Q: Qualif,
936+
{
937+
fn new(
938+
_: Q,
939+
cx: &ConstCx<'mir, 'tcx>,
940+
borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>,
941+
temp_promotion_state: &IndexVec<Local, TempState>,
942+
) -> Self {
943+
let mut per_local = BitSet::new_empty(cx.body.local_decls.len());
944+
initialize_qualifs::<Q>(&mut per_local, cx, temp_promotion_state);
945+
946+
TempOnlyResolver {
947+
cx: (*cx).clone(),
948+
borrowed_locals,
949+
per_local,
950+
_qualif: PhantomData,
951+
}
952+
}
953+
}
954+
955+
956+
impl<Q> Visitor<'tcx> for TempOnlyResolver<'_, 'tcx, Q>
957+
where
958+
Q: Qualif
959+
{
960+
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
961+
QualifPropagator::<Q>::new(&self.cx, &mut self.per_local, &self.borrowed_locals)
962+
.visit_statement(statement, location);
963+
}
964+
965+
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
966+
QualifPropagator::<Q>::new(&self.cx, &mut self.per_local, &self.borrowed_locals)
967+
.visit_terminator(terminator, location);
968+
969+
if let mir::TerminatorKind::Call {
970+
destination: Some((return_place, _)),
971+
func,
972+
args,
973+
..
974+
} = &terminator.kind {
975+
let return_ty = return_place.ty(self.cx.body, self.cx.tcx).ty;
976+
let in_call = Q::in_call(&self.cx, &mut self.per_local, func, args, return_ty);
977+
QualifPropagator::<Q>::new(&self.cx, &mut self.per_local, &self.borrowed_locals)
978+
.assign_qualif(return_place, in_call, location);
979+
}
980+
}
981+
}
982+
983+
impl<Q> QualifResolver<'tcx, Q> for TempOnlyResolver<'_, 'tcx, Q>
984+
where
985+
Q: Qualif
986+
{
987+
fn get(&mut self) -> &BitSet<Local> {
988+
&self.per_local
989+
}
990+
}
991+
908992
struct FlowSensitiveResolver<'mir, 'tcx, Q>
909993
where
910994
Q: Qualif
@@ -1116,9 +1200,8 @@ where
11161200
borrowed_locals.seek(location);
11171201

11181202
for local in borrowed_locals.get().iter() {
1119-
// FIXME: This is unsound. Mutable borrows can still mutate types that aren't `Freeze`.
11201203
let ty = self.cx.body.local_decls[local].ty;
1121-
if !ty.is_freeze(self.cx.tcx, self.cx.param_env, DUMMY_SP) {
1204+
if Q::in_any_value_of_ty(&self.cx, ty).unwrap_or(true) {
11221205
self.qualifs_per_local.insert(local);
11231206
}
11241207
}
@@ -2220,7 +2303,8 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet<Local>) {
22202303
return (1 << IsNotPromotable::IDX, tcx.arena.alloc(BitSet::new_empty(0)));
22212304
}
22222305

2223-
Checker::new(tcx, def_id, body, Mode::Const).check_const()
2306+
let mut checker = Checker::new(tcx, def_id, body, Mode::Const);
2307+
checker.check_const()
22242308
}
22252309

22262310
pub struct QualifyAndPromoteConstants<'tcx> {

0 commit comments

Comments
 (0)