From 31237fe9685c140eb7f592184f6025ff64f72dd7 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 12 Feb 2026 10:47:33 -0500 Subject: [PATCH] allow the use of primitive names in HCL 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. --- internal/addrs/parse_ref.go | 11 +++++++++ internal/addrs/parse_ref_test.go | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/internal/addrs/parse_ref.go b/internal/addrs/parse_ref.go index 88d960f001..f96ffa9b28 100644 --- a/internal/addrs/parse_ref.go +++ b/internal/addrs/parse_ref.go @@ -407,6 +407,17 @@ func parseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) { } remain := traversal[1:] // trim off "action" return parseActionRef(rootRange, remain) + + case "string", "number", "bool", "any": + if len(traversal) == 1 { + // A standalone word is a primitive type constraint. + return nil, diags + } + + // There could technically be providers that implement resources by + // these names, so if the traversal has more parts we still fallthrough + // to the default resource parsing. + fallthrough default: return parseResourceRef(ManagedResourceMode, rootRange, traversal) } diff --git a/internal/addrs/parse_ref_test.go b/internal/addrs/parse_ref_test.go index 721dedcbd5..0d11274eaa 100644 --- a/internal/addrs/parse_ref_test.go +++ b/internal/addrs/parse_ref_test.go @@ -1056,6 +1056,47 @@ func TestParseRef(t *testing.T) { }, ``, }, + + // a standalone primitive name is a type constraint, and does not + // reference anything + { + `string`, + nil, + ``, + }, + { + `bool`, + nil, + ``, + }, + { + `number`, + nil, + ``, + }, + { + `any`, + nil, + ``, + }, + + { + // a multi-step traversal starting with a primitive name is still + // treated as any other resource reference + `string.foo`, + &Reference{ + Subject: Resource{ + Mode: ManagedResourceMode, + Type: "string", + Name: "foo", + }, + SourceRange: tfdiags.SourceRange{ + Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, + End: tfdiags.SourcePos{Line: 1, Column: 11, Byte: 10}, + }, + }, + ``, + }, } for _, test := range tests {