class_docstr: Perform the body repeatedly while the condition ``cond`` is true.
  
  Parameters
  ----------
  _cond: function  (Required)
      * A Python function that takes ``loop_vars`` as positional arguments.
      * The function must return a ``bool`` ``Var``.
  
  _body: function  (Required)
      * A Python function that takes ``loop_vars`` as positional arguments.
      * The function must return the same number of output vars as ``loop_vars``
        with the same types.
  
  loop_vars: tuple (Required)
      * Python tuple of ``Variables``.
  
  _existing_blocks: list[Block] (Optional)
      * Python list of ``Block``.
      * For internal use only. When converting a milproto, we already got existing blocks,
        and the ``build_nested_blocks`` function can use them directly.
      * When ``_existing_blocks`` is set, ``_cond`` and ``_body`` must be dummy functions which returns ``None``.
  
  Returns
  -------
  tuple
      * Python tuple (same type as ``loop_vars``).
class_docstr_tok: ["Perform","the","body","repeatedly","while","the","condition","``","cond","``","is","true",".","Parameters","--","--","--","--","--","_cond",":","function","(","Required",")","*","A","Python","function","that","takes","``","loop_vars","``","as","positional","arguments",".","*","The","function","must","return","a","``","bool","``","``","Var","``",".","_body",":","function","(","Required",")","*","A","Python","function","that","takes","``","loop_vars","``","as","positional","arguments",".","*","The","function","must","return","the","same","number","of","output","vars","as","``","loop_vars","``","with","the","same","types",".","loop_vars",":","tuple","(","Required",")","*","Python","tuple","of","``","Variables","``",".","_existing_blocks",":","list","[","Block","]","(","Optional",")","*","Python","list","of","``","Block","``",".","*","For","internal","use","only",".","When","converting","a","milproto",",","we","already","got","existing","blocks",",","and","the","``","build_nested_blocks","``","function","can","use","them","directly",".","*","When","``","_existing_blocks","``","is","set",",","``","_cond","``","and","``","_body","``","must","be","dummy","functions","which","returns","``","None","``",".","Returns","--","--","--","-","tuple","*","Python","tuple","(","same","type","as","``","loop_vars","``",")","."]
docstr: For tensor types `type1`, `type2` that are of the same rank, return
  compat_shape (python list) where compat_shape[i] is integer iff type1
  and type2 have the same integer shape on dim i. compat_shape[i] is
  symbolic otherwise.
  
  Return None if `type1`, `type2` have different rank or non-tensor
  type.
code: def get_compat_shape(type1, type2):
      """
      For tensor types `type1`, `type2` that are of the same rank, return
      compat_shape (python list) where compat_shape[i] is integer iff type1
      and type2 have the same integer shape on dim i. compat_shape[i] is
      symbolic otherwise.
  
      Return None if `type1`, `type2` have different rank or non-tensor
      type.
      """
      if not types.is_tensor(type1) or not types.is_tensor(type2):
          return None
  
      s1 = type1.get_shape()
      s2 = type2.get_shape()
  
      if len(s1) != len(s2):
          return None
  
      compat_shape = []
      for d1, d2 in zip(s1, s2):
          if d1 != d2:
              compat_shape.append(get_new_symbol())
          else:
              compat_shape.append(d1)
      return compat_shape
  
imports: import copy
  import numpy
  from coremltools import _logger
  from coremltools.converters.mil.mil import Block, get_existing_symbol, get_new_symbol, types
  from coremltools.converters.mil.mil.input_type import DefaultInputs, InputSpec, InternalInputType, ListInputType, PyFunctionInputType, TensorInputType, TupleInputType
  from coremltools.converters.mil.mil.operation import NONE, SYMBOL, VALUE, Operation, mil_list, precondition
  from coremltools.converters.mil.mil.ops.defs._op_reqs import register_op
  from coremltools.converters.mil.mil.ops.defs._utils import infer_type_with_broadcast, promoted_primitive_type
  from coremltools.converters.mil.mil.types import is_compatible_type
  from coremltools.converters.mil.mil.types.type_list import list
  from coremltools.converters.mil.mil.types.type_mapping import builtin_to_string, is_subtype, numpy_type_to_builtin_type, numpy_val_to_builtin_val
label_desc: Use image node_id 5 for calling the while_loop obj's underlying member method code with example usage: obj.get_compat_shape(type1, type2) and returns: compat_shape, None, None