Repository: tokio-rs/tokio
File: tokio/src/process/mod.rs (Rust)

Code before:
    ///         .stdout(Stdio::piped())
    ///         .stderr(Stdio::piped())
    ///         .spawn_with(|cmd| cmd.spawn_with_attributes(&attribute_list))
    ///         .unwrap()
    ///         .wait_with_output()
    ///         .await
    ///         .unwrap();
    /// # }
    /// ```
    #[cfg(tokio_unstable)]
    #[inline]
    pub fn spawn_with(
        &mut self,
        with: impl Fn(&mut StdCommand) -> io::Result<StdChild>,
    ) -> io::Result<Child> {
        self.spawn_with_inner(with)
    }

    /// Small indirection for the implementation of [`Self::spawn`] and
    /// [`Self::spawn_with`] to use: [`Self::spawn`] cannot depend directly on
    /// on [`Self::spawn_with`] since it is behind `tokio_unstable`.
    fn spawn_with_inner(
        &mut self,
        with: impl Fn(&mut StdCommand) -> io::Result<StdChild>,
    ) -> io::Result<Child> {
        imp::spawn_child_with(&mut self.std, with).map(|spawned_child| Child {
            child: FusedChild::Child(ChildDropGuard {
                inner: spawned_child.child,
                kill_on_drop: self.kill_on_drop,
            }),
            stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
            stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
            stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
        })
    }

    /// Executes the command as a child process, waiting for it to finish and
    /// collecting its exit status.
    ///
    /// By default, stdin, stdout and stderr are inherited from the parent.
    /// If any input/output handles are set to a pipe then they will be immediately
    /// closed after the child is spawned.
    ///
    /// All I/O this child does will be associated with the current default
    /// event loop.
    ///
    /// The destructor of the future returned by this function will kill
    /// the child if [`kill_on_drop`] is set to true.
    ///
    /// [`kill_on_drop`]: fn@Self::kill_on_drop
    ///

Review comment (refactor):
Might be worth also moving the body of `map` into a helper function to avoid the generics bloat

Code after:
    /// let _output = Command::new("ls")
    ///     .stdin(Stdio::null())
    ///     .stdout(Stdio::piped())
    ///     .stderr(Stdio::piped())
    ///     .spawn_with(|cmd| cmd.spawn_with_attributes(&attribute_list))
    ///     .unwrap()
    ///     .wait_with_output()
    ///     .await
    ///     .unwrap();
    /// # }
    /// ```
    #[cfg(tokio_unstable)]
    #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
    #[inline]
    pub fn spawn_with(
        &mut self,
        with: impl Fn(&mut StdCommand) -> io::Result<StdChild>,
    ) -> io::Result<Child> {
        // On two lines to circumvent a mutable borrow check failure.
        let child = with(&mut self.std)?;
        self.build_child(child)
    }

    /// Small indirection for the spawn implementations.
    ///
    /// This is introduced for [`Self::spawn`] and [`Self::spawn_with`] to use:
    /// [`Self::spawn`] cannot depend directly on on [`Self::spawn_with`] since
    /// it is behind `tokio_unstable`. It also serves as a way to reduce
    /// monomorphization bloat by taking in an already-spawned child process
    /// instead of a command and custom spawn function.
    fn build_child(&self, child: StdChild) -> io::Result<Child> {
        let spawned_child = imp::build_child(child)?;

        Ok(Child {
            child: FusedChild::Child(ChildDropGuard {
                inner: spawned_child.child,
                kill_on_drop: self.kill_on_drop,
            }),
            stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
            stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
            stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
        })
    }

    /// Executes the command as a child process, waiting for it to finish and
    /// collecting its exit status.
    ///
    /// By default, stdin, stdout and stderr are inherited from the parent.
    /// If any input/output handles are set to a pipe then they will be immediately
    /// closed after the child is spawned.
    ///