Commit b31b71f3a for llama.cpp
commit b31b71f3a076bfc4278daad442203a9c51c6e676
Author: Pascal <admin@serveurperso.com>
Date: Wed Sep 9 09:08:27 2026 +0200
jinja: treat a null left operand of in as a plain lookup (#28620)
Templates that default an optional variable to none and then test its
membership in a map hit an error, while the same expression is a normal
lookup returning false in Jinja. The undefined counterpart of this case
was already handled just above.
diff --git a/common/jinja/runtime.cpp b/common/jinja/runtime.cpp
index b02992529..49354c7c9 100644
--- a/common/jinja/runtime.cpp
+++ b/common/jinja/runtime.cpp
@@ -167,6 +167,12 @@ value binary_expression::execute_impl(context & ctx) {
}
throw std::runtime_error("Cannot perform operation " + op.value + " on undefined values");
} else if (is_val<value_none>(left_val) || is_val<value_none>(right_val)) {
+ if (!is_val<value_none>(right_val) && (op.value == "in" || op.value == "not in")) {
+ // case: none in {'low': 1}
+ // A null left operand is looked up like any other value.
+ bool member = test_is_in();
+ return mk_val<value_bool>(op.value == "in" ? member : !member);
+ }
if (op.value == "+" || op.value == "~") {
value res = mk_val<value_undefined>();
if (workaround_concat_null_with_str(res)) {
diff --git a/tests/test-jinja.cpp b/tests/test-jinja.cpp
index 974a3f9dd..ab551d7b3 100644
--- a/tests/test-jinja.cpp
+++ b/tests/test-jinja.cpp
@@ -374,6 +374,24 @@ static void test_expressions(testing & t) {
"42"
);
+ test_template(t, "none in object",
+ "{{ x in {'low': 1, 'high': 2} }}",
+ {{"x", nullptr}},
+ "False"
+ );
+
+ test_template(t, "none not in object",
+ "{{ x not in {'low': 1, 'high': 2} }}",
+ {{"x", nullptr}},
+ "True"
+ );
+
+ test_template(t, "none in array",
+ "{{ x in [1, none, 3] }}",
+ {{"x", nullptr}},
+ "True"
+ );
+
test_template(t, "dot notation",
"{{ user.name }}",
{{"user", {{"name", "Bob"}}}},