Skip to content

Commit ed92538

Browse files
authored
Fix type morphing of nested tuples (#1756)
* Fix type morphing of nested tuples - use downstream morphed sub-types to compose final element type * Better unit tests for tuple morphing
1 parent a469402 commit ed92538

File tree

2 files changed

+88
-3
lines changed

2 files changed

+88
-3
lines changed

manifest/morph/morph.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ func morphTupleIntoType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePat
186186
return tftypes.Value{}, elp.NewErrorf("[%s] failed to morph tuple element into tuple element: %v", elp.String(), err)
187187
}
188188
lvals[i] = nv
189+
eltypes[i] = nv.Type()
189190
}
190191
return tftypes.NewValue(tftypes.Tuple{ElementTypes: eltypes}, lvals), nil
191192
case t.Is(tftypes.List{}):

manifest/morph/morph_test.go

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func TestMorphValueToType(t *testing.T) {
139139
}),
140140
T: tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.DynamicPseudoType}},
141141
},
142-
Out: tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.DynamicPseudoType, tftypes.DynamicPseudoType, tftypes.DynamicPseudoType}}, []tftypes.Value{
142+
Out: tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.String, tftypes.String, tftypes.String}}, []tftypes.Value{
143143
tftypes.NewValue(tftypes.String, "foo"),
144144
tftypes.NewValue(tftypes.String, "bar"),
145145
tftypes.NewValue(tftypes.String, "baz"),
@@ -201,6 +201,90 @@ func TestMorphValueToType(t *testing.T) {
201201
map[string]tftypes.Value{"foo": tftypes.NewValue(tftypes.String, "baz")}),
202202
}),
203203
},
204+
"tuple(object)->tuple(object)": {
205+
In: sampleInType{
206+
V: tftypes.NewValue(
207+
tftypes.Tuple{ElementTypes: []tftypes.Type{
208+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"first": tftypes.String}},
209+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"second": tftypes.DynamicPseudoType}},
210+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"third": tftypes.Tuple{ElementTypes: []tftypes.Type{
211+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String}},
212+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"bar": tftypes.String}},
213+
}},
214+
}},
215+
}},
216+
[]tftypes.Value{
217+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"first": tftypes.String}},
218+
map[string]tftypes.Value{"first": tftypes.NewValue(tftypes.String, "foo")}),
219+
220+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"second": tftypes.DynamicPseudoType}},
221+
map[string]tftypes.Value{"second": tftypes.NewValue(tftypes.DynamicPseudoType, nil)}),
222+
223+
tftypes.NewValue(
224+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{
225+
"third": tftypes.Tuple{ElementTypes: []tftypes.Type{
226+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String}},
227+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"bar": tftypes.String}},
228+
}},
229+
}},
230+
map[string]tftypes.Value{
231+
"third": tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{
232+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String}},
233+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"bar": tftypes.String}},
234+
}}, []tftypes.Value{
235+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String}}, map[string]tftypes.Value{"foo": tftypes.NewValue(tftypes.String, "some")}),
236+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"bar": tftypes.String}}, map[string]tftypes.Value{"bar": tftypes.NewValue(tftypes.String, "other")}),
237+
}),
238+
},
239+
),
240+
},
241+
),
242+
T: tftypes.Tuple{ElementTypes: []tftypes.Type{
243+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"first": tftypes.String}},
244+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"second": tftypes.DynamicPseudoType}},
245+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"third": tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}}}}}},
246+
}},
247+
},
248+
249+
Out: tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{
250+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"first": tftypes.String}},
251+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"second": tftypes.DynamicPseudoType}},
252+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"third": tftypes.Tuple{ElementTypes: []tftypes.Type{
253+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
254+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
255+
}}}},
256+
}},
257+
[]tftypes.Value{
258+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"first": tftypes.String}},
259+
map[string]tftypes.Value{"first": tftypes.NewValue(tftypes.String, "foo")}),
260+
261+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"second": tftypes.DynamicPseudoType}},
262+
map[string]tftypes.Value{"second": tftypes.NewValue(tftypes.String, nil)}),
263+
264+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"third": tftypes.Tuple{ElementTypes: []tftypes.Type{
265+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
266+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
267+
}}}},
268+
map[string]tftypes.Value{"third": tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{
269+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
270+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
271+
}},
272+
[]tftypes.Value{
273+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
274+
map[string]tftypes.Value{
275+
"foo": tftypes.NewValue(tftypes.String, "some"),
276+
"bar": tftypes.NewValue(tftypes.String, nil),
277+
}),
278+
tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"foo": tftypes.String, "bar": tftypes.String}},
279+
map[string]tftypes.Value{
280+
"foo": tftypes.NewValue(tftypes.String, nil),
281+
"bar": tftypes.NewValue(tftypes.String, "other"),
282+
}),
283+
},
284+
)},
285+
),
286+
}),
287+
},
204288
"set->tuple": {
205289
In: sampleInType{
206290
V: tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{
@@ -410,9 +494,9 @@ func TestMorphValueToType(t *testing.T) {
410494
}},
411495
},
412496
Out: tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{
413-
"one": tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.DynamicPseudoType, tftypes.DynamicPseudoType}},
497+
"one": tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.String, tftypes.String}},
414498
}}, map[string]tftypes.Value{
415-
"one": tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.DynamicPseudoType, tftypes.DynamicPseudoType}},
499+
"one": tftypes.NewValue(tftypes.Tuple{ElementTypes: []tftypes.Type{tftypes.String, tftypes.String}},
416500
[]tftypes.Value{
417501
tftypes.NewValue(tftypes.String, "bar"),
418502
tftypes.NewValue(tftypes.String, "baz"),

0 commit comments

Comments
 (0)