2026-01-11 20:34.03: New job: test ahrefs/ocannl https://github.com/ahrefs/ocannl.git#refs/heads/master (0f3ca702cdde9b394bc974150ae39fff467ee69c) (linux-x86_64:(lint-fmt))Base: ocaml/opam:debian-13-ocaml-4.08@sha256:6fadef23b5069dc945f3a454c49421fd09e8c17aa57d3f9ad27d3879fce6aa44ocamlformat 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 0f3ca702cat > Dockerfile <<'END-OF-DOCKERFILE'FROM ocaml/opam:debian-13-ocaml-4.08@sha256:6fadef23b5069dc945f3a454c49421fd09e8c17aa57d3f9ad27d3879fce6aa44USER 1000:1000RUN cd ~/opam-repository && (git cat-file -e c65fcb116531ae66ad3316b265e233443ef25044 || git fetch origin master) && git reset -q --hard c65fcb116531ae66ad3316b265e233443ef25044 && 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-11 20:34.03: Using cache hint "ahrefs/ocannl-ocaml/opam:debian-13-ocaml-4.08@sha256:6fadef23b5069dc945f3a454c49421fd09e8c17aa57d3f9ad27d3879fce6aa44-debian-13-4.08_opam-2.5-ocamlformat-c65fcb116531ae66ad3316b265e233443ef25044"2026-01-11 20:34.03: Using OBuilder spec:((from ocaml/opam:debian-13-ocaml-4.08@sha256:6fadef23b5069dc945f3a454c49421fd09e8c17aa57d3f9ad27d3879fce6aa44)(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 c65fcb116531ae66ad3316b265e233443ef25044 || git fetch origin master) && git reset -q --hard c65fcb116531ae66ad3316b265e233443ef25044 && 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-11 20:34.03: Waiting for resource in pool OCluster2026-01-11 20:34.03: Waiting for worker…2026-01-11 20:34.04: Got resource from pool OClusterBuilding on bremusa.ocamllabs.ioAll commits already cachedHEAD is now at 0f3ca702 Fix d=1 handling in Concat projection components(from ocaml/opam:debian-13-ocaml-4.08@sha256:6fadef23b5069dc945f3a454c49421fd09e8c17aa57d3f9ad27d3879fce6aa44)2026-01-11 20:34.07 ---> using "c557567380599a9d74e9cba757661af503505628fe0a86c2e1639761275a17b1" 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 c65fcb116531ae66ad3316b265e233443ef25044 || git fetch origin master) && git reset -q --hard c65fcb116531ae66ad3316b265e233443ef25044 && git log --no-decorate -n1 --oneline && opam update -u"))From https://github.com/ocaml/opam-repository* branch master -> FETCH_HEADee48e882f0..a6b2f19780 master -> origin/masterc65fcb1165 Merge pull request #29080 from dra27/ocaml-config-urls<><> 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)The following actions will be performed:- recompile ocaml-base-compiler 4.08.1* [upstream changes]- recompile ocaml-config 1 [uses ocaml-base-compiler]- recompile ocaml 4.08.1 [uses ocaml-base-compiler]- recompile opam-depext 1.2.3 [uses ocaml]===== 4 to recompile =====<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>[ocaml-config.1/gen_ocaml_config.ml.in] downloaded from https://opam.ocaml.org/cache[opam-depext.1.2.3] downloaded from cache at https://opam.ocaml.org/cache[ocaml-base-compiler.4.08.1] downloaded from cache at https://opam.ocaml.org/cache[ocaml-config.1/ocaml-config.install] downloaded from https://opam.ocaml.org/cache[ocaml-base-compiler.4.08.1/alt-signal-stack.patch] downloaded from https://opam.ocaml.org/cache[ocaml-base-compiler.4.08.1/fix-gcc10.patch] downloaded from https://opam.ocaml.org/cache[ocaml-base-compiler.4.08.1/ocaml-base-compiler.install] downloaded from https://opam.ocaml.org/cache<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>-> removed opam-depext.1.2.3-> removed ocaml.4.08.1-> removed ocaml-config.1-> removed ocaml-base-compiler.4.08.1-> installed ocaml-base-compiler.4.08.1-> installed ocaml-config.1-> installed ocaml.4.08.1-> installed opam-depext.1.2.3Done.# Run eval $(opam env) to update the current shell environment2026-01-11 20:34.07 ---> using "16899c2fef5c54ba2a6b59b7d620ad4b67d2e0172975d17db354d347759a1972" from cache/: (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.20.2<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>[dune.3.20.2] found in cache<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>-> installed dune.3.20.2Done.# Run eval $(opam env) to update the current shell environment2026-01-11 20:34.07 ---> using "1468b5f7ce404b9299ebedec1ed552a4ca6fc39928d39e9b418130c05e92a7fc" from cache/: (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 cmdliner 2.1.0 [required by ocamlformat]- install csexp 1.5.2 [required by ocamlformat]- 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 dune-build-info 3.20.2 [required by ocamlformat-lib]- install ocaml-version 4.0.3 [required by ocamlformat-lib]- install dune-configurator 3.20.2 [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[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.20.2] found in cache[dune-configurator.3.20.2] found in cache[base.v0.14.3] downloaded from cache at https://opam.ocaml.org/cache[base.v0.14.3/fix-mpopcnt.patch] downloaded from https://opam.ocaml.org/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] downloaded from cache at https://opam.ocaml.org/cache[topkg.1.1.1] found in cache[stdio.v0.14.0] downloaded from cache at https://opam.ocaml.org/cache[uutf.1.0.4] found in cache[uuseg.15.0.0] downloaded from cache at https://opam.ocaml.org/cache[uucp.15.0.0] downloaded from cache at https://opam.ocaml.org/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 cmdliner.2.1.0-> installed menhirLib.20250912-> installed menhirSdk.20250912-> installed ocaml-version.4.0.3-> installed re.1.11.0-> installed sexplib0.v0.14.0-> installed dune-build-info.3.20.2-> installed dune-configurator.3.20.2-> 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 fpath.0.7.3-> installed menhir.20250912-> 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-11 20:34.07 ---> using "67ee4bd39bcc00fddad12fdceec092ff69a0ab03cc07acefc813f4637cfd01d9" from cache/src: (copy (src .) (dst /src/))2026-01-11 20:34.07 ---> saved as "bbb8b4ef1e3fe734979a7067cfa1c04c3331b458ea4bfbb344a3aa53dac87117"/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 "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 "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 9fe2745..112219e 100644--- a/_build/default/arrayjit/lib/assignments.ml+++ b/_build/default/arrayjit/lib/.formatted/assignments.ml@@ -406,8 +406,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@@ -423,8 +423,7 @@ 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 basecase block_iters rev_iters =let exception Empty_block in@@ -467,8 +466,7 @@ let%track4_sexp to_low_level code =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 =@@ -492,7 +490,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@@ -536,14 +535,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 |])@@ -552,7 +553,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/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 "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 78996bb..5fb1acb 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@@ -1877,10 +1878,9 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =~equal:(fun (_, _, s1) (_, _, s2) -> Idx.equal_symbol s1 s2)all_product_projs_with_itersin- (* 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. *)+ (* 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. *)let product_indices : Idx.axis_index list =List.filter_map all_dims ~f:(fun dim ->match dim with@@ -1913,9 +1913,7 @@ let%debug4_sexp derive_projections (update_step : update_step) : unit =in(* Union all symbols within each Concat group *)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)@@ -2336,7 +2334,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 d207b79..79cdef6 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 inFile "tensor/row.ml", line 1, characters 0-0:diff --git a/_build/default/tensor/row.ml b/_build/default/tensor/.formatted/row.mlindex 39de749..524b298 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 ()@@ -4207,12 +4209,10 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)let target_repr, _ =Utils.union_find ~equal:Proj_id.equal !proj_classes ~key:target_pid ~rank:0in- if not (Map.mem !projs target_repr) then (+ if not (Map.mem !projs target_repr) thenlet 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 *)@@ -4226,7 +4226,7 @@ let%debug4_sexp solve_proj_equations (eqs : proj_equation list)inprojs :=Map.set !projs ~key:target_repr- ~data:(if List.is_empty syms then Idx.Fixed_idx 0 else Idx.Concat syms)));+ ~data:(if List.is_empty syms then Idx.Fixed_idx 0 else Idx.Concat syms));{v_env;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-11 20:34.09: Job failed: Failed: Build failed