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

Omit inferred type annotations for 'coalesce' arguments #5765

Merged
merged 3 commits into from
Dec 1, 2017

Conversation

anandthakker
Copy link
Contributor

As described in #5755, such inferred annotations cause a runtime type error for null inputs, thus preempting the desired null-coalescing behavior of something like ["coalesce", ["get", "a"], ["get", "b"]].

Copy link
Contributor

@jfirebaugh jfirebaugh left a comment

Choose a reason for hiding this comment

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

Rather than wrapping and unwrapping, did you consider an approach where parse gets a flag from Coalesce.parse indicating not to insert inferred assertions?

@anandthakker
Copy link
Contributor Author

Rather than wrapping and unwrapping, did you consider an approach where parse gets a flag from Coalesce.parse indicating not to insert inferred assertions?

I considered that, but Coalesce.parse also needs to know if an assertion "should" have been added, in order to know whether or not to wrap itself in an outer assertion. Given that, it seemed simpler to contain the logic within Coalesce.parse.

Realizing now that an alternative would be to just always wrap the coalesce in an outer assertion, even if none of its arguments are typed value. Maybe that's better.

@jfirebaugh
Copy link
Contributor

👍 always wrapping with an outer assertion.

Copy link
Contributor

@jfirebaugh jfirebaugh left a comment

Choose a reason for hiding this comment

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

Hmm, not really satisfied with how this turned out. The logic is complex and quite hard to follow.

Can we try another approach?

// Thus, if any of our arguments would have needed an annotation, we
// need to wrap the enclosing coalesce expression with it instead.
const needsAnnotation = expectedType &&
parsedArgs.some(arg => checkSubtype(expectedType, arg.type));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This bit isn't strictly necessary -- we could just always return new Coalesce(ValueType, parsedArgs) -- I figured including it would be more explicit & therefore clearer.

const expected = context.expectedType;
const actual = parsed.type;
if (expected) {
// When we expect a number, string, or boolean but have a
Copy link
Contributor

Choose a reason for hiding this comment

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

How about:

                    // When we expect a number, string, boolean, or array but
                    // have a Value, we can wrap it in a refining assertion.
                    // When we expect a Color but have a String or Value, we
                    // can wrap it in "to-color" coercion.
                    // Otherwise, we do static type-checking.
                    if ((expected.kind === 'string' || expected.kind === 'number' || expected.kind === 'boolean') && actual.kind === 'value') {
                        if (!options.omitTypeAnnotations) {
                            parsed = new Assertion(expected, [parsed]);
                        }
                    } else if (expected.kind === 'array' && actual.kind === 'value') {
                        if (!options.omitTypeAnnotations) {
                            parsed = new ArrayAssertion(expected, parsed);
                        }
                    } else if (expected.kind === 'color' && (actual.kind === 'value' || actual.kind === 'string')) {
                        if (!options.omitTypeAnnotations) {
                            parsed = new Coercion(expected, [parsed]);
                        }
                    } else if (context.checkSubtype(context.expectedType, parsed.type)) {
                        return null;
                    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👌

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated with this approach.

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