Skip to content

Borrow checker thinks self is not mutable, when it is. #106325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Nordgaren opened this issue Dec 31, 2022 · 3 comments · Fixed by #106410
Closed

Borrow checker thinks self is not mutable, when it is. #106325

Nordgaren opened this issue Dec 31, 2022 · 3 comments · Fixed by #106410
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.

Comments

@Nordgaren
Copy link

Nordgaren commented Dec 31, 2022

I am trying to extend ByteOrder + Seek, and I have two traits, right now. The first is just extending ByteOrder, and the second extends ByteOrder + Seek

pub trait BinaryReader: ReadBytesExt {
     fn read_bytes(&mut self, size: usize) -> std::io::Result<Vec<u8>> {
        let mut buf = vec![0u8; size];
        self.read_exact(&mut buf[..])?;
        Ok(buf)
    }
    
    //other methods
}

impl<R: ReadBytesExt> BinaryReader for R {}

pub trait BinaryPeeker: ReadBytesExt + Seek {
   fn peek_bytes(&mut self, size: usize, position: u64) -> std::io::Result<Vec<u8>> {
        let start = self.stream_position()?;
        self.seek(SeekFrom::Start(position))?;
        let bytes = self.read_bytes(size);
        self.seek(SeekFrom::Start(start))?;
        return bytes;
    }
    
    //other methods
}

For some reason, I get this error when compiling, and it only occurs on the line with read_bytes.

  --> src\binary_reader.rs:60:21
   |
60 |         let bytes = self.read_bytes(size);
   |                     ^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

There are two ways I can work around this, for now. One is by copying the read_bytes method into the other trait, which I don't really wanna do, or I found this goofy code will also work...

    fn peek_bytes(&mut self, size: usize, position: u64) -> std::io::Result<Vec<u8>> {
        let mut s = self;
        let start = s.stream_position()?;
        s.seek(SeekFrom::Start(position))?;
        let bytes = s.read_bytes(size);
        s.seek(SeekFrom::Start(start))?;
        return bytes;
    }

Hopefully this helps clue you in on what is going on.

Is this a bug with the borrow checker?

Meta

rustc --version --verbose:

rustc 1.66.0 (69f9c33d7 2022-12-12)
binary: rustc
commit-hash: 69f9c33d71c871fc16ac445211281c6e7a340943
commit-date: 2022-12-12
host: x86_64-pc-windows-msvc
release: 1.66.0
LLVM version: 15.0.2
Backtrace

No additional info from setting the environment variable. I suspect it's because BACKTRACE doesn't deal with the borrow checker?

@Nordgaren Nordgaren added the C-bug Category: This is a bug. label Dec 31, 2022
@SkiFire13
Copy link
Contributor

I tried reproducing your issue in this playground and this is the error I got:

error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): the method `read_bytes` exists for mutable reference `&mut Self`, but its trait bounds were not satisfied
  --> src/lib.rs:21:26
   |
21 |         let bytes = self.read_bytes(size);
   |                          ^^^^^^^^^^
   |
note: trait bound `Self: Sized` was not satisfied
  --> src/lib.rs:15:6
   |
15 | impl<R: ReadBytesExt> BinaryReader for R {}
   |      ^                ------------     -
   |      |
   |      unsatisfied trait bound introduced here
note: trait bound `&mut Self: ReadBytesExt` was not satisfied
  --> src/lib.rs:15:9
   |
15 | impl<R: ReadBytesExt> BinaryReader for R {}
   |         ^^^^^^^^^^^^  ------------     -
   |         |
   |         unsatisfied trait bound introduced here
help: consider relaxing the type parameter's implicit `Sized` bound
   |
15 | impl<R: ?Sized + ReadBytesExt> BinaryReader for R {}
   |         ++++++++
help: consider relaxing the type parameter's implicit `Sized` bound
   |
15 | impl<R: ?Sized + ReadBytesExt> BinaryReader for R {}
   |         ++++++++

It doesn't complain about mutability though, but rather about a Sized bound (which is implied in the implementation of BinaryReader but not in the one of BinaryPeeker. The diagnostic also suggests a way to fix the issue, with other alternatives being adding a Sized supertrait to BinarySeeker or a where Self: Sized constraint to peek_bytes, although both seem non-ideal.

@clubby789
Copy link
Contributor

clubby789 commented Jan 2, 2023

The underlying issue is #93078. The cleanest solution is changing your blanket impl to impl<R: ReadBytesExt+?Sized> BinaryReader for R {}, propagating up the ?Sized bound from Read and ReadBytesExt

@rustbot label +A-diagnostics

@rustbot rustbot added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 2, 2023
@Nordgaren
Copy link
Author

The underlying issue is #93078. The cleanest solution is changing your blanket impl to impl<R: ReadBytesExt+?Sized> BinaryReader for R {}, propagating up the ?Sized bound from Read and ReadBytesExt

@rustbot label +A-diagnostics

That does fix it, yea. I only have to add ?Sized to the first trait. Should I add it to all of these traits, or I will encounter this again? I am new to rust, and still not entirely sure what this means, or what it means for my trait.

Thanks!

JohnTitor pushed a commit to JohnTitor/rust that referenced this issue Jan 8, 2023
…-diag, r=compiler-errors

Suggest `mut self: &mut Self` for `?Sized` impls

Closes rust-lang#106325
Closes rust-lang#93078

The suggestion is _probably_ not what the user wants (hence `MaybeIncorrect`) but at least makes the problem in the above issues clearer. It might be better to add a note explaining why this is the case, but I'm not sure how best to word that so this is a start.

`@rustbot` label +A-diagnostics
@bors bors closed this as completed in fe07531 Jan 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants