@@ -125,20 +125,32 @@ extension Value {
125125 return true
126126 }
127127
128+ /// Project out a sub-field of this value according to `path`.
129+ /// If this is an "owned" value the result is an "owned" value which forwards the original value.
130+ /// This only works if _all_ non-trivial fields are projected. Otherwise some non-trivial results of
131+ /// `destructure_struct` or `destructure_tuple` will be leaked.
128132 func createProjection( path: SmallProjectionPath , builder: Builder ) -> Value {
129133 let ( kind, index, subPath) = path. pop ( )
134+ let result : Value
130135 switch kind {
131136 case . root:
132137 return self
133138 case . structField:
134- let structExtract = builder. createStructExtract ( struct: self , fieldIndex: index)
135- return structExtract. createProjection ( path: subPath, builder: builder)
139+ if ownership == . owned {
140+ result = builder. createDestructureStruct ( struct: self ) . results [ index]
141+ } else {
142+ result = builder. createStructExtract ( struct: self , fieldIndex: index)
143+ }
136144 case . tupleField:
137- let tupleExtract = builder. createTupleExtract ( tuple: self , elementIndex: index)
138- return tupleExtract. createProjection ( path: subPath, builder: builder)
145+ if ownership == . owned {
146+ result = builder. createDestructureTuple ( tuple: self ) . results [ index]
147+ } else {
148+ result = builder. createTupleExtract ( tuple: self , elementIndex: index)
149+ }
139150 default :
140151 fatalError ( " path is not materializable " )
141152 }
153+ return result. createProjection ( path: subPath, builder: builder)
142154 }
143155
144156 func createAddressProjection( path: SmallProjectionPath , builder: Builder ) -> Value {
0 commit comments