You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2026/10/24 02:23:00 UTC
[jira] [Created] (GROOVY-12485) Recognise Zazr control carriers by name in the monadic carrier allow-list
Paul King created GROOVY-12485:
----------------------------------
Summary: Recognise Zazr control carriers by name in the monadic carrier allow-list
Key: GROOVY-12485
URL: https://issues.apache.org/jira/browse/GROOVY-12485
Project: Groovy
Issue Type: Bug
Components: groovy-macro-library, groovy-typecheckers, Static Type Checker
Affects Versions: 6.0.0
Reporter: Paul King
h2. Background
GEP-23 ships a standard carrier allow-list ({{org.apache.groovy.runtime.MonadicCarrierRegistry}}) shared by the {{DO}} runtime dispatcher, {{MonadicChecker}} and {{MonadicShapeChecker}}. Third-party libraries Groovy must not
depend on are listed by fully-qualified name: Functional Java ({{fj.data.*}}, {{fj.P1}}) and Vavr (ry/Either/Validation}}).
[Zazr|https://zazr.dev/] ({{dev.zazr:zazr-core}}, Apache 2.0, JDK 25+, no runtime dependencies) is er {{dev.zazr}} with the same four control carriers plus {{Lazy}}. All of them exposesingle-argument {{flatMap}}/{{map}}, so they already participate in {{DO}} via the structural path. However, structural participation is deliberately *untrusted*: {{MonadicChecker.trustedCarrierName}} returns {{null}} for it,
and {{MonadicShapeChecker.carrierFor}} only consults the registry and {{@Monadic}}. The result is tguarantees than the equivalent Vavr code.
h2. Observed behaviour (Groovy 6.0.0, zazr-core 0.4.0, JDK 25)
||Scenario||Zazr carrier||Same shape over Optional/Stream||
|{{DO}} over Option/Try/Either/Validation/Lazy under {{MonadicChecker}}|compiles and runs|compiles and runs|
|{{MonadicShapeChecker}} on {{Option.some(1).map \{ Option.some(it) \}}}|accepted silently, yields error: "did you mean 'flatMap'?"|
|Mixed carriers in one {{DO}} under {{MonadicChecker}}|compiles, then {{GroovyCastException}} at runtime|compile error: "Mixing carriers in a comprehension is not supported"|
Reproducer for the mixed-carrier case:
{code:groovy}
import dev.zazr.control.*
import groovy.transform.TypeChecked
import static org.apache.groovy.macrolib.MacroLibGroovyMethods.DO
@TypeChecked(extensions = 'groovy.typecheckers.MonadicChecker')
def mixed() {
DO(x in Option.some(1), y in Try.success(2)) { Option.some(x + y) } // should be rejected at
}
{code}
Reproducer for the shape-lint gap:
{code:groovy}
import dev.zazr.control.Option
import groovy.transform.TypeChecked
@TypeChecked(extensions = 'groovy.typecheckers.MonadicShapeChecker')
def nested() { Option.some(1).map { Option.some(it) } } // M<M<T>>, no diagnostic today
{code}
h2. Proposed change
Add name-keyed rows to {{MonadicCarrierRegistry.NAMED_ENTRIES}}, using the structural {{flatMap}}/{ as the Vavr rows do:
{code:java}
// Zazr (dev.zazr) — recognised by name; no dependency. Structural flatMap/map,
// listed so the carriers are trusted by MonadicChecker and linted by MonadicShapeChecker.
new NamedEntry("dev.zazr.control.Option", "flatMap", "map"),
new NamedEntry("dev.zazr.control.Either", "flatMap", "map"),
new NamedEntry("dev.zazr.control.Try", "flatMap", "map"),
new NamedEntry("dev.zazr.control.Validation", "flatMap", "map"),
new NamedEntry("dev.zazr.Lazy", "flatMap", "map")
{code}
No new dependency and no behavioural change for any existing carrier. Because matching walks the tynested record cases ({{Option.Some}}, {{Try.Failure}}, {{Validation.Invalid}}, ...) resolve to their sealed parent as they do for {{fj.data.Some}} today.
h2. Scope of work
* {{MonadicCarrierRegistry}}: add the entries above and extend the class Javadoc.
* Tests: a {{ZazrCarrierTest}} in groovy-macro-library mirroring {{FunctionalJavaCarrierTest}}, usir {{dev.zazr.control}} (same pattern as the existing {{fj/data/Option.groovy}} stub) so the buildtakes no dependency. Cover: {{DO}} dispatch, {{MonadicChecker}} rejecting a mixed Zazr comprehension, {{MonadicShapeChecker}} reporting the three shape mistakes on a Zazr chain.
* Docs: {{_monadic-comprehensions.adoc}} allow-list paragraph; GEP-23 allow-list and version historvy 6.0 release notes paragraph listing recognised libraries (if backported).
h2. Notes
* Zazr's {{Validation.flatMap}} short-circuits (its Javadoc says so; accumulation is via {{zip}}/{{ so {{DO}} semantics over it match Vavr and Functional Java {{Validation}}: dependent steps, firstfailure wins. * Zazr's collections ({{Vector}}, {{List}}, {{LazyList}}) also have structural {{flatMap}}/{{map}};ft out, matching the treatment of {{io.vavr.collection.*}}.
* The user-configurable registration channel deferred to 7.0 by GEP-23 is the general fix for libraries Groovy does not know about; until it exists, extending the core allow-list is the only route for a type owned by another project.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)