Skip to content

Classify a quoted condition as a conditional operand - #1577

Merged
trueqbit merged 3 commits into
devfrom
feature/quoted-conditions-in-or
Oct 11, 2026
Merged

trueqbit merged 3 commits into
devfrom
feature/quoted-conditions-in-or

Conversation

@trueqbit

@trueqbit trueqbit commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #1564: based on its branch, so this diff shows only the changes on top of it.

Summary

|| is the logical OR for conditions and the string concatenation otherwise. The two operator|| overloads told them apart by the raw operand types, and quoted_expression_t is not a condition, so a c()-quoted condition always took the concatenation:

c(eq(&User::id, 1)) || c(eq(&User::id, 2))  // was: conc_t, serialized as `||`
eq(&User::id, 1) || eq(&User::id, 2)        // or_condition_t, serialized as OR

That contradicts what #1564 establishes: a node built from c(x) is the very node built from x. A quoted condition is now classified as a conditional operand: c(cond1) || c(cond2), c(cond1) || cond2 and cond1 || c(cond2) now all build the OR that cond1 || cond2 builds.

Only || needed this: it is the one overloaded operator with two meanings. && accepts any operator argument and already built an and_condition_t from quoted conditions.

The classification lives on the operand axis, not in the || overloads, as the vocabulary layer intends for an operand-only node such as the quoting wrapper:

  • is_conditional_operand_v becomes an open trait with a SFINAE slot, like is_operator_argument_v (vocabulary/traits/operand_traits_fwd.h);
  • its condition_t base rule is now a specialization in tags.h, so every node inheriting condition_t is classified as before;
  • ast/quoted_expression.h classifies a quoted operand as the operand it quotes, next to its is_operator_argument_v specialization.

The || overloads are unchanged; they ask the trait about their operands as before. The other operand traits (arithmetic, negatable, chainable) are left as they are: a quoted operand already passes wherever they are checked, via is_operator_argument.

Consumer-visible change

Code that relied on c(cond1) || c(cond2) concatenating two conditions now gets their OR. Concatenating conditions on purpose remains available explicitly as conc(cond1, cond2). Concatenation of non-conditions, e.g. c(&User::name) || "a", is unchanged.

This is also half of the trap reported in #1575 (c(match<Post>("cat")) || c(match<Post>("dog")) serializing ||); the other half, match() results not being conditions at all, follows in a separate PR stacked on this one.

Test plan

  • tests/static_tests/quoted_operands.cpp, new section "logical or concatenation":
    • c(cond1) || c(cond2), c(cond1) || cond2 and cond1 || c(cond2) have the type of cond1 || cond2, an or_condition_t;
    • c(cond1) && c(cond2) has the type of cond1 && cond2;
    • is_conditional_operand holds for c(cond1), and not for c(&User::name);
    • c(&User::name) || "a" and c(&User::name) || c("a") still build a conc_t.

🤖 Generated with Claude Code

`||` is the logical OR for conditions and the string concatenation
otherwise. The overloads told them apart by the raw operand types, so a
`c()`-quoted condition never counted as a condition: `c(cond1) || c(cond2)`
built a concatenation where `cond1 || cond2` builds an OR. Classify the
operands after unwrapping them, as the node built from them holds them.

Co-Authored-By: Claude Opus 5.5
Instead of unwrapping in the `||` overloads, let the operand axis classify
the quoting wrapper, as the vocabulary layer intends for operand-only nodes:
`is_conditional_operand_v` becomes an open trait like
`is_operator_argument_v`, the `condition_t` base rule is its specialization
in `tags.h`, and `quoted_expression.h` classifies a quoted operand as the
operand it quotes. The `||` overloads ask the trait about their operands
again, as before.

Co-Authored-By: Claude Opus 5.5
@trueqbit trueqbit changed the title Tell || apart by its unwrapped operands Classify a quoted condition as a conditional operand Oct 7, 2026
@trueqbit
trueqbit marked this pull request as ready for review October 8, 2026 10:42
@trueqbit
trueqbit requested a review from fnc12 October 11, 2026 10:29
Base automatically changed from fix/unwrap-quoted-expressions to dev October 11, 2026 11:49
@trueqbit
trueqbit merged commit 2b1d367 into dev Oct 11, 2026
20 checks passed
@trueqbit
trueqbit deleted the feature/quoted-conditions-in-or branch October 11, 2026 11:49
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