77//! but we still need to do bounds checking and adjust the layout. To not duplicate that with MPlaceTy, we actually
88//! implement the logic on OpTy, and MPlaceTy calls that.
99
10+ use std:: marker:: PhantomData ;
11+ use std:: ops:: Range ;
12+
1013use rustc_middle:: mir;
1114use rustc_middle:: ty;
1215use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
1316use rustc_middle:: ty:: Ty ;
14- use rustc_middle:: ty:: TyCtxt ;
15- use rustc_target:: abi:: HasDataLayout ;
1617use rustc_target:: abi:: Size ;
1718use rustc_target:: abi:: { self , VariantIdx } ;
1819
@@ -24,44 +25,42 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
2425 fn layout ( & self ) -> TyAndLayout < ' tcx > ;
2526
2627 /// Get the metadata of a wide value.
27- fn meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
28- & self ,
29- ecx : & InterpCx < ' mir , ' tcx , M > ,
30- ) -> InterpResult < ' tcx , MemPlaceMeta < M :: Provenance > > ;
28+ fn meta ( & self ) -> InterpResult < ' tcx , MemPlaceMeta < Prov > > ;
3129
3230 fn len < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
3331 & self ,
3432 ecx : & InterpCx < ' mir , ' tcx , M > ,
3533 ) -> InterpResult < ' tcx , u64 > {
36- self . meta ( ecx ) ?. len ( self . layout ( ) , ecx)
34+ self . meta ( ) ?. len ( self . layout ( ) , ecx)
3735 }
3836
3937 /// Offset the value by the given amount, replacing the layout and metadata.
40- fn offset_with_meta (
38+ fn offset_with_meta < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
4139 & self ,
4240 offset : Size ,
4341 meta : MemPlaceMeta < Prov > ,
4442 layout : TyAndLayout < ' tcx > ,
45- cx : & impl HasDataLayout ,
43+ ecx : & InterpCx < ' mir , ' tcx , M > ,
4644 ) -> InterpResult < ' tcx , Self > ;
4745
48- fn offset (
46+ fn offset < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
4947 & self ,
5048 offset : Size ,
5149 layout : TyAndLayout < ' tcx > ,
52- cx : & impl HasDataLayout ,
50+ ecx : & InterpCx < ' mir , ' tcx , M > ,
5351 ) -> InterpResult < ' tcx , Self > {
5452 assert ! ( layout. is_sized( ) ) ;
55- self . offset_with_meta ( offset, MemPlaceMeta :: None , layout, cx )
53+ self . offset_with_meta ( offset, MemPlaceMeta :: None , layout, ecx )
5654 }
5755
58- fn transmute (
56+ fn transmute < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
5957 & self ,
6058 layout : TyAndLayout < ' tcx > ,
61- cx : & impl HasDataLayout ,
59+ ecx : & InterpCx < ' mir , ' tcx , M > ,
6260 ) -> InterpResult < ' tcx , Self > {
61+ assert ! ( self . layout( ) . is_sized( ) && layout. is_sized( ) ) ;
6362 assert_eq ! ( self . layout( ) . size, layout. size) ;
64- self . offset_with_meta ( Size :: ZERO , MemPlaceMeta :: None , layout, cx )
63+ self . offset_with_meta ( Size :: ZERO , MemPlaceMeta :: None , layout, ecx )
6564 }
6665
6766 /// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for
@@ -72,6 +71,28 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
7271 ) -> InterpResult < ' tcx , OpTy < ' tcx , M :: Provenance > > ;
7372}
7473
74+ /// A type representing iteration over the elements of an array.
75+ pub struct ArrayIterator < ' tcx , ' a , Prov : Provenance + ' static , P : Projectable < ' tcx , Prov > > {
76+ base : & ' a P ,
77+ range : Range < u64 > ,
78+ stride : Size ,
79+ field_layout : TyAndLayout < ' tcx > ,
80+ _phantom : PhantomData < Prov > , // otherwise it says `Prov` is never used...
81+ }
82+
83+ impl < ' tcx , ' a , Prov : Provenance + ' static , P : Projectable < ' tcx , Prov > >
84+ ArrayIterator < ' tcx , ' a , Prov , P >
85+ {
86+ /// Should be the same `ecx` on each call, and match the one used to create the iterator.
87+ pub fn next < ' mir , M : Machine < ' mir , ' tcx , Provenance = Prov > > (
88+ & mut self ,
89+ ecx : & InterpCx < ' mir , ' tcx , M > ,
90+ ) -> InterpResult < ' tcx , Option < ( u64 , P ) > > {
91+ let Some ( idx) = self . range . next ( ) else { return Ok ( None ) } ;
92+ Ok ( Some ( ( idx, self . base . offset ( self . stride * idx, self . field_layout , ecx) ?) ) )
93+ }
94+ }
95+
7596// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
7697impl < ' mir , ' tcx : ' mir , Prov , M > InterpCx < ' mir , ' tcx , M >
7798where
@@ -104,7 +125,7 @@ where
104125 // But const-prop actually feeds us such nonsense MIR! (see test `const_prop/issue-86351.rs`)
105126 throw_inval ! ( ConstPropNonsense ) ;
106127 }
107- let base_meta = base. meta ( self ) ?;
128+ let base_meta = base. meta ( ) ?;
108129 // Re-use parent metadata to determine dynamic field layout.
109130 // With custom DSTS, this *will* execute user-defined code, but the same
110131 // happens at run-time so that's okay.
@@ -132,7 +153,7 @@ where
132153 base : & P ,
133154 variant : VariantIdx ,
134155 ) -> InterpResult < ' tcx , P > {
135- assert ! ( !base. meta( self ) ?. has_meta( ) ) ;
156+ assert ! ( !base. meta( ) ?. has_meta( ) ) ;
136157 // Downcasts only change the layout.
137158 // (In particular, no check about whether this is even the active variant -- that's by design,
138159 // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)
@@ -206,20 +227,13 @@ where
206227 pub fn project_array_fields < ' a , P : Projectable < ' tcx , M :: Provenance > > (
207228 & self ,
208229 base : & ' a P ,
209- ) -> InterpResult < ' tcx , impl Iterator < Item = InterpResult < ' tcx , P > > + ' a >
210- where
211- ' tcx : ' a ,
212- {
230+ ) -> InterpResult < ' tcx , ArrayIterator < ' tcx , ' a , M :: Provenance , P > > {
213231 let abi:: FieldsShape :: Array { stride, .. } = base. layout ( ) . fields else {
214232 span_bug ! ( self . cur_span( ) , "operand_array_fields: expected an array layout" ) ;
215233 } ;
216234 let len = base. len ( self ) ?;
217235 let field_layout = base. layout ( ) . field ( self , 0 ) ;
218- let tcx: TyCtxt < ' tcx > = * self . tcx ;
219- // `Size` multiplication
220- Ok ( ( 0 ..len) . map ( move |i| {
221- base. offset_with_meta ( stride * i, MemPlaceMeta :: None , field_layout, & tcx)
222- } ) )
236+ Ok ( ArrayIterator { base, range : 0 ..len, stride, field_layout, _phantom : PhantomData } )
223237 }
224238
225239 /// Subslicing
0 commit comments