@@ -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.
842842pub 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
849849impl 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+
908992struct FlowSensitiveResolver < ' mir , ' tcx , Q >
909993where
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
22262310pub struct QualifyAndPromoteConstants < ' tcx > {
0 commit comments