Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why a rust immutable reference can call &mut self methd?

Tags:

rust

Why a rust immutable reference can call &mut self methd?

in my code comments:

  1. stdin's type is &ChildStdin, why can call a "&mut self" function write_all?
  2. and why as_ref result can call a "&mut self" function write_all?
use std::io::{self, Write};
use std::process::{Command, Stdio};

fn main() -> io::Result<()> {
    let child = Command::new("cmd.exe")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    let mut stdin = child.stdin.as_ref().unwrap();
    
    //1. stdin's type is &ChildStdin, why can call a "&mut self" function write_all?
    stdin.write_all(b"dir\n")?;

    //2. and why as_ref result can call a "&mut self" function write_all?
    child.stdin.as_ref().unwrap().write_all(b"dir\n")?;
 
    let output = child.wait_with_output()?;

    println!("output = {:?}", output);

    Ok(())
}

like image 773
Alanthinker Xiang Avatar asked Jan 24 '23 06:01

Alanthinker Xiang


1 Answers

In the documentation of ChildStdin, you can find the impl Write for &ChildStdin. This was added in 1.48 because these writes are supposedly safe to call, according to the original issue:

The implementations of Write which are MT-safe under the covers can implement a trait along the lines of [...] and some already do [...]. However, these appear to be the extent of the current implementations. The following types could also do the same:

  • [...]
  • ChildStdin – similar to File or *Streams;

and the PR.


Notably, we don't have a &mut ChildStdin at any point. Instead, you create a mutable reference to the immutable reference, a &mut &ChildStdin. This mutable reference is then given to the write_all trait method from the linked Write implementation for &ChildStdin.

While there is a impl Write for ChildStdin too (which would need a &mut ChildStdin), we don't actually use it here.

like image 136
Niklas Mohrin Avatar answered Jan 26 '23 19:01

Niklas Mohrin