gohcl: WithRange[T] for concise decoding with source locations#516
Closed
apparentlymart wants to merge 1 commit intohashicorp:mainfrom
Closed
gohcl: WithRange[T] for concise decoding with source locations#516apparentlymart wants to merge 1 commit intohashicorp:mainfrom
apparentlymart wants to merge 1 commit intohashicorp:mainfrom
Conversation
Until now gohcl has forced callers to decide between two non-ideal options: - Decode directly into a "normal" Go type, like string, but then have no access to the source location of that value. - Decode into an hcl.Expression and then separately decode that expression into a normal type, which gives access to the source location but requires an extra decoding step downstream. Source location information is important if subsequent code does any further validation of the value beyond what HCL can do itself, and so this forces implementers to decide between returning low-quality error messages or writing more lines of code for decoding, and since a lot of people would prefer to write less code despite the consequences, this has therefore led to software with poor-quality error messages. Go 1.18 provides a compromise: we can use a generic struct type to pair up any normal value with an hcl.Range value, thus still achieving a one-shot decode behavior for simpler applications but giving those applications convenient access to both the resulting value and the source location it came from. This is essentially just another "special" type that gohcl has bespoke handling for, similar to hcl.Body, hcl.Expression, and hcl.Attributes. If decoding an expression into a value of a WithRange[T] type then it behaves as if decoding into a T directly, but writes the result into the Value field of the WithRange[T] alongside the source range.
Contributor
Author
|
I'm no longer working at HashiCorp after today, so I won't be able to interact with the branch of this PR anymore and so I'm going to close it but hope it'll still be a useful starting point for a future PR with a similar goal! |
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.
Until now
gohclhas forced callers to decide between two non-ideal options:hcl.Expressionand then separately decode that expression into a normal type, which gives access to the source location but requires an extra decoding step downstream.Source location information is important if subsequent code does any further validation of the value beyond what HCL can do itself, and so this forces implementers to decide between returning low-quality error messages or writing more lines of code for decoding, and since a lot of people would prefer to write less code despite the consequences, this has therefore led to software with poor-quality error messages.
Go 1.18 provides a compromise: we can use a generic struct type to pair up any normal value with an
hcl.Rangevalue, thus still achieving a one-shot decode behavior for simpler applications but giving those applications convenient access to both the resulting value and the source location it came from.This is essentially just another "special" type that
gohclhas bespoke handling for, similar tohcl.Body,hcl.Expression, andhcl.Attributes. If decoding an expression into a value of aWithRange[T]type then it behaves as if decoding into aTdirectly, but writes the result into theValuefield of theWithRange[T]alongside the source range.An important goal here is to do this without requiring all callers of this module to use Go 1.18. To achieve that, the generic code is all in a conditionally-compiled file, and we assume that any caller which includes
WithRange[T]would inherently require 1.18 itself anyway, so we won't enter the codepath for handling this type on older versions of Go.This is just a prototype for now. It needs some more thorough testing with various interesting variations to see if it's behavior is reasonable in each case. For example:
WithRange[cty.Value]*WithRange[Foo]vs.WithRange[*Foo]for optional attributes.WithRange[hcl.Expression](redundant, but should either work or return an explicit error explaining why not)WithRange[T]for a field representing a nested block type, rather than one representing an attribute? Should the range in that case be the block'sDeclRange, or something else?WithRange[T]on a,remain-tagged field? (Probably not, but it should still return a sensible error message if someone tries.)