zclconf / go-cty

A type system for dynamic values in Go applications
MIT License
348 stars 71 forks source link

Value "refinements" #153

Closed apparentlymart closed 1 year ago

apparentlymart commented 1 year ago

Originally the purpose of unknown values in cty was primarily to allow type checking of expressions whose input values are not fully known yet. Consequently they had a pretty simple model: an unknown value has a type constraint and operations on unknown values check that the type constraints are valid but otherwise just return even more unknown values to allow type checking to continue with subsequent derived expressions.

However, this limited approach misses some opportunities to use known constraints on the range of results from certain operations to allow some operations on unknown values to return known values, or at least values that are "more known" (have a smaller range than just meeting a type constraint).

This changeset introduces a new model of "refinements" that can constrain the range of an unknown value beyond just a type constraint, and some early work to make use of that new information to return refined values from various built-in operations.

This is backward-compatible with the old behavior in the sense that conventionally we don't consider it a breaking change for a result to be "more known" in a new minor release than it was in the previous release. However, applications depending on operation methods -- in particular Value.RawEquals, but not limited to that -- may find that their unit tests now produce slightly different results where previously-unknown values are now either fully known or are refined with a more limited range. If the new refined range seems correct then I'd suggest updating those tests as part of upgrading cty; if the refined range seems incorrect then that may be a bug, so please open a new issue to discuss it.

Future changes might improve the refinements analysis further, causing even smaller ranges for unknown values. However, refinement analysis is always "best effort" and so it is not a bug for cty to return an unknown value with a wider range than necessary: narrowing that range might be an opportunity for improvement in a future minor release.