Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hashicorp/hcl Loading
base: 581f975
Choose a base ref
...
head repository: hashicorp/hcl Loading
compare: 4790ab6
Choose a head ref
  • 1 commit
  • 3 files changed
  • 1 contributor

Commits on Jun 14, 2022

  1. 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.
    apparentlymart committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    4790ab6 View commit details
    Browse the repository at this point in the history
Loading