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 {