2026-01-20 15:50.47: New job: test ahrefs/ocannl https://github.com/ahrefs/ocannl.git#refs/heads/master (9517730f5abd78e4d3eb3d6e36149fa2aa7f9bf5) (linux-x86_64:(lint-fmt))Base: ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500ocamlformat version: version 0.28.1 (from opam)To reproduce locally:git clone --recursive "https://github.com/ahrefs/ocannl.git" -b "master" && cd "ocannl" && git reset --hard 9517730fcat > Dockerfile <<'END-OF-DOCKERFILE'FROM ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500USER 1000:1000RUN cd ~/opam-repository && (git cat-file -e 873cb18c37b308713d11ad3894c4bb78d73fb3e7 || git fetch origin master) && git reset -q --hard 873cb18c37b308713d11ad3894c4bb78d73fb3e7 && git log --no-decorate -n1 --oneline && opam update -uRUN opam depext -i duneWORKDIR /srcRUN opam depext -i ocamlformat=0.28.1COPY --chown=1000:1000 . /src/RUN opam exec -- dune build @fmt --ignore-promoted-rules || (echo "dune build @fmt failed"; exit 2)END-OF-DOCKERFILEdocker build .END-REPRO-BLOCK2026-01-20 15:50.47: Using cache hint "ahrefs/ocannl-ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500-debian-13-4.08_opam-2.5-ocamlformat-873cb18c37b308713d11ad3894c4bb78d73fb3e7"2026-01-20 15:50.47: Using OBuilder spec:((from ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500)(user (uid 1000) (gid 1000))(run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "cd ~/opam-repository && (git cat-file -e 873cb18c37b308713d11ad3894c4bb78d73fb3e7 || git fetch origin master) && git reset -q --hard 873cb18c37b308713d11ad3894c4bb78d73fb3e7 && git log --no-decorate -n1 --oneline && opam update -u"))(run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "opam depext -i dune"))(workdir /src)(run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "opam depext -i ocamlformat=0.28.1"))(copy (src .) (dst /src/))(run (shell "opam exec -- dune build @fmt --ignore-promoted-rules || (echo \"dune build @fmt failed\"; exit 2)")))2026-01-20 15:50.47: Waiting for resource in pool OCluster2026-01-20 15:50.47: Waiting for worker…2026-01-20 15:50.47: Got resource from pool OClusterBuilding on toxis.caelum.ci.devAll commits already cachedHEAD is now at 9517730f Merge pull request #424 from ahrefs/codex-ambiguous-concat(from ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500)Unable to find image 'ocaml/opam:debian-13-ocaml-4.08@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500' locallydocker.io/ocaml/opam@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500: Pulling from ocaml/opam281b80c799de: Already exists00fc4ac50d5e: Already exists7dc48a314bea: Already exists8f654937f9e3: Already exists1240f6fbe8cc: Already existsf77f967230a1: Already exists1b4ac3d9a8c2: Already exists27b61414175d: Already exists26fabf9b20e0: Already existsb4426e2c299b: Already exists9c12df827e83: Already exists9a5608646906: Already exists2a83342677ae: Already exists5cbaedd36b85: Already exists750a9830ac77: Already exists400560080670: Already existsbad13195b6fa: Already existsb51fe78b498e: Already exists185ce27e889b: Already exists8a483dc1e759: Already exists4de9d6d54a13: Already exists0c268a22c8a0: Already exists4f4fb700ef54: Already existse61881bc2621: Already existsc864a4af1ff0: Already exists42d012f62ad9: Already existsccb2ed78fa2e: Already exists84c22434b2f6: Already exists18c972827b32: Already exists4c6dcdff9e80: Already exists280bf9d33ca6: Already exists51ce8c29753c: Already exists5ac80663b9d2: Already exists93f877c915e3: Already exists8573ccc6bb69: Already existsd26192cd75ec: Already existsc7cce15b715e: Already existsc998ca7b5976: Already exists3cd1b61d806b: Already exists19a26ec5319e: Already existsb1f6813045f3: Already exists7a2b7a29296d: Pulling fs layer94a0ebb2d223: Pulling fs layer1c7f29f6d19a: Pulling fs layer1493b442f343: Pulling fs layer1493b442f343: Waiting1c7f29f6d19a: Verifying Checksum1c7f29f6d19a: Download complete94a0ebb2d223: Download complete1493b442f343: Verifying Checksum1493b442f343: Download complete7a2b7a29296d: Download complete7a2b7a29296d: Pull complete94a0ebb2d223: Pull complete1c7f29f6d19a: Pull complete1493b442f343: Pull completeDigest: sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea500Status: Downloaded newer image for ocaml/opam@sha256:7cdc2a1943ac1462f548be7816c6d02f14e605659f225027208abe04795ea5002026-01-20 15:50.48 ---> using "4c1f60dc0cc5644c6a4c05cf3315bdbf9cc478b70e443b212a1220385bab8bba" from cache/: (user (uid 1000) (gid 1000))/: (run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "cd ~/opam-repository && (git cat-file -e 873cb18c37b308713d11ad3894c4bb78d73fb3e7 || git fetch origin master) && git reset -q --hard 873cb18c37b308713d11ad3894c4bb78d73fb3e7 && git log --no-decorate -n1 --oneline && opam update -u"))From https://github.com/ocaml/opam-repository* branch master -> FETCH_HEADa6b2f19780..10a02a697b master -> origin/master873cb18c37 Merge pull request #29216 from shonfeder/release-dune-3.21.0<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><>[default] Initialiseddefault (at git+file:///home/opam/opam-repository):[INFO] opam 2.1 and 2.2 include many performance and security improvements over 2.0; please consider upgrading (https://opam.ocaml.org/doc/Install.html)Everything as up-to-date as possible (run with --verbose to show unavailable upgrades).However, you may "opam upgrade" these packages explicitly, which will ask permission to downgrade or uninstall the conflicting packages.Nothing to do.# Run eval $(opam env) to update the current shell environment2026-01-20 15:52.08 ---> saved as "72a7cd495abee3d0659c15140c96fff42d035222fc9b794ad453f1a5292cd6f1"/: (run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "opam depext -i dune"))# Detecting depexts using vars: arch=x86_64, os=linux, os-distribution=debian, os-family=debian# No extra OS packages requirements found.# All required OS packages found.# Now letting opam install the packagesThe following actions will be performed:- install dune 3.21.0<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>[dune.3.21.0] found in cache<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>-> installed dune.3.21.0Done.# Run eval $(opam env) to update the current shell environment2026-01-20 15:52.45 ---> saved as "3b5aee51bb4636e6dab95deb6944478b896d0b06f021712424b773f7d70073ac"/: (workdir /src)/src: (run (cache (opam-archives (target /home/opam/.opam/download-cache)))(network host)(shell "opam depext -i ocamlformat=0.28.1"))# Detecting depexts using vars: arch=x86_64, os=linux, os-distribution=debian, os-family=debian# No extra OS packages requirements found.# All required OS packages found.# Now letting opam install the packagesThe following actions will be performed:- install sexplib0 v0.14.0 [required by base]- install ocamlbuild 0.16.1 [required by fpath, astring, uuseg]- install either 1.0.0 [required by ocamlformat-lib]- install menhirLib 20250912 [required by ocamlformat-lib]- install csexp 1.5.2 [required by ocamlformat]- install dune-build-info 3.21.0 [required by ocamlformat-lib]- install camlp-streams 5.0.1 [required by ocamlformat-lib]- install seq base [required by re]- install menhirSdk 20250912 [required by ocamlformat-lib]- install fix 20250919 [required by ocamlformat-lib]- install menhirCST 20250912 [required by menhir]- install ocamlfind 1.9.8 [required by ocp-indent, astring, fpath, uuseg]- install ocaml-version 4.0.3 [required by ocamlformat-lib]- install cmdliner 2.1.0 [required by ocamlformat]- install dune-configurator 3.21.0 [required by base]- install re 1.11.0 [required by ocamlformat]- install menhir 20250912 [required by ocamlformat-lib]- install topkg 1.1.1 [required by fpath, astring, uuseg]- install ocp-indent 1.9.0 [required by ocamlformat-lib]- install base v0.14.3 [required by ocamlformat-lib]- install uutf 1.0.4 [required by ocamlformat-lib]- install astring 0.8.5 [required by ocamlformat-lib]- install stdio v0.14.0 [required by ocamlformat-lib]- install uucp 15.0.0 [required by uuseg]- install fpath 0.7.3 [required by ocamlformat-lib]- install uuseg 15.0.0 [required by ocamlformat-lib]- install ocamlformat-lib 0.28.1 [required by ocamlformat]- install ocamlformat 0.28.1===== 28 to install =====<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>[astring.0.8.5] found in cache[base.v0.14.3] found in cache[camlp-streams.5.0.1] found in cache[cmdliner.2.1.0] found in cache[csexp.1.5.2] found in cache[dune-build-info.3.21.0] found in cache[dune-configurator.3.21.0] found in cache[either.1.0.0] found in cache[fix.20250919] found in cache[fpath.0.7.3] found in cache[menhir.20250912] found in cache[menhirCST.20250912] found in cache[menhirLib.20250912] found in cache[menhirSdk.20250912] found in cache[ocaml-version.4.0.3] found in cache[ocamlbuild.0.16.1] found in cache[ocamlfind.1.9.8] found in cache[ocamlformat.0.28.1] found in cache[ocamlformat-lib.0.28.1] found in cache[ocp-indent.1.9.0] found in cache[re.1.11.0] found in cache[sexplib0.v0.14.0] found in cache[stdio.v0.14.0] found in cache[topkg.1.1.1] found in cache[uucp.15.0.0] found in cache[uuseg.15.0.0] found in cache[uutf.1.0.4] found in cache<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>-> installed seq.base-> installed camlp-streams.5.0.1-> installed csexp.1.5.2-> installed either.1.0.0-> installed fix.20250919-> installed menhirCST.20250912-> installed menhirLib.20250912-> installed menhirSdk.20250912-> installed ocaml-version.4.0.3-> installed sexplib0.v0.14.0-> installed re.1.11.0-> installed cmdliner.2.1.0-> installed dune-build-info.3.21.0-> installed dune-configurator.3.21.0-> installed ocamlfind.1.9.8-> installed ocp-indent.1.9.0-> installed ocamlbuild.0.16.1-> installed base.v0.14.3-> installed topkg.1.1.1-> installed stdio.v0.14.0-> installed uutf.1.0.4-> installed astring.0.8.5-> installed menhir.20250912-> installed fpath.0.7.3-> installed uucp.15.0.0-> installed uuseg.15.0.0-> installed ocamlformat-lib.0.28.1-> installed ocamlformat.0.28.1Done.<><> ocp-indent.1.9.0 installed successfully ><><><><><><><><><><><><><><><><><>=> This package requires additional configuration for use in editors. Install package 'user-setup', or manually:* for Emacs, add these lines to ~/.emacs:(add-to-list 'load-path "/home/opam/.opam/4.08/share/emacs/site-lisp")(require 'ocp-indent)* for Vim, add this line to ~/.vimrc:set rtp^="/home/opam/.opam/4.08/share/ocp-indent/vim"# Run eval $(opam env) to update the current shell environment2026-01-20 15:54.10 ---> saved as "feaec41ae6674b5392c1669250b45e7c9432e92ab5fcb8c64fb0ca2bc77dcd2b"/src: (copy (src .) (dst /src/))2026-01-20 15:54.12 ---> saved as "984e39e63899a90706c1d35ebf5c8f8dedb7742bb0f34dc491a94a1fe2e52af5"/src: (run (shell "opam exec -- dune build @fmt --ignore-promoted-rules || (echo \"dune build @fmt failed\"; exit 2)"))Warning: Invalid documentation comment:File "tensor/einsum_types.ml", line 39, characters 0-0:End of text is not allowed in '[...]' (code).File "test/ppx/test_ppx_op.ml", line 1, characters 0-0:diff --git a/_build/default/test/ppx/test_ppx_op.ml b/_build/default/test/ppx/.formatted/test_ppx_op.mlindex 3663191..41e2cf1 100644--- a/_build/default/test/ppx/test_ppx_op.ml+++ b/_build/default/test/ppx/.formatted/test_ppx_op.ml@@ -22,7 +22,6 @@ let z3 =let%op concat_single = { hey11 } ++^ "i=>i"let%op concat_pair = ({ hey12 }, { hey13 }) ++^ "i; j => i^j" [ "i"; "j" ]-let () = ignore (y0, y1, y2, a, b, y)let () = ignore (z, z2, z3)let () = ignore (concat_single, concat_pair)File "test/operations/test_concat_ppx.ml", line 1, characters 0-0:diff --git a/_build/default/test/operations/test_concat_ppx.ml b/_build/default/test/operations/.formatted/test_concat_ppx.mlindex c9676f8..7775d28 100644--- a/_build/default/test/operations/test_concat_ppx.ml+++ b/_build/default/test/operations/.formatted/test_concat_ppx.ml@@ -26,12 +26,8 @@ let () =let r3 = concat_capture t1 t2 inStdio.printf "concat_capture id: %d\n" r3.Tensor.id;- let p1 =- PDSL.ndarray [| 1.0; 2.0; 3.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] ()- in- let p2 =- PDSL.ndarray [| 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] ()- in+ let p1 = PDSL.ndarray [| 1.0; 2.0; 3.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] () in+ let p2 = PDSL.ndarray [| 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () inlet loss = sum_all (concat2 p1 p2) inlet ctx = Context.auto () inignore (Train.update_once ctx loss);File "test/operations/test_concat_graph.ml", line 1, characters 0-0:diff --git a/_build/default/test/operations/test_concat_graph.ml b/_build/default/test/operations/.formatted/test_concat_graph.mlindex 8d6b84a..980219d 100644--- a/_build/default/test/operations/test_concat_graph.ml+++ b/_build/default/test/operations/.formatted/test_concat_graph.ml@@ -12,9 +12,7 @@ let () =Tensor.unsafe_reinitialize ();(* Create two input tensors with different sizes *)- let x1 =- PDSL.ndarray [| 1.0; 2.0; 3.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] ()- in+ let x1 = PDSL.ndarray [| 1.0; 2.0; 3.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] () inlet x2 = PDSL.ndarray [| 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () in(* Concatenate and apply sin for a nice differentiable function *)@@ -54,12 +52,8 @@ let () =printf "\n=== Three-way Concatenation Forward and Backprop Graph Test ===\n\n%!";(* Create three input tensors with different sizes *)let x1_3 = PDSL.ndarray [| 1.0; 2.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () in- let x2_3 =- PDSL.ndarray [| 3.0; 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] ()- in- let x3_3 =- PDSL.ndarray [| 6.0; 7.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] ()- in+ let x2_3 = PDSL.ndarray [| 3.0; 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 3 ] () in+ let x3_3 = PDSL.ndarray [| 6.0; 7.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () in(* Concatenate and apply sin *)let%op result3 = sin ((x1_3, x2_3, x3_3) ++^ "a; b; c => a^b^c") in@@ -104,9 +98,7 @@ let () =(* One concatenated dimension is 1 to exercise Fixed_idx 0 behavior. *)let x1_u = PDSL.ndarray [| 1.0; 2.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () inlet x2_u = PDSL.ndarray [| 3.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 1 ] () in- let x3_u =- PDSL.ndarray [| 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] ()- in+ let x3_u = PDSL.ndarray [| 4.0; 5.0 |] ~batch_dims:[] ~input_dims:[] ~output_dims:[ 2 ] () inlet%op result_u = sin ((x1_u, x2_u, x3_u) ++^ "a; b; c => a^b^c") inlet%op loss_u = result_u ++ "...|... => 0" inFile "tensor/ppx_op.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/ppx_op.ml b/_build/default/tensor/.formatted/ppx_op.mlindex fadd7c3..28f8d84 100644--- a/_build/default/tensor/ppx_op.ml+++ b/_build/default/tensor/.formatted/ppx_op.ml@@ -183,8 +183,7 @@ let rec translate ~no_grads_for_inline_defs ~num_configs ~is_toplevel ~opt_label(vbs, Ast_builder.Default.pexp_array ~loc [ e ])inlet spec = substitute_identifiers_in_einsum_spec ~loc spec_str in- ( vbs1,- [%expr concat ?label:[%e opt_expr ~loc label] [%e spec] [%e rhses_expr]] )+ (vbs1, [%expr concat ?label:[%e opt_expr ~loc label] [%e spec] [%e rhses_expr]])| [%expr[%e? { pexp_desc = Pexp_ident { txt = Lident "++^"; _ }; _ }][%e? expr1]File "tensor/operation.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/operation.ml b/_build/default/tensor/.formatted/operation.mlindex b390494..5dda887 100644--- a/_build/default/tensor/operation.ml+++ b/_build/default/tensor/.formatted/operation.ml@@ -469,9 +469,9 @@ let concat_sum ?(capture_dims = []) ?(negated = false) spec ?grad_spec rhses =accum = Ir.Ops.Add;lhs = g;rhs = Asgns.Rev_sides { op; lhses };- projections = projections.Tensor.projections;- projections_debug = projections.Tensor.projections_debug;- }+ projections = projections.Tensor.projections;+ projections_debug = projections.Tensor.projections_debug;+ }inTensor.blockop ~op_label:"++^" ~spec ~delayed_vars:capture_dims ~op_asn ~grad_asn ?grad_spec rhses@@ -816,10 +816,13 @@ structlet einsum1 ?label ?capture_dims spec t1 = einsum1 ?label ?capture_dims spec t1 ()let einmax1 ?label ?capture_dims spec t1 = einmax1 ?label ?capture_dims spec t1 ()let tropical ?label ?capture_dims spec t1 t2 = tropical ?label ?capture_dims spec t1 t2 ()+let concat_sum ?label ?capture_dims ?negated spec rhses =concat_sum ?label ?capture_dims ?negated spec rhses ()+let concat ?label ?capture_dims ?negated spec rhses =concat ?label ?capture_dims ?negated spec rhses ()+let offsets ?label () = offsets ?label ()let uniform ?label () = uniform () ?label ()let uniform_at ?label counter = uniform_at ?label counter ()File "arrayjit/lib/assignments.ml", line 1, characters 0-0:diff --git a/_build/default/arrayjit/lib/assignments.ml b/_build/default/arrayjit/lib/.formatted/assignments.mlindex 449c853..185039d 100644--- a/_build/default/arrayjit/lib/assignments.ml+++ b/_build/default/arrayjit/lib/.formatted/assignments.ml@@ -286,8 +286,7 @@ let%track4_sexp to_low_level code =Array.fold2_exn projections.product_space projections.product_iterators~init:(Map.empty (module Indexing.Symbol))~f:(fun acc ds its ->- List.fold2_exn ds its ~init:acc ~f:(fun acc d iter ->- Map.set acc ~key:iter ~data:d))+ List.fold2_exn ds its ~init:acc ~f:(fun acc d iter -> Map.set acc ~key:iter ~data:d))inlet concat_offset_for syms active =let _, offset =@@ -302,8 +301,8 @@ let%track4_sexp to_low_level code =(* Create a substitution from product iterators to loop iterators. Fresh loop symbols areneeded because product_iterators may be shared across different operations/tensors, buteach lowered operation needs private loop symbols to avoid conflicts in low_level.ml's- symbol-to-tensor tracking.- Concat offsets are computed per Concat index using symbol order. *)+ symbol-to-tensor tracking. Concat offsets are computed per Concat index using symbol+ order. *)let exception Empty_block inlet block_iters = Array.of_list_rev block_iters inlet concat_syms_opt =@@ -342,9 +341,9 @@ let%track4_sexp to_low_level code =| Some (Indexing.Fixed_idx _) | Some Indexing.Sub_axis | None -> (coeff, s))inIndexing.Affine { symbols; offset }- | Indexing.Concat syms ->- (* For Block lowering: find the active component (in block_iters) and resolve to it- with the appropriate offset based on Concat symbol order. *)+ | Indexing.Concat syms -> (+ (* For Block lowering: find the active component (in block_iters) and resolve to it with+ the appropriate offset based on Concat symbol order. *)let active =List.find_mapi syms ~f:(fun _i s ->if Array.mem ~equal:Indexing.equal_symbol block_iters s then@@ -355,13 +354,14 @@ let%track4_sexp to_low_level code =| _ -> Noneelse None)in- (match active with+ match active with| Some (s', 0) -> Indexing.Iterator s'| Some (s', offset) -> Indexing.Affine { symbols = [ (1, s') ]; offset }| None ->raise@@ Utils.User_error- "Concat index could not be resolved to an active component during Block lowering")+ "Concat index could not be resolved to an active component during Block \+ lowering")intrylet lhs_idcs : Indexing.axis_index array =@@ -449,8 +449,8 @@ let%track4_sexp to_low_level code =let fetch_op = Constant neutral_value inLow_level.Seq (loop (Fetch { array = lhs; fetch_op; dims }), for_loops_with_resets)else for_loops_with_resets- and loop_accum_rev ~initialize_neutral ~accum ~(op : Ops.op) ~lhs ~lhses projections :- Low_level.t =+ and loop_accum_rev ~initialize_neutral ~accum ~(op : Ops.op) ~lhs ~lhses projections : Low_level.t+ =let projections : Indexing.projections = Lazy.force projections inlet all_prod_iters =Array.to_list projections.product_iterators@@ -466,15 +466,13 @@ let%track4_sexp to_low_level code =inlet target_needs_init =Array.map target_projections ~f:(fun proj ->- initialize_neutral- && not (Indexing.is_surjective proj && Indexing.is_injective proj))+ initialize_neutral && not (Indexing.is_surjective proj && Indexing.is_injective proj))inlet iter_sizes =Array.fold2_exn projections.product_space projections.product_iterators~init:(Map.empty (module Indexing.Symbol))~f:(fun acc ds its ->- List.fold2_exn ds its ~init:acc ~f:(fun acc d iter ->- Map.set acc ~key:iter ~data:d))+ List.fold2_exn ds its ~init:acc ~f:(fun acc d iter -> Map.set acc ~key:iter ~data:d))inlet concat_offset_for syms active =let _, offset =@@ -523,7 +521,7 @@ let%track4_sexp to_low_level code =| Some (Indexing.Fixed_idx _) | Some Indexing.Sub_axis | None -> (coeff, s))inIndexing.Affine { symbols; offset }- | Indexing.Concat syms ->+ | Indexing.Concat syms -> ((* For Rev_sides lowering: find the active component and resolve with offset *)let active =List.find_mapi syms ~f:(fun _i s ->@@ -535,18 +533,18 @@ let%track4_sexp to_low_level code =| _ -> Noneelse None)in- (match active with+ match active with| Some (s', 0) -> Indexing.Iterator s'| Some (s', offset) -> Indexing.Affine { symbols = [ (1, s') ]; offset }| None ->raise@@ Utils.User_error- "Concat index could not be resolved to an active component during Rev_sides lowering")+ "Concat index could not be resolved to an active component during Rev_sides \+ lowering")inlet target_tn_exn = function| Node tn -> tn- | Merge_buffer _ ->- raise @@ Utils.User_error "Rev_sides cannot write to merge buffers"+ | Merge_buffer _ -> raise @@ Utils.User_error "Rev_sides cannot write to merge buffers"intrylet rhs_idcs : Indexing.axis_index array =@@ -577,7 +575,8 @@ let%track4_sexp to_low_level code =let rhs2 = apply_op op [| rhs_ll |] inlet target_tn = target_tn_exn target_buf inif initialize_neutral && target_can_skip.(i) then set target_tn lhs_idcs rhs2- else set target_tn lhs_idcs @@ apply_op (Ops.Binop accum) [| get target_buf lhs_idcs; rhs2 |]+ else+ set target_tn lhs_idcs @@ apply_op (Ops.Binop accum) [| get target_buf lhs_idcs; rhs2 |]with Empty_block -> Low_level.Noopinlet rec for_loop block_iters rev_iters = function@@ -621,14 +620,16 @@ let%track4_sexp to_low_level code =| Merge_buffer _ ->raise @@ Utils.User_error "Rev_sides cannot initialize merge buffers"in- Some (Fetch { array; fetch_op = Constant neutral_value; dims = lazy projections.rhs_dims.(i) }))+ Some+ (Fetch+ { array; fetch_op = Constant neutral_value; dims = lazy projections.rhs_dims.(i) }))|> Array.to_listinif List.is_empty init_ops then for_loops_with_resetselse Low_level.unflat_lines (List.map init_ops ~f:loop @ [ for_loops_with_resets ])and loop (code : t) : Low_level.t =match code with- | Accum_op { initialize_neutral; accum; lhs; rhs; projections; _ } ->+ | Accum_op { initialize_neutral; accum; lhs; rhs; projections; _ } -> (let op, rhses =match rhs with| Unop { op; rhs } -> (Ops.Unop op, [| rhs |])@@ -637,7 +638,7 @@ let%track4_sexp to_low_level code =| Block { op; rhses } -> (Ops.Unop op, rhses)| Rev_sides { op; lhses } -> (Ops.Unop op, lhses)in- (match rhs with+ match rhs with| Rev_sides _ -> loop_accum_rev ~initialize_neutral ~accum ~op ~lhs ~lhses:rhses projections| _ -> loop_accum ~initialize_neutral ~accum ~op ~lhs ~rhses projections)| Set_vec_unop { op; lhs; rhs; projections; _ } ->File "tensor/tensor.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/tensor.ml b/_build/default/tensor/.formatted/tensor.mlindex d8bdf41..ff82fef 100644--- a/_build/default/tensor/tensor.ml+++ b/_build/default/tensor/.formatted/tensor.ml@@ -355,7 +355,7 @@ let%track7_sexp op ~(label : string list) ?(ternary_op = Shape.Pointwise_tern)| [ t1; t2; t3 ] -> Shape.Broadcast_tern (ternary_op, t1.shape, t2.shape, t3.shape)| _ ->(* Let's implement what we need when we need it. *)- assert false )+ assert false)inlet embedded_nodes = ref @@ Set.singleton (module Tn) v inlet children =@@ -370,7 +370,14 @@ let%track7_sexp op ~(label : string list) ?(ternary_op = Shape.Pointwise_tern)let params = Set.union_list (module T) @@ List.map ordered_ts ~f:(fun ti -> ti.params) in(* Create a preliminary shape_update to get projections_debug and projections for op_asn. *)let preliminary_shape_update =- Shape.{ shape; logic = shape_logic; id = get_update_id (); unsafe_projections = None; neutral_elem = None }+ Shape.+ {+ shape;+ logic = shape_logic;+ id = get_update_id ();+ unsafe_projections = None;+ neutral_elem = None;+ }inShape.propagate_shapes preliminary_shape_update;let projections_debug = Shape.logic_to_spec preliminary_shape_update.logic in@@ -527,6 +534,7 @@ let%track7_sexp blockop ?op_label ~spec ~delayed_vars ~op_asn ~grad_asn ?grad_sp(Shape.make ?batch_dims ?input_dims ?output_dims ?batch_axes ?input_axes ?output_axes ?deduced())rhses_list+let%track7_sexp unop ?op_label ?transpose_op ~op_asn ~grad_asn ?grad_spec t1 ?(label = [])?top_down_prec ?batch_dims ?batch_axes ?input_dims ?output_dims ?input_axes ?output_axes?deduced () : t =File "tensor/shape.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/shape.ml b/_build/default/tensor/.formatted/shape.mlindex db46566..b1654fb 100644--- a/_build/default/tensor/shape.ml+++ b/_build/default/tensor/.formatted/shape.ml@@ -269,7 +269,8 @@ let einsum_slot_spec_to_dims_bio ~original_spec ~sh_id ~row_var_env ~dim_var_envlet dims =List.map labels ~f:(fun label ->Row.Var- (Hashtbl.find_or_add dim_var_env label ~default:(fun () -> Row.get_var ~name:label ())))+ (Hashtbl.find_or_add dim_var_env label ~default:(fun () ->+ Row.get_var ~name:label ())))inRow.Concat dimsin@@ -284,14 +285,13 @@ let add_var_used_in_spec_or_compose row =let add_var_used_in_pointwise row =match row with Row.Row_var { v; _ } -> Row.add_used_in_pointwise v | _ -> ()-(* For Block specs, compute invalid_vars: variables that are allowed to be 0.- A variable v is invalid if:- 1. v appears in a component of a Concat dimension on one side- 2. For ALL shapes on the other side, there EXISTS an axis such that for ALL components- of that axis, the complement of v's component has non-empty intersection.- This is a four-quantifier condition: ∀shapes ∃axis ∀components: complement ∩ component ≠∅ *)-let compute_block_invalid_vars ~(this_side_rows : Row.t list)- ~(other_side_shapes : Row.t list list) : Row.dim_var_set =+(* For Block specs, compute invalid_vars: variables that are allowed to be 0. A variable v is+ invalid if: 1. v appears in a component of a Concat dimension on one side 2. For ALL shapes on+ the other side, there EXISTS an axis such that for ALL components of that axis, the complement of+ v's component has non-empty intersection. This is a four-quantifier condition: ∀shapes ∃axis+ ∀components: complement ∩ component ≠∅ *)+let compute_block_invalid_vars ~(this_side_rows : Row.t list) ~(other_side_shapes : Row.t list list)+ : Row.dim_var_set =(* Extract all dims from rows (including beg_dims from bcast) *)let dims_of_rows rows =List.concat_map rows ~f:(fun (row : Row.t) ->@@ -300,9 +300,8 @@ let compute_block_invalid_vars ~(this_side_rows : Row.t list)inrow.dims @ dims_from_bcast)in- (* Get component var sets for each axis.- For non-Concat dims, there's one component with all vars of that dim.- For Concat dims, each element is a separate component. *)+ (* Get component var sets for each axis. For non-Concat dims, there's one component with all vars+ of that dim. For Concat dims, each element is a separate component. *)let axis_components_of_dim (dim : Row.dim) : Row.dim_var_set list =match dim with| Row.Concat dims -> List.map dims ~f:Row.vars_of_dim@@ -313,8 +312,8 @@ let compute_block_invalid_vars ~(this_side_rows : Row.t list)List.map other_side_shapes ~f:(fun shape_rows ->List.map (dims_of_rows shape_rows) ~f:axis_components_of_dim)in- (* For each Concat on this side, find invalid vars.- Non-Concat dims cannot contribute invalid vars since their complement is empty. *)+ (* For each Concat on this side, find invalid vars. Non-Concat dims cannot contribute invalid vars+ since their complement is empty. *)let this_side_dims = dims_of_rows this_side_rows inList.fold this_side_dims ~init:Row.dim_var_set_empty ~f:(fun acc dim ->match dim with@@ -1296,8 +1295,8 @@ let%debug4_sexp get_inequalities ?(for_projections = false)let rhs_results =List.mapi (List.zip_exn ls_rhses rhses) ~f:(fun i (ls_rhs, sh) ->let extras, proj_env, (b, inp, o) =- einsum_slot_spec_to_dims_bio ~original_spec:spec ~sh_id:sh.id ~row_var_env ~dim_var_env- ls_rhs+ einsum_slot_spec_to_dims_bio ~original_spec:spec ~sh_id:sh.id ~row_var_env+ ~dim_var_env ls_rhsin(i, sh, extras, proj_env, b, inp, o))in@@ -1339,7 +1338,8 @@ let%debug4_sexp get_inequalities ?(for_projections = false)Rows_constr{r = [ Row.get_row_for_var Row.empty_provenance var ];- constr = Total_elems { numerator = Num_elems solved_dim; divided_by = [] };+ constr =+ Total_elems { numerator = Num_elems solved_dim; divided_by = [] };origin =[{@@ -1416,17 +1416,18 @@ let%debug4_sexp get_inequalities ?(for_projections = false)};])in- (* Compute invalid_vars: variables that are allowed to be 0 (dimension 0 is invalid).- A variable is invalid if it's in a Concat component whose complement covers an axis- on the other side. We check both directions: RHS->LHS and LHS->RHS.- The four-quantifier condition: ∀shapes ∃axis ∀components: complement ∩ component ≠∅ *)+ (* Compute invalid_vars: variables that are allowed to be 0 (dimension 0 is invalid). A+ variable is invalid if it's in a Concat component whose complement covers an axis on the+ other side. We check both directions: RHS->LHS and LHS->RHS. The four-quantifier condition:+ ∀shapes ∃axis ∀components: complement ∩ component ≠∅ *)let rhs_shapes : Row.t list list =List.map rhs_results ~f:(fun (_, _, _, _, b_rhs, i_rhs, o_rhs) -> [ b_rhs; i_rhs; o_rhs ])inlet lhs_rows = [ b_lhs; i_lhs; o_lhs ] in(* LHS is a single shape, so wrap it in a singleton list for the shapes parameter *)let invalid_from_rhs =- compute_block_invalid_vars ~this_side_rows:(List.concat rhs_shapes) ~other_side_shapes:[ lhs_rows ]+ compute_block_invalid_vars ~this_side_rows:(List.concat rhs_shapes)+ ~other_side_shapes:[ lhs_rows ]inlet invalid_from_lhs =compute_block_invalid_vars ~this_side_rows:lhs_rows ~other_side_shapes:rhs_shapes@@ -1806,8 +1807,8 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =(* We will not use the old inferred padding so that we can derive precisely the paddingcontributed by this step. *)let _debug_update_step : update_step = update_step in- let (proj_axis_env, invalid_vars, ineqs) :- proj_axis_env * Row.dim_var_set * Row.constraint_ list =+ let (proj_axis_env, invalid_vars, ineqs) : proj_axis_env * Row.dim_var_set * Row.constraint_ list+ =get_inequalities ~for_projections:true update_stepin(* We need to solve the equations/inequalities one last time because of fresh row variables@@ -1883,12 +1884,10 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =(module Idx.Symbol)(Row.product_dim_iterators proj_env |> List.map ~f:(fun (p, d, s) -> (s, (p, d))))in- (* Build connected components from Concat indices.- Symbols that appear together in a Concat must be iterated together.- We use union-find to group symbols into connected components.- Include both product dimensions and Concat dimensions.- Note: Concat can appear either as Row.Concat dim or as a regular Dim whose- proj_id maps to Idx.Concat. *)+ (* Build connected components from Concat indices. Symbols that appear together in a Concat must+ be iterated together. We use union-find to group symbols into connected components. Include+ both product dimensions and Concat dimensions. Note: Concat can appear either as Row.Concat dim+ or as a regular Dim whose proj_id maps to Idx.Concat. *)let product_indices : Idx.axis_index list =List.filter_map all_dims ~f:(fun dim ->match dim with@@ -1913,12 +1912,11 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =inlet unique_by_iterator =let seen =- Set.of_list- (module Idx.Symbol)- (List.map unique_by_iterator ~f:(fun (_, _, s) -> s))+ Set.of_list (module Idx.Symbol) (List.map unique_by_iterator ~f:(fun (_, _, s) -> s))inlet missing_symbols =- concat_groups |> List.concat |> Utils.unique_keep_first ~equal:Idx.equal_symbol+ concat_groups |> List.concat+ |> Utils.unique_keep_first ~equal:Idx.equal_symbol|> List.filter ~f:(fun s -> not (Set.mem seen s))inlet missing_entries =@@ -1927,13 +1925,11 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =inunique_by_iterator @ missing_entriesin- (* Union-find to group symbols that appear in the same Concat.- Symbols within the same Concat must be in the same iteration group so that- they are iterated SEQUENTIALLY (via unflat_lines), not NESTED.- For (a, b) ++^ "a; b => a^b", i2 and i3 should be in the same group:- - First iterate i2 (RHS[0] active)- - Then iterate i3 (RHS[1] active)- This is achieved by making them part of the same product_iterators entry. *)+ (* Union-find to group symbols that appear in the same Concat. Symbols within the same Concat must+ be in the same iteration group so that they are iterated SEQUENTIALLY (via unflat_lines), not+ NESTED. For (a, b) ++^ "a; b => a^b", i2 and i3 should be in the same group: - First iterate i2+ (RHS[0] active) - Then iterate i3 (RHS[1] active) This is achieved by making them part of the+ same product_iterators entry. *)let symbol_classes : (Idx.symbol, Idx.symbol) Hashtbl.t = Hashtbl.create (module Idx.Symbol) inlet find_repr sym =let rec loop s =@@ -1953,9 +1949,7 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =in(* Union all symbols within each Concat group to make them iterate sequentially *)List.iter concat_groups ~f:(fun syms ->- match syms with- | [] -> ()- | first :: rest -> List.iter rest ~f:(fun s -> union first s));+ match syms with [] -> () | first :: rest -> List.iter rest ~f:(fun s -> union first s));(* Group unique_by_iterator entries by their representative symbol *)let components : (Idx.symbol, (Row.proj_id * int * Idx.symbol) list) Hashtbl.t =Hashtbl.create (module Idx.Symbol)@@ -2376,7 +2370,8 @@ let shape_spec_to_dims_bio labels =let dims =List.map labels ~f:(fun label ->Row.Var- (Hashtbl.find_or_add dim_var_env label ~default:(fun () -> Row.get_var ~name:label ())))+ (Hashtbl.find_or_add dim_var_env label ~default:(fun () ->+ Row.get_var ~name:label ())))inRow.Concat dimsinFile "arrayjit/lib/low_level.ml", line 1, characters 0-0:diff --git a/_build/default/arrayjit/lib/low_level.ml b/_build/default/arrayjit/lib/.formatted/low_level.mlindex 7bb5852..5359d1f 100644--- a/_build/default/arrayjit/lib/low_level.ml+++ b/_build/default/arrayjit/lib/.formatted/low_level.ml@@ -269,7 +269,8 @@ let visit_llc traced_store ~merge_node_id reverse_node_map ~max_visits llc =| Indexing.Concat _syms ->(* Concat should be eliminated during lowering before we get here *)invalid_arg- "BUG: Concat index encountered during virtualization - should have been eliminated during lowering")+ "BUG: Concat index encountered during virtualization - should have been eliminated \+ during lowering")inlet rec loop_proc ~first_visit env llc =let loop = loop_proc ~first_visit env in@@ -308,9 +309,9 @@ let visit_llc traced_store ~merge_node_id reverse_node_map ~max_visits llc =traced.is_accessing <- traced.is_accessing || is_accessing_comp traced_store llsc;traced.is_complex <- traced.is_complex || is_complex_comp traced_store llsc);Hash_set.add traced.assignments (lookup env idcs);- (* Track which tensor uses which symbol. When multiple tensors share a symbol- (e.g., in Block/concat lowering), mark both as complex to disable virtualization.- See TODO(#134): this prevents multiple virtual arrays from sharing for loops. *)+ (* Track which tensor uses which symbol. When multiple tensors share a symbol (e.g., in+ Block/concat lowering), mark both as complex to disable virtualization. See TODO(#134):+ this prevents multiple virtual arrays from sharing for loops. *)let track_symbol s =match Hashtbl.find reverse_node_map s with| None -> Hashtbl.set reverse_node_map ~key:s ~data:tnFile "tensor/row.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/row.ml b/_build/default/tensor/.formatted/row.mlindex 898e33e..1534f31 100644--- a/_build/default/tensor/row.ml+++ b/_build/default/tensor/.formatted/row.ml@@ -2424,9 +2424,11 @@ let%track5_sexp solve_dim_ineq ~(stage : stage) origin ~(cur : dim) ~(subr : dim(* Element-wise unification of concatenated dimensions *)let eqs = List.map2_exn dims1 dims2 ~f:(fun d1 d2 -> Dim_eq { d1; d2; origin }) in(eqs, env)- | _, Concat dims when List.count dims ~f:(function Var v -> Set.mem env.invalid_vars v | _ -> false) >= List.length dims - 1 ->- (* Concat in subr position with all-but-one (or all) components being invalid vars:- preserve inequality so the solver can infer the variables *)+ | _, Concat dims+ when List.count dims ~f:(function Var v -> Set.mem env.invalid_vars v | _ -> false)+ >= List.length dims - 1 ->+ (* Concat in subr position with all-but-one (or all) components being invalid vars: preserve+ inequality so the solver can infer the variables *)([ Dim_ineq { cur; subr; from_ = Sexp.List []; origin } ], env)| Concat _, _ | _, Concat _ ->(* Defer to dimension equality for concat with non-concat *)@@ -2941,13 +2943,13 @@ let%debug5_sexp rec close_dim_terminal ~(stage : stage) ~is_param origin env (di(* The input dimension itself cannot be dim-1, and the over dimension doesn't becometransitively terminal. *)[]- | Concat dims ->- (* For concatenation, filter out dimension-0 components and if one remains, close it.- TODO: Consider guessing invalid_vars components to 0 at stage 6, but wait until needed. *)+ | Concat dims -> (+ (* For concatenation, filter out dimension-0 components and if one remains, close it. TODO:+ Consider guessing invalid_vars components to 0 at stage 6, but wait until needed. *)let non_zero_dims = List.filter dims ~f:(function Dim { d = 0; _ } -> false | _ -> true) in- (match non_zero_dims with- | [ single ] -> close_dim_terminal ~stage ~is_param origin env single- | _ -> [])+ match non_zero_dims with+ | [ single ] -> close_dim_terminal ~stage ~is_param origin env single+ | _ -> [])let last_dim_is dims p = match List.last dims with Some (Dim { d; _ }) -> p d | _ -> false@@ -3214,8 +3216,7 @@ let%track5_sexp close_row_terminal ~(stage : stage) ~is_param origin envlet%debug5_sexp eliminate_dim_entry stage origin env v ~lub constr =let guess_dim () =- if Set.mem env.invalid_vars v then get_dim ~d:0 ~proj_id:56 ()- else get_dim ~d:1 ~proj_id:59 ()+ if Set.mem env.invalid_vars v then get_dim ~d:0 ~proj_id:56 () else get_dim ~d:1 ~proj_id:59 ()inmatch (lub, constr) with| Some (Dim { d; _ } as lub), At_least_dim d2 when d2 > d ->@@ -3232,8 +3233,7 @@ let%debug5_sexp eliminate_dim_entry stage origin env v ~lub constr =Some (Dim_eq { d1 = Var v; d2 = lub; origin })| None, At_least_dim d when is_stage7 stage ->Some (Dim_eq { d1 = Var v; d2 = get_dim ~d ~proj_id:58 (); origin })- | None, _ when is_stage7 stage ->- Some (Dim_eq { d1 = Var v; d2 = guess_dim (); origin })+ | None, _ when is_stage7 stage -> Some (Dim_eq { d1 = Var v; d2 = guess_dim (); origin })| _ -> Nonelet%track5_sexp process_shape_row ~(stage : stage) origin env ({ dims; bcast; prov } as r : row) :@@ -3245,12 +3245,12 @@ let%track5_sexp process_shape_row ~(stage : stage) origin env ({ dims; bcast; pr| Affine { over; conv = Some { kernel; _ }; _ } ->finalize_upper_lower_bound over @ finalize_upper_lower_bound kernel| Concat dims -> List.concat_map dims ~f:finalize_upper_lower_bound- | Var v ->+ | Var v -> (let guess_dim () =if Set.mem env.invalid_vars v then get_dim ~d:0 ~proj_id:61 ()else get_dim ~d:1 ~proj_id:62 ()in- (match find_dim env.dim_env v with+ match find_dim env.dim_env v with| Some (Bounds_dim { is_in_param = true; _ }) when final ->raise@@ Shape_error@@ -3993,8 +3993,10 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)let verify_when_solved2 = ref [] inlet p_dims = ref [] inlet iterated_vars = ref [] in- let p_concat_targets = ref [] in (* (target_pid, component proj_dims) for deferred Concat handling *)- let p_concat_components = ref @@ Set.empty (module Proj_id) in (* proj_ids that are Concat components *)+ let p_concat_targets = ref [] in+ (* (target_pid, component proj_dims) for deferred Concat handling *)+ let p_concat_components = ref @@ Set.empty (module Proj_id) in+ (* proj_ids that are Concat components *)let proj_classes = ref @@ Map.empty (module Proj_id) inlet rec loop (eq : proj_equation) : unit =match eq with@@ -4019,8 +4021,8 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)| None -> c.target_id <- Some p);(* We will substitute variables in conv_input later *)p_conv_input := (p, conv_input) :: !p_conv_input- | Proj_eq (Solved idx, (Conv_input _ | Concat _ as conv_input))- | Proj_eq ((Conv_input _ | Concat _ as conv_input), Solved idx) ->+ | Proj_eq (Solved idx, ((Conv_input _ | Concat _) as conv_input))+ | Proj_eq (((Conv_input _ | Concat _) as conv_input), Solved idx) ->verify_when_solved1 := (idx, conv_input) :: !verify_when_solved1| Proj_eq( (Conv_input { stride = stride1; over = over1; _ } as conv_input1),@@ -4029,7 +4031,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)loop (Proj_eq (over1, over2));if equal_proj conv_input1 conv_input2 then ()else verify_when_solved2 := (conv_input1, conv_input2) :: !verify_when_solved2- | Proj_eq ((Conv_input _ as conv_input1), (Conv_input _ | Concat _ as conv_input2))+ | Proj_eq ((Conv_input _ as conv_input1), ((Conv_input _ | Concat _) as conv_input2))| Proj_eq ((Concat _ as conv_input1), (Conv_input _ as conv_input2)) ->(* Conv_input vs Conv_input/Concat - defer verification *)if equal_proj conv_input1 conv_input2 then ()@@ -4110,7 +4112,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)(module Proj_id)(Set.to_list !p_concat_components|> List.map ~f:(fun p ->- fst @@ Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0))+ fst @@ Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0))inList.iter !p_solved ~f:(fun (p, idx) ->let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in@@ -4150,8 +4152,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)[] )));List.iter concat_dims ~f:(fun (p, d) ->let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:p ~rank:0 in- if not @@ Map.mem !product_dim repr then- product_dim := Map.set !product_dim ~key:repr ~data:d);+ if not @@ Map.mem !product_dim repr then product_dim := Map.set !product_dim ~key:repr ~data:d);(* Create fresh iterators for product dimensions, EXCEPT for those that will get their index fromConv_input (they will be processed later). *)Map.iteri !product_dim ~f:(fun ~key:p ~data:_ ->@@ -4232,9 +4233,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)inlet syms =List.filter_map proj_dims ~f:(fun (pid, { d; _ }) ->- let repr, _ =- Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:pid ~rank:0- in+ let repr, _ = Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:pid ~rank:0 inmatch Map.find !projs repr with| Some (Idx.Iterator s) -> Some s| Some (Idx.Fixed_idx 0) when d = 0 -> None (* d=0 is invalid dimension, skip *)@@ -4246,9 +4245,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)"Concat component projection %{pid#Proj_id} (d=%{d#Int}) has no iterator"],[] ))in- let expected_idx =- if List.is_empty syms then Idx.Fixed_idx 0 else Idx.Concat syms- in+ let expected_idx = if List.is_empty syms then Idx.Fixed_idx 0 else Idx.Concat syms inmatch Map.find !projs target_repr with| None -> projs := Map.set !projs ~key:target_repr ~data:expected_idx| Some existing_idx ->@@ -4312,6 +4309,6 @@ let proj_to_iterator_exn proj_env p =let product_dim_iterators proj_env =Map.to_alist proj_env.product_dim|> List.filter_map ~f:(fun (p, d) ->- match Map.find proj_env.proj_to_index p with- | Some (Idx.Iterator s) -> Some (p, d, s)- | _ -> None)+ match Map.find proj_env.proj_to_index p with+ | Some (Idx.Iterator s) -> Some (p, d, s)+ | _ -> None)dune build @fmt failed"/usr/bin/env" "bash" "-c" "opam exec -- dune build @fmt --ignore-promoted-rules || (echo "dune build @fmt failed"; exit 2)" failed with exit status 22026-01-20 15:54.14: Job failed: Failed: Build failed