-
Notifications
You must be signed in to change notification settings - Fork 589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Short-circuit behavior for the &&
and ||
operators
#538
Closed
Commits on Jun 14, 2022
-
go.mod: Specify that we use the Go 1.17 language in this module
The main motivation here is that we were apparently using bit shifting with signed shift amounts even though modern Go toolchains seem to raise that as an error if the go.mod file selects a language version less than Go 1.13. Go 1.17 is therefore newer than we strictly need to solve that particular problem, but gets us caught up with a relatively release of the language. This alone doesn't break compatibility for anyone using older versions of Go with HCL, since the Go toolchain will still attempt to compile modules targeting later versions and will only mention the newer language version if compilation would already have failed for some other reason.
Configuration menu - View commit details
-
Copy full SHA for b440b17 - Browse repository at this point
Copy the full SHA b440b17View commit details -
hclsyntax: && and || operators are right-associative
Previously we just treated all binary operators as being left-associative, which for many of them didn't make a lot of difference anyway because they were associative operators. The logical AND and OR operators are also effectively associative the way we have them implemented right now, because HCL always evaluates both sides of a binary operator anyway and so there's no way to depend on the associativity for either of these operations. However, we'd like to implement a similar short-circuit behavior as we see in many other similar languages, at which point the evaluation order of the operations would become important in order to constrain which expressions get fully evaluated and which are "short-circuited". Treating these operators as right-associative instead of left-associative will make the subsequent implementation more intuitive, since the LHS of the outermost operation will decide whether to evaluate the RHS, rather than recursing into the LHS completely first and then unwinding if the innermost term causes the short-circuit. Since we expect HCL expression evaluation to always be side-effect-free it doesn't technically matter what associativity we use -- the result would be the same either way -- but this approach will make the control flow during evaluation match intuition about how a short-circuit behaves. This commit does not yet actually implement the short-circuit behavior, which will hopefully follow in a subsequent commit.
Configuration menu - View commit details
-
Copy full SHA for 9ba6757 - Browse repository at this point
Copy the full SHA 9ba6757View commit details -
hclsyntax: Short-circuit behavior for the && and || operators
Previously we just always evaluated both operands of any binary operator and then executed the operator. For the logical operators that was inconsistent with their treatment in several other languages with a similar grammar to ours, leading to users being surprised that HCL didn't short circuit the same way as their favorite other languages did. Our initial exclusion of short-circuiting here was, as with various other parts of HCL's design, motivated by the goals of producing consistent results even when unknown values are present and of proactively returning as many errors as possible in order to give better context when debugging. However, in acknowledgement of the fact that logical operator short-circuiting has considerable ergonomic benefits when writing out compound conditional expressions where later terms rely on the guarantees of earlier terms, this commit implements a compromise design where we can get the short-circuit benefits for dynamic-value-related errors without losing our ability to proactively detect type-related errors even when short-circuiting. Specifically, if a particular operator participates in short-circuiting then it gets an opportunity to decide for a particular known LHS value whether to short-circuit. If it decides to do so then HCL will evaluate the RHS in a type-checking-only mode, where we ignore any specific values in the variable scope but will still raise errors if the RHS expression tries to do anything to them that is inconsistent with their type. If the LHS of a short-circuit-capable operator turns out to be an unknown value of a suitable type, we'll pessimistically treat it as a short-circuit and defer full evaluation of the RHS until we have more information, so as to avoid raising errors that would be guarded away once the LHS becomes known. The effect of this compromise is that it's possible to use the short-circuit operators in common value-related guard situations, like checking whether a value is null or is a number that would be valid to index a particular list: foo != null && foo.something idx < 3 && foo[idx] On the other hand though, it is _not_ possible to use the behavior to guard against problems that are related to types rather than to values, which allows us to still proactively detect various kinds of errors that are likely to be mistakes: foo != null && fo.something # Typoed "foo" as "fo" foo != null && foo.smething # Typoed "something" as "smething" num < 3 && num.something # Numbers never have attributes Those coming from dynamic languages will probably still find these errors surprising, but HCL's other features follow a similar sort of hybrid model of statically checking types where possible and that tradeoff seems to have worked well to make it possible to express more complicated situations while still providing some of the help typically expected from a static type system for "obviously wrong" situations. It should typically be possible to adjust an expression to make it friendly to short-circuit guard style by being more precise about the types being used.
Configuration menu - View commit details
-
Copy full SHA for 4790ab6 - Browse repository at this point
Copy the full SHA 4790ab6View commit details
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.