Skip to content

Commit

Permalink
stdlib: Conversion functions can accept unknown-typed nulls
Browse files Browse the repository at this point in the history
This is one of those confusing situations where the multiple
subtly-different meanings of cty.DynamicPseudoType meet:

 - The "Type" field specifies a target type that the argument must be
   converted to before calling the function, and so cty.DynamicPseudoType
   here essentially means "don't do any pre-conversion at all".
 - However, that means that the value given as an argument might be a
   null or unknown value with a type constraint. In that position,
   cty.DynamicPseudoType represents "we don't yet know the type", which
   not all functions are equipped to deal with and so those that are must
   opt-in with AllowDynamicPseudoType: true.

Without declaring AllowDynamicPseudoType, the general function handling
code will just skip calling the function at all when the argument doesn't
yet have a known type, returning an unknown value of an unknown type to
represent that the function's result cannot be known until the argument's
type has become known.

However, type conversion functions can safely accept values of unknown
type, because they are just thin wrappers around package convert which
already deal with that situation automatically. The conversion functions
should set AllowDynamicType: true so that package convert can be the one
to deal with the situation, and can thus convert a null value of unknown
type into a null value of the target type (since null-to-null conversions
are always allowed).
  • Loading branch information
apparentlymart committed Mar 20, 2024
1 parent f41ae52 commit 4b76b75
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 1.14.4 (Unreleased)

* `msgpack`: Now uses string encoding instead of float encoding for a whole number that is too large to fit in any of MessagePack's integer types.
* `function/stdlib`: Type conversion functions (constructed with `MakeToFunc`) can now convert null values of unknown type into null values of the target type, rather than returning an unknown value in that case.

# 1.14.3 (February 29, 2024)

Expand Down
5 changes: 3 additions & 2 deletions cty/function/stdlib/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ func MakeToFunc(wantTy cty.Type) function.Function {
// messages to be more appropriate for an explicit type
// conversion, whereas the cty function system produces
// messages aimed at _implicit_ type conversions.
Type: cty.DynamicPseudoType,
AllowNull: true,
Type: cty.DynamicPseudoType,
AllowNull: true,
AllowDynamicType: true,
},
},
Type: func(args []cty.Value) (cty.Type, error) {
Expand Down
6 changes: 6 additions & 0 deletions cty/function/stdlib/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ func TestTo(t *testing.T) {
cty.NullVal(cty.Number),
``,
},
{
cty.NullVal(cty.DynamicPseudoType),
cty.Number,
cty.NullVal(cty.Number),
``,
},
{
cty.UnknownVal(cty.Bool),
cty.String,
Expand Down

0 comments on commit 4b76b75

Please sign in to comment.