Skip to content
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

cty: add CanListFunc, CanSetFunc, CanMapFunc #91

Merged
merged 1 commit into from
Mar 16, 2021

Conversation

mildwonkey
Copy link
Contributor

The logic which may result in a panic in List(), Map() and Set() have been extracted into these helper functions, which return errors instead. The original callers (still) panic if an error is returned.

These new functions are called in the appropriate conversion functions in the convert package to validate that the given elements can be used to create a single Type, to help reduce the number of panics that occur when calling Convert.

For additional background information on the (odd) scenarios that can lead to these panics, see hashicorp/terraform#26195

While working on this, I realized that conversionCheckMapElementTypes was doing much the same thing, so I removed it in favor of CanMapFunc(). However since the logic for CanMapFunc() was taken from Map(), it's lost the path-specific error. If that's not good enough I can roll back its removal!

@codecov
Copy link

codecov bot commented Mar 9, 2021

Codecov Report

Merging #91 (129cba3) into main (080b168) will increase coverage by 0.02%.
The diff coverage is 64.70%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #91      +/-   ##
==========================================
+ Coverage   70.85%   70.88%   +0.02%     
==========================================
  Files          79       79              
  Lines        6636     6656      +20     
==========================================
+ Hits         4702     4718      +16     
- Misses       1490     1491       +1     
- Partials      444      447       +3     
Impacted Files Coverage Δ
cty/convert/conversion_collection.go 79.60% <0.00%> (-1.72%) ⬇️
cty/value_init.go 76.11% <100.00%> (+4.69%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 080b168...139e794. Read the comment docs.

@@ -186,6 +184,23 @@ func ListValEmpty(element Type) Value {
}
}

// CanListFunc returns an error if the given Values can not be coalesced
// into a single List due to inconsistent element types.
func CanListFunc(vals []Value) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I created this confusion by making a typo when we were originally talking about this, but I was actually proposing for these to be named CanListVal, CanMapVal, etc, to represent that they each determine whether the corresponding Can... function can succeed.

Given that there's only one possible panic situation here, and for consistency with the other Can...-prefixed functions elsewhere in cty, I think I'd rather have these be functions that return bool to indicate that a subsequent call would succeed, rather than returning an error, and then let the ListVal/etc functions be responsible for constructing a suitable panic message as they were before.

This does mean that the convert codepaths will also need to construct themselves a suitable error value to return, but I think that's justified because the error messages there ought to be written with an end-user audience in mind, rather than a Go developer audience in mind. We don't really have enough context to return a great error message at that convert layer (cause we're already in a "shouldn't really happen" situation anyway), so I'd go for something pretty generic like this:

List element types don't match

A higher layer can replace that with a better error message if it has more interesting context to add, but we can save that for a later change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! I reverted the corresponding constructor functions (so they maintain the element-specific error message) and refactored the Can... funcs to return bools (that was my original plan anyway, so cool!). I also added test coverage for the new functions.

@mildwonkey mildwonkey force-pushed the panic-elems branch 2 times, most recently from 8bbb856 to 129cba3 Compare March 10, 2021 14:00
Despite our best efforts to correctly unify element types during conversion,
sometimes some inconsistent types slip through anyway and make the
conversion panic.

Although in the long run it would be better to fix these problems upstream,
it's the responsibility of the caller of cty to not try to perform any
invalid operations, and so here we make the convert package pre-verify
that it's found a sensible result before trying to construct it, and
thus it can return a proper error if not rather than panicking.
@apparentlymart
Copy link
Collaborator

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants