def test_scope_passdown_resursive():
        """
        Test the resursive back propagation when passing down scope info.
        """
        # Case 1
        @mb.program(input_specs=[mb.TensorSpec(shape=(2, 4))])
        def prog(x):
            with mb.scope(
                ScopeInfo(source=ScopeSource.TORCHSCRIPT_MODULE_TYPE, data=["module_1"]),
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_1"]),
            ):
                # This op is created by pass_1
                relu = mb.relu(x=x)

            with mb.scope(
                ScopeInfo(source=ScopeSource.TORCHSCRIPT_MODULE_TYPE, data=["module_3"]),
            ):
                return mb.relu(x=relu)

        block = prog.functions["main"]
        ops = list(block.operations)

        with block:
            with mb.scope(
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_2"]),
            ):
                # The subgraph is constructed under pass_2
                y = mb.leaky_relu(x=block.inputs["x"], alpha=0.8, before_op=ops[1])
                y = mb.add(x=y, y=y, before_op=ops[1])
                y = mb.leaky_relu(x=y, alpha=0.4, before_op=ops[1])

                block._replace_var(ops[0].outputs[0], y)

        ops = list(block.operations)
        assert ops[0].outputs[0].scopes == {
            ScopeSource.TORCHSCRIPT_MODULE_TYPE: ["module_1"],
            ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1"],
        }

        add_ops = block.find_ops(op_type="add")
        const_ops = block.find_ops(op_type="const")
        leaky_relu_ops = block.find_ops(op_type="leaky_relu")

        assert len(add_ops) == 1
        assert len(const_ops) == 2
        assert len(leaky_relu_ops) == 2

        for op in leaky_relu_ops + add_ops + const_ops:
            assert op.scopes == {
                ScopeSource.TORCHSCRIPT_MODULE_TYPE: ["module_1"],
                ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1", "pass_2"],
            }

        # Case 2: Test for VALID_OPS_TO_COPY_SCOPE_INFO in the scope back propagation
        # The same var cannot be visited twice
        @mb.program(input_specs=[mb.TensorSpec(shape=(2, 4))])
        def prog(x):
            with mb.scope(
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_1"]),
            ):
                # This op is created by pass_1
                relu = mb.relu(x=x)

            with mb.scope(
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_1"]),
            ):
                return mb.relu(x=relu)

        block = prog.functions["main"]
        ops = list(block.operations)

        with block:
            with mb.scope(
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_2"]),
            ):
                # The subgraph is constructed under pass_2
                relu = ops[0].outputs[0]

                y = mb.leaky_relu(x=relu, alpha=0.8, before_op=ops[1])
                y = mb.concat(values=[y, y, relu, y], axis=0, before_op=ops[1])
                y1, y2, y3, y4 = mb.split(x=y, axis=0, num_splits=4, before_op=ops[1])

                block._replace_var(relu, y1, anchor_op=y1.op)

        ops = list(block.operations)
        relu_ops = block.find_ops(op_type="relu")
        leaky_relu_op = block.find_ops(op_type="leaky_relu")[0]
        concat_op = block.find_ops(op_type="concat")[0]
        split_op = block.find_ops(op_type="split")[0]

        for op in [leaky_relu_op, concat_op, split_op]:
            assert op.scopes == {
                ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1", "pass_2"],
            }

        for op in relu_ops:
            assert op.scopes == {
                ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1"],
            }

        # Case 3: Similar to case 2, but the relu op has torch scope.
        @mb.program(input_specs=[mb.TensorSpec(shape=(2, 4))])
        def prog(x):
            with mb.scope(
                ScopeInfo(source=ScopeSource.TORCHSCRIPT_MODULE_TYPE, data=["module_1"]),
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_1"]),
            ):
                # This op is created by pass_1
                relu = mb.relu(x=x)

            with mb.scope(
                ScopeInfo(source=ScopeSource.TORCHSCRIPT_MODULE_TYPE, data=["module_1"]),
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_1"]),
            ):
                return mb.relu(x=relu)

        block = prog.functions["main"]
        ops = list(block.operations)

        with block:
            with mb.scope(
                ScopeInfo(source=ScopeSource.COREMLTOOLS_GRAPH_PASS, data=["pass_2"]),
            ):
                # The subgraph is constructed under pass_2
                relu = ops[0].outputs[0]

                y = mb.leaky_relu(x=relu, alpha=0.8, before_op=ops[1])
                y = mb.concat(values=[y, y, relu, y], axis=0, before_op=ops[1])
                y1, y2, y3, y4 = mb.split(x=y, axis=0, num_splits=4, before_op=ops[1])

                block._replace_var(relu, y1, anchor_op=y1.op)

        ops = list(block.operations)
        relu_ops = block.find_ops(op_type="relu")
        leaky_relu_op = block.find_ops(op_type="leaky_relu")[0]
        concat_op = block.find_ops(op_type="concat")[0]
        split_op = block.find_ops(op_type="split")[0]

        for op in [leaky_relu_op, concat_op, split_op]:
            assert op.scopes == {
                ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1", "pass_2"],
                ScopeSource.TORCHSCRIPT_MODULE_TYPE: ["module_1"],
            }

        for op in relu_ops:
            assert op.scopes == {
                ScopeSource.COREMLTOOLS_GRAPH_PASS: ["pass_1"],
                ScopeSource.TORCHSCRIPT_MODULE_TYPE: ["module_1"],
            }

        Test the resursive back propagation when passing down scope info.
        
coremltools/converters/mil/mil/tests/test_programs.py