     [ at+ ]
     [ 3drop ] if ; inline
 
-:: check-variables ( vars declared actual -- ? )
-    actual terminated?>> [ t ] [
-        actual declared [ in>>  length ] bi@ declared in-var>>
-            [ vars check-variable ] keep :> ( in-diff in-ok? in-var ) 
-        actual declared [ out>> length ] bi@ declared out-var>>
-            [ vars check-variable ] keep :> ( out-diff out-ok? out-var )
-        { [ in-ok? ] [ out-ok? ] [ in-diff out-diff = ] } 0&&
-        dup [
-            in-var  [ in-diff  swap vars adjust-variable ] when*
-            out-var [ out-diff swap vars adjust-variable ] when*
-        ] when
+:: check-variable ( vars declared actual slot var-slot -- diff ok? var )
+    actual declared [ slot call length ] bi@ declared var-slot call
+    [ vars (check-variable) ] keep ; inline
+
+:: unify-variables ( in-diff in-ok? in-var out-diff out-ok? out-var vars -- ? )
+    { [ in-ok? ] [ out-ok? ] [ in-diff out-diff = ] } 0&&
+    dup [
+        in-var  [ in-diff  swap vars adjust-variable ] when*
+        out-var [ out-diff swap vars adjust-variable ] when*
+    ] when ;
+
+: check-variables ( vars declared actual -- ? )
+    dup terminated?>> [ 3drop t ] [
+        [ [ in>>  ] [ in-var>>  ] check-variable ]
+        [ [ out>> ] [ out-var>> ] check-variable ]
+        [ 2drop ] 3tri unify-variables
     ] if ;
 
-: complex-unbalanced-branches-error ( known -- * )
+: combinator-unbalanced-branches-error ( known -- * )
     [ word>> ] [
         branches>> <reversed>
         [ [ known>callable ] { } map-as ]

: check-declared-effect ( known effect -- )
    [ >>actual ] keep
    2dup [ [ variables>> ] [ effect>> ] bi ] dip check-variables
    [ 2drop ] [ drop complex-unbalanced-branches-error ] if ;


stack-checker.visitor ;
IN: stack-checker.row-polymorphism

: with-inner-d ( quot -- inner-d )
    inner-d-index get
    [ meta-d length inner-d-index set call ] dip
    inner-d-index get [ min inner-d-index set ] keep ; inline

:: (effect-here) ( inner-d old-meta-d-length old-input-count -- effect )
    old-meta-d-length inner-d - input-count get old-input-count - +
    meta-d length inner-d -
    [ "x" <array> ] bi@ terminated? get <terminated-effect> ; inline

: with-effect-here ( quot -- effect )
    meta-d length input-count get
    [ with-inner-d ] 2dip (effect-here) ; inline

:: (check-variable) ( actual-count declared-count variable vars -- difference ? )
    actual-count declared-count -
    variable [
        variable vars at* nip
