@@ -125,20 +125,32 @@ extension Value {
125
125
return true
126
126
}
127
127
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.
128
132
func createProjection( path: SmallProjectionPath , builder: Builder ) -> Value {
129
133
let ( kind, index, subPath) = path. pop ( )
134
+ let result : Value
130
135
switch kind {
131
136
case . root:
132
137
return self
133
138
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
+ }
136
144
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
+ }
139
150
default :
140
151
fatalError ( " path is not materializable " )
141
152
}
153
+ return result. createProjection ( path: subPath, builder: builder)
142
154
}
143
155
144
156
func createAddressProjection( path: SmallProjectionPath , builder: Builder ) -> Value {
0 commit comments