@@ -183,21 +183,16 @@ impl ConstValue {
183183
184184 /// Check if a constant may contain provenance information. This is used by MIR opts.
185185 /// Can return `true` even if there is no provenance.
186- pub fn may_have_provenance ( & self , tcx : TyCtxt < ' _ > , size : Size ) -> bool {
186+ pub fn may_have_provenance ( & self , tcx : TyCtxt < ' _ > , size : Option < Size > ) -> bool {
187187 match * self {
188188 ConstValue :: ZeroSized | ConstValue :: Scalar ( Scalar :: Int ( _) ) => return false ,
189- ConstValue :: Scalar ( Scalar :: Ptr ( ..) ) => return true ,
190- // It's hard to find out the part of the allocation we point to;
191- // just conservatively check everything.
192- ConstValue :: Slice { alloc_id, meta : _ } => {
193- !tcx. global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) . provenance ( ) . ptrs ( ) . is_empty ( )
189+ ConstValue :: Scalar ( Scalar :: Ptr ( ..) ) | ConstValue :: Slice { .. } => return true ,
190+ ConstValue :: Indirect { alloc_id, offset } => {
191+ let allocation = tcx. global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) ;
192+ let end = if let Some ( size) = size { offset + size } else { allocation. size ( ) } ;
193+ let provenance_map = allocation. provenance ( ) ;
194+ !provenance_map. range_empty ( AllocRange :: from ( offset..end) , & tcx)
194195 }
195- ConstValue :: Indirect { alloc_id, offset } => !tcx
196- . global_alloc ( alloc_id)
197- . unwrap_memory ( )
198- . inner ( )
199- . provenance ( )
200- . range_empty ( AllocRange :: from ( offset..offset + size) , & tcx) ,
201196 }
202197 }
203198
@@ -490,35 +485,26 @@ impl<'tcx> Const<'tcx> {
490485 Self :: Val ( val, ty)
491486 }
492487
493- /// Return true if any evaluation of this constant always returns the same value,
494- /// taking into account even pointer identity tests.
488+ /// Return true if any evaluation of this constant in the same MIR body
489+ /// always returns the same value, taking into account even pointer identity tests.
490+ ///
491+ /// In other words, this answers: is "cloning" the mir::ConstOperand ok?
495492 pub fn is_deterministic ( & self ) -> bool {
496493 // Primitive types cannot contain provenance and always have the same value.
497494 if self . ty ( ) . is_primitive ( ) {
498495 return true ;
499496 }
500497
501- // Some constants may generate fresh allocations for pointers they contain,
502- // so using the same constant twice can yield two different results.
503- // Notably, valtrees purposefully generate new allocations.
504498 match self {
505- Const :: Ty ( _, c) => match c. kind ( ) {
506- ty:: ConstKind :: Param ( ..) => true ,
507- // A valtree may be a reference. Valtree references correspond to a
508- // different allocation each time they are evaluated. Valtrees for primitive
509- // types are fine though.
510- ty:: ConstKind :: Value ( ..)
511- | ty:: ConstKind :: Expr ( ..)
512- | ty:: ConstKind :: Unevaluated ( ..)
513- // This can happen if evaluation of a constant failed. The result does not matter
514- // much since compilation is doomed.
515- | ty:: ConstKind :: Error ( ..) => false ,
516- // Should not appear in runtime MIR.
517- ty:: ConstKind :: Infer ( ..)
518- | ty:: ConstKind :: Bound ( ..)
519- | ty:: ConstKind :: Placeholder ( ..) => bug ! ( ) ,
520- } ,
499+ // Some constants may generate fresh allocations for pointers they contain,
500+ // so using the same constant twice can yield two different results.
501+ // Notably, valtrees purposefully generate new allocations.
502+ Const :: Ty ( ..) => false ,
503+ // We do not know the contents, so don't attempt to do anything clever.
521504 Const :: Unevaluated ( ..) => false ,
505+ // When an evaluated contant contains provenance, it is encoded as an `AllocId`.
506+ // Cloning the constant will reuse the same `AllocId`. If this is in the same MIR
507+ // body, this same `AllocId` will result in the same pointer in codegen.
522508 Const :: Val ( ..) => true ,
523509 }
524510 }
0 commit comments