def annotate(return_type=_invalid_placeholder_type, **kwargs):
    """
    A decorator that informs the compyler about the return type of a function
    and a collection of hint for other variable names. These can include
     - captured variables
     - function arguments
     - other variables within the function

    Ex:

        @annotate(compyler.double, a=compyler.double, b=compyler.double)
        def add(a, b):

    In certain cases when the class members are annotated this does not work.
    For instance this fails because the annotate decorator is called before
    the class double is fully defined.

        class double:
            @annotate(double, other=double)
            def __add__(self, other):

     So it is necessary to add one level of laziness and delay the type

        @class_annotate()
        class double:
            @annotate(delay_type.double, other=delay_type.double)
            def __add__(self, other):

    After which apply_delayed_types() must be called to fill in the delayed
    type.
    """
    global annotated_function_list

    def decorator(func):
        global annotated_function_list
        func.type_annotations = kwargs
        if return_type is not _invalid_placeholder_type:
            func.return_type = return_type
        annotated_function_list += [func]
        return func

    return decorator

    A decorator that informs the compyler about the return type of a function
    and a collection of hint for other variable names. These can include
     - captured variables
     - function arguments
     - other variables within the function

    Ex:

        @annotate(compyler.double, a=compyler.double, b=compyler.double)
        def add(a, b):

    In certain cases when the class members are annotated this does not work.
    For instance this fails because the annotate decorator is called before
    the class double is fully defined.

        class double:
            @annotate(double, other=double)
            def __add__(self, other):

     So it is necessary to add one level of laziness and delay the type

        @class_annotate()
        class double:
            @annotate(delay_type.double, other=delay_type.double)
            def __add__(self, other):

    After which apply_delayed_types() must be called to fill in the delayed
    type.
    
coremltools/converters/mil/mil/types/annotate.py