From 0eb4b5cc0ec494f4b8de6933d2eddf97b12a77f7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 8 Jan 2018 14:46:44 -0800 Subject: [core] Omit inferred type annotations for 'coalesce' arguments --- src/mbgl/style/expression/coalesce.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/mbgl/style/expression/coalesce.cpp') diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp index bfde3c7581..0373c9626c 100644 --- a/src/mbgl/style/expression/coalesce.cpp +++ b/src/mbgl/style/expression/coalesce.cpp @@ -1,4 +1,5 @@ #include +#include namespace mbgl { namespace style { @@ -36,14 +37,15 @@ ParseResult Coalesce::parse(const Convertible& value, ParsingContext& ctx) { } optional outputType; - if (ctx.getExpected() && *ctx.getExpected() != type::Value) { - outputType = ctx.getExpected(); + optional expectedType = ctx.getExpected(); + if (expectedType && *expectedType != type::Value) { + outputType = expectedType; } Coalesce::Args args; args.reserve(length - 1); for (std::size_t i = 1; i < length; i++) { - auto parsed = ctx.parse(arrayMember(value, i), i, outputType); + auto parsed = ctx.parse(arrayMember(value, i), i, outputType, ParsingContext::omitTypeAnnotations); if (!parsed) { return parsed; } @@ -52,9 +54,19 @@ ParseResult Coalesce::parse(const Convertible& value, ParsingContext& ctx) { } args.push_back(std::move(*parsed)); } - assert(outputType); - return ParseResult(std::make_unique(*outputType, std::move(args))); + + // Above, we parse arguments without inferred type annotation so that + // they don't produce a runtime error for `null` input, which would + // preempt the desired null-coalescing behavior. + // Thus, if any of our arguments would have needed an annotation, we + // need to wrap the enclosing coalesce expression with it instead. + bool needsAnnotation = expectedType && + std::any_of(args.begin(), args.end(), [&] (const auto& arg) { + return type::checkSubtype(*expectedType, arg->getType()); + }); + + return ParseResult(std::make_unique(needsAnnotation ? type::Value : *outputType, std::move(args))); } } // namespace expression -- cgit v1.2.1