Complexy working with MutexGuard

I have code that compiles and works shown at the (current) bottom of my last topic: clean way to terminate tcpstream

That code works fine, but I don't like how it requires the use of a struct to represent the connection as so:

struct Connection {
    opt_stream: Option<TcpStream>,
}

So my goal now is to change the code to simply work with a type for the connection like this:

type Connection = Option<TcpStream>;

My question amounts to how to fix the compiler error that I get when I go from this code block that works with the struct definition for Connection:

            let mut safe_stream = mt_stream.lock().unwrap();
            if let None = safe_stream.opt_stream {
                safe_stream.opt_stream  =
                    Some(TcpStream::connect("127.0.0.1:5555").unwrap());
            }

To this (obviously naive) attempt to work with the type definition for Connenction :

            let mut safe_stream = mt_stream.lock().unwrap();
            if let None = safe_stream {
                safe_stream =
                    Some(TcpStream::connect("127.0.0.1:5555").unwrap());
            }

gets the following compiler error:

22 |             if let None = safe_stream {
   |                    ^^^^   ----------- this expression has type                `MutexGuard<'_, Option<TcpStream>>`
   |                    |
   |                    expected struct `MutexGuard`, found enum `Option`
   |
   = note: expected struct `MutexGuard<'_, Option<TcpStream>, >`
                found enum `Option<_>`

error[E0308]: mismatched types

My attempts to fix this so far have failed, and I'm hoping there's some obvious fix.

Thanks so much for any ideas.

Looks like you need an explicit deref to get a &Option<TcpStream> out of the MutexGuard for matching against:

    if let None = &*safe_stream {

I'd actually prefer this version:

    if safe_stream.is_none() {

If you need to access the inner TcpStream at that point, Option::get_or_insert_with() would be useful.

let mut safe_stream = mt_stream.lock().unwrap();
let tcp_stream = safe_stream
    .opt_stream
    .get_or_insert_with(|| TcpStream::connect("127.0.0.1:5555").unwrap());
tcp_stream.write_all(b"foobar").unwarp(); // etc
1 Like

My favorite Option method!

Thank you. I will try using your suggestion. It so happens I found I could incorporate the use of deref_mut in order to fix the problem I was having. The code I arrived at looked like this:

use std::ops::DerefMut;

type Connection = Option<TcpStream>;

            let mut safe_stream_mutex = mt_stream.lock().unwrap();
            let safe_stream = safe_stream_mutex.deref_mut();
            if let None = safe_stream {
                *safe_stream =
                    Some(TcpStream::connect("127.0.0.1:5555").unwrap());
            }

I find it interesting that the code that represented the Connection as a struct was simpler. But not too much, and I like the deref_mut code better.

Your option is cleaner.

Interesting! Thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.