Skip to content

Commit

Permalink
function/stdlib: ConcatFunc precise handling of marks
Browse files Browse the repository at this point in the history
ConcatFunc will now only mark the resulting list with marks from the
argument lists as a whole, and not aggregate individual list element marks
at the top-level result.

The individual element marks will still be preserved, but they'll remain
attached to the individual element values they came from, avoiding the
result as a whole becoming marked.
  • Loading branch information
apparentlymart committed Apr 19, 2021
1 parent d22934f commit fc963dc
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 5 deletions.
23 changes: 18 additions & 5 deletions cty/function/stdlib/sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (
var ConcatFunc = function.New(&function.Spec{
Params: []function.Parameter{},
VarParam: &function.Parameter{
Name: "seqs",
Type: cty.DynamicPseudoType,
Name: "seqs",
Type: cty.DynamicPseudoType,
AllowMarked: true,
},
Type: func(args []cty.Value) (ret cty.Type, err error) {
if len(args) == 0 {
Expand Down Expand Up @@ -75,6 +76,7 @@ var ConcatFunc = function.New(&function.Spec{
// given values will be lists and that they will either be of
// retType or of something we can convert to retType.
vals := make([]cty.Value, 0, len(args))
var markses []cty.ValueMarks // remember any marked lists we find
for i, list := range args {
list, err = convert.Convert(list, retType)
if err != nil {
Expand All @@ -83,26 +85,37 @@ var ConcatFunc = function.New(&function.Spec{
return cty.NilVal, function.NewArgError(i, err)
}

list, listMarks := list.Unmark()
if len(listMarks) > 0 {
markses = append(markses, listMarks)
}

it := list.ElementIterator()
for it.Next() {
_, v := it.Element()
vals = append(vals, v)
}
}
if len(vals) == 0 {
return cty.ListValEmpty(retType.ElementType()), nil
return cty.ListValEmpty(retType.ElementType()).WithMarks(markses...), nil
}

return cty.ListVal(vals), nil
return cty.ListVal(vals).WithMarks(markses...), nil
case retType.IsTupleType():
// If retType is a tuple type then we could have a mixture of
// lists and tuples but we know they all have known values
// (because our params don't AllowUnknown) and we know that
// concatenating them all together will produce a tuple of
// retType because of the work we did in the Type function above.
vals := make([]cty.Value, 0, len(args))
var markses []cty.ValueMarks // remember any marked seqs we find

for _, seq := range args {
seq, seqMarks := seq.Unmark()
if len(seqMarks) > 0 {
markses = append(markses, seqMarks)
}

// Both lists and tuples support ElementIterator, so this is easy.
it := seq.ElementIterator()
for it.Next() {
Expand All @@ -111,7 +124,7 @@ var ConcatFunc = function.New(&function.Spec{
}
}

return cty.TupleVal(vals), nil
return cty.TupleVal(vals).WithMarks(markses...), nil
default:
// should never happen if Type is working correctly above
panic("unsupported return type")
Expand Down
48 changes: 48 additions & 0 deletions cty/function/stdlib/sequence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,54 @@ func TestConcat(t *testing.T) {
cty.NumberIntVal(3),
}),
},
{
[]cty.Value{
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
}),
cty.ListVal([]cty.Value{
cty.NumberIntVal(2),
cty.NumberIntVal(3),
}).Mark("a"),
},
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
cty.NumberIntVal(2),
cty.NumberIntVal(3),
}).Mark("a"),
},
{
[]cty.Value{
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
}),
cty.ListVal([]cty.Value{
cty.NumberIntVal(2).Mark("b"),
cty.NumberIntVal(3),
}),
},
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
cty.NumberIntVal(2).Mark("b"),
cty.NumberIntVal(3),
}),
},
{
[]cty.Value{
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
}).Mark("a"),
cty.ListVal([]cty.Value{
cty.NumberIntVal(2).Mark("b"),
cty.NumberIntVal(3),
}),
},
cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
cty.NumberIntVal(2).Mark("b"),
cty.NumberIntVal(3),
}).Mark("a"),
},
{
[]cty.Value{
cty.ListVal([]cty.Value{
Expand Down

0 comments on commit fc963dc

Please sign in to comment.