code: def gen_variable_type_func(
      fn: NativeFunctionWithDifferentiabilityInfo,
  ) -> Dict[str, List[str]]:
      f = fn.func
      result = {}
      with native_function_manager(f):
          name = cpp.name(f.func)
          formals = gen_formals(f)
  
          if (
              fn.info is None
              and str(f.func.name.name) not in RESET_GRAD_ACCUMULATOR
              and get_base_name(f) not in DONT_REQUIRE_DERIVATIVE
              and len(gen_differentiable_outputs(fn)) > 0
              and cpp.name(f.func)
              not in DONT_ENFORCE_SAME_TENSOR_IMPL_OR_STORAGE
              and type_wrapper_name(f)
              not in DONT_ENFORCE_STORAGE_IMPL_USE_COUNT
              and type_wrapper_name(f)
              not in DONT_ENFORCE_TENSOR_IMPL_USE_COUNT
          ):
              # NOTE: [ Registering AutogradNotImplemented boxed kernel ]
              #
              # When there is no derivatives.yaml entry, we register a generic boxed
              # NotImplemented kernel to set grad_fn to be NotImplemented, so that forward
              # proceeds as usual but an error is properly produced on backward.
              # TODO: it would be nice to not have these special cases
              #
              # There are several cases where still let codegen handle it:
              # 1) ops that need to reset grad accumulator (we let codegen handle this case
              #     because) the list is (currently) only accessible in Python.
              # 2) User explicitly specifies DONT_REQUIRE_DERIVATIVE. This basically makes
              #    autograd a fallthrough with NDEBUG checks. This can be useful for when all
              #    outputs are integral.
              # 3) When there are no differentiable outputs. This is similar to (2).
              # 4) There are certain ops where we skip certain NDEBUG checks. this is similar
              #    to (1).
              type_definition = ""
              wrapper_registration = (
                  AUTOGRAD_NOT_IMPLEMENTED_REGISTRATION.substitute(
                      unqual_operator_name_with_overload=f.func.name
                  )
              )
              result["type_derived_method_definitions_Default"] = [
                  type_definition
              ]
              result["wrapper_registrations_Default"] = [
                  wrapper_registration
              ]
          else:
              if not fn.info:
                  key = "Default"
                  type_definition = METHOD_DEFINITION.substitute(
                      return_type=cpp.returns_type(
                          f.func.returns, symint=True
                      ).cpp_type(),
                      type_wrapper_name=type_wrapper_name(f, key),
                      type_definition_body=emit_body(fn, key),
                      formals=formals,
                  )
                  wrapper_registration = gen_wrapper_registration(
                      f, key
                  )
                  result[f"type_derived_method_definitions_{key}"] = [
                      type_definition
                  ]
                  result[f"wrapper_registrations_{key}"] = [
                      wrapper_registration
                  ]
              else:
                  for key in fn.info.keys():
                      type_definition = METHOD_DEFINITION.substitute(
                          return_type=cpp.returns_type(
                              f.func.returns, symint=True
                          ).cpp_type(),
                          type_wrapper_name=type_wrapper_name(f, key),
                          type_definition_body=emit_body(fn, key),
                          formals=formals,
                      )
                      wrapper_registration = gen_wrapper_registration(
                          f, key
                      )
                      result[
                          f"type_derived_method_definitions_{key}"
                      ] = [type_definition]
                      result[f"wrapper_registrations_{key}"] = [
                          wrapper_registration
                      ]
      # See Note [Manual Backend kernels]
      assert (name in MANUAL_BACKEND) == f.manual_kernel_registration
      # If you want to register a kernel to Autograd, you must make the op abstract.
      # In other words, this op must have dispatch section in native_functions.yaml.
      if name in MANUAL_AUTOGRAD_AND_TRACER or (
          fn.info
          and any(info.has_derivatives for info in fn.info.values())
      ):
          msg = (
              f"There's a formula for {name}(or its functional variant) in derivatives.yaml. "
              f"It's required to add a dispatch section for it with explicit supported backends e.g CPU/CUDA "
              f"or CompositeExplicitAutograd in native_functions.yaml. Please see "
              f"https://github.com/pytorch/pytorch/tree/master/aten/src/ATen/native#choosing-the-right-dispatch-keyword "
              f"for instructions to choose the right dispatch keyword."
          )
          assert f.is_abstract, msg
  
      return result
  
file_path: pytorch/tools/autograd/gen_variable_type.py
imports: import re
  from typing import Callable, Dict, List, Optional, Sequence, Set, Tuple, Union
  from torchgen.api import cpp
  from torchgen.api.autograd import DifferentiableInput, dispatch_strategy, ForwardDerivative, gen_differentiable_outputs, is_differentiable, NativeFunctionWithDifferentiabilityInfo, SavedAttribute
  from torchgen.api.types import ArrayRefCType, BaseCppType, BaseCType, Binding, DispatcherSignature, intArrayRefT, iTensorListRefT, ListCType, MutRefCType, OptionalCType, scalarT, SpecialArgName, stringT, symIntArrayRefT, TENSOR_LIST_LIKE_CTYPES, tensorListT, tensorT, TupleCType, VectorCType
  from torchgen.code_template import CodeTemplate
  from torchgen.context import native_function_manager, with_native_function, with_native_function_and
  from torchgen.model import Argument, BaseType, ListType, NativeFunction, SchemaKind, SelfArgument, TensorOptionsArguments
  from torchgen.utils import FileManager, mapMaybe
  from .context import with_native_function_with_differentiability_info_and_key
  from .gen_inplace_or_view_type import ALL_VIEW_FUNCTIONS, ASSIGN_RETURN_VALUE, AUTOGRAD_NOT_IMPLEMENTED_REGISTRATION, gen_formals, get_base_name, get_view_info, is_tensor_list_type, is_tensor_type, METHOD_DEFINITION, modifies_arguments, TMP_VAR, unpack_args, unpacked_name, use_derived, WRAPPER_REGISTRATION
  from .gen_trace_type import declare_returned_variables, get_return_value, MANUAL_AUTOGRAD_AND_TRACER, MANUAL_BACKEND, tie_return_values, type_wrapper_name
label_desc: Use image node_id 3 for calling a global function with example usage: gen_variable_type_func(fn) and returns: result