code: def chain_future(a: "Future[_T]", b: "Future[_T]") -> None:
      
  
      def copy(future: "Future[_T]") -> None:
          assert future is a
          if b.done():
              return
          if hasattr(a, "exc_info") and a.exc_info() is not None:  # type: ignore
              future_set_exc_info(b, a.exc_info())  # type: ignore
          elif a.exception() is not None:
              b.set_exception(a.exception())
          else:
              b.set_result(a.result())
  
      if isinstance(a, Future):
          future_add_done_callback(a, copy)
      else:
          # concurrent.futures.Future
          from tornado.ioloop import IOLoop
  
          IOLoop.current().add_future(a, copy)
docs: Chain two futures together so that when one completes, so does the other.
  
      The result (success or failure) of ``a`` will be copied to ``b``, unless
      ``b`` has already been completed or cancelled by the time ``a`` finishes.
  
      .. versionchanged:: 5.0
  
         Now accepts both Tornado/asyncio `Future` objects and
         `concurrent.futures.Future`.