Open
Conversation
mildwonkey
previously approved these changes
Feb 13, 2026
Contributor
mildwonkey
left a comment
There was a problem hiding this comment.
lgtm, and reading the linked issues was interesting. this is going to be very useful!
thank you for this trip down memory lane 😂 - my very first every terraform task was porting funcs to go-cty
4861f7d to
808ee8a
Compare
The convert function allows for inline type conversions within the Terraform language. A custom decoder for the function which allows for type expression literals as the second parameter.
We add `convert` to our set of functions, and we clean up the duplicate function assignments in this package. The multiple assignments have meant that any function changes are inevitably forgotten from the testing framework, and we shouldn't need to declare the mapping multiple times.
In order to allow for type constraints to be inserted into arbitrary expressions using the `convert` function, we need to allow for the use of primitive type names. Previously `string`, `number`, `bool`, and `any` would be considered as incomplete resource references, because there are no constraints on what providers can name resources. However because you cannot use a standalone resource type name as a reference in HCL, we can make an exception here for when these identifiers are not part of a longer traversal.
808ee8a to
c507cfe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a
convertfunction, allowing for inline type conversions within Terraform configuration. The full type constraint syntax is available within the second function argument, allowing for explicit typing of values, and injection of optional attributes with defaults.Most of the time Terraform's type inference is sufficient when assigning data in configuration, but there are still numerous edge cases which cause problems for users when the inferred types don't align correctly. These for example may arise from the opposing sides of conditional expressions having different inferred types, a lack of a literal syntax for expressing certain values (we don't have syntax for maps, lists, or sets!), or equality comparisons where type is not implicitly converted.
The convert function more easily takes the default literal types, and directly applies the type the user specifies:
The conversion works in the same manner that assignment to a typed variable input works, without the need for an additional module just to complete the type conversion. This means that defaults can be injected for object types:
This also lends itself to data manipulation using the conversion, or even prevents conversions which may not be wanted:
Another common case is where a user wants to instantiate an empty container containing some more complex type. This leads to problems like:
{}isn't an empty map, which would need an element type, it's an empty object which can never have attributes. Or[]which isn't an empty list without an element type, but rather an empty tuple which has exactly zero elements.Convert allows for the explicit creation of these zero values for users
This also replaces the need for most of the existing
to*conversion functions for complex types, which often lack the expressivity to fully solve user issues. They can be retained as is for now though, since they would still be a valid shorthand for when the type conversion is only concerned with the outer container type, and there is no need to force users to change syntax since the identifiers are otherwise of no value, This would be the equivalentconvertsyntax for these functionsCompatibility concerns:
Prior to this change, because of the open namespace for provider resources, the identifiers
string,number,bool, andanywould be considered the start of a resource reference when resolving variables in an expression. These identifiers were not reserved, but we can at least partly consider the context in which they are resolved. Because referring to a resource type without a resource name is not valid, if any of these words appear as a single element traversal (i.e. no.name*), we can choose to not resolve them as a reference in order to allow them to appear in the type expression.This doesn't break any existing behavior, however it does change an error slightly in the case one of these identifiers is accidentally used. In older versions, something like
attr = numberwould result in the errorA reference to a resource type must be followed by at least one attribute access, specifying the resource name. Now the error reads likeThere is no variable named "number", which might arguably be easier to understand in the case where a resource callednumberdoesn't exist. If the resource is prefaced with theresource.identifier the error does not change.In the rare case that there is a resource using one of these type names, and there is an an error in the configuration where the type is not followed by the name, the current error is a slight downgrade. That may be acceptable given the near zero chance of it happening, but a possible mitigation would be to extend the
There is no variable namederror with another line that that states that if it is a known resource type, to follow it with a resource name.While we're in here we also remove the duplicate mapping of functions in the lang package, which has led to functions missing from the test framework multiple times.
We can use this feature as a milestone to close the following issues:
Closes #23562
Closes #27643
Closes #29622
Closes #29809
Closes #32304
Closes #33303
Closes #35027
Most of those are not directly solved by this feature, but rather this feature offers a way to help those cases in various ways, while still working within the language and type system that we have. More information can be added in the individual issues on a case by case basis.