Skip to content
New issue

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

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

Already on GitHub? # to your account

Borrow checking for static methods became more strict #100725

Open
Andrepuel opened this issue Aug 18, 2022 · 9 comments
Open

Borrow checking for static methods became more strict #100725

Andrepuel opened this issue Aug 18, 2022 · 9 comments
Labels
C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-types Relevant to the types team, which will review and decide on the PR/issue.
Milestone

Comments

@Andrepuel
Copy link

Code

I tried this code:

pub struct Bigger<'a> {
    _marker: &'a (),
}
impl<'a> Bigger<'a> {
    pub fn get_addr(byte_list: &'a mut Vec<u8>) -> &mut u8 {
        byte_list.iter_mut().find_map(|item| {
            Self::other(item);
            Some(())
        });

        byte_list.push(0);
        byte_list.last_mut().unwrap()
    }

    pub fn other<'b: 'a>(_value: &'b mut u8) {
        todo!()
    }
}

I expected to see this happen: I don't know what should be the behavior. Looks like it all boils down to what is going to be 'a within Bigger::<'a>::other. In stable version of Rust, the code was accepted.

Instead, this happened: Using nightly version of the compiler a borrow checker error happened.

Version it worked on

It most recently worked on: cargo 1.63.0 (fd9c4297c 2022-07-01) / rustc 1.63.0 (4b91a6e 2022-08-08)

Version with regression

rustc --version --verbose:

rustc 1.65.0-nightly (9c20b2a8c 2022-08-17)
binary: rustc
commit-hash: 9c20b2a8cc7588decb6de25ac6a7912dcef24d65
commit-date: 2022-08-17
host: x86_64-unknown-linux-gnu
release: 1.65.0-nightly
LLVM version: 15.0.0
@Andrepuel Andrepuel added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Aug 18, 2022
@rustbot rustbot added I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. and removed regression-untriaged Untriaged performance or correctness regression. labels Aug 18, 2022
@5225225
Copy link
Contributor

5225225 commented Aug 18, 2022

searched nightlies: from nightly-2022-01-01 to nightly-2022-08-16
regressed nightly: nightly-2022-08-05
searched commit range: 1b57946...f6f9d5e
regressed commit: caee496

bisected with cargo-bisect-rustc v0.6.4

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc 2022-01-01 --preserve -- build 

Probably #98835 ?

@steffahn
Copy link
Member

steffahn commented Aug 18, 2022

Yes, that’s definitely #98835, but an interesting new case AFAICT.

Edit: On second thought, it’s slightly less interesting/new than I initially thought. See this comment.

@steffahn
Copy link
Member

steffahn commented Aug 18, 2022

So for some context/explanation, the compiler used to (arguably somewhat “incorrectly”) act more like as if the closure was

        byte_list.iter_mut().find_map(|item| {
            Bigger::<'_>::other(item);
            Some(())
        });

instead of

        byte_list.iter_mut().find_map(|item| {
            Bigger::<'a>::other(item); // <- expansion of the `Self::other`
            Some(())
        });

and hence accepted item to be shorter-lived than 'a.


To fix the code, you’ll just need to replace Self::other by Bigger::other to remove that overly-specific and constraining lifetime 'a.

@Andrepuel
Copy link
Author

So for some context/explanation, the compiler used to (arguably somewhat “incorrectly”) act more like as if the closure was

In fact, I am glad that the new version of the compiler flagged that error. That helped me into fixing an unnecessary overly-specific lifetime constraint that slipped through the code review process.

I've reported this as the regression worried me.

@steffahn
Copy link
Member

I've reported this as the regression worried me.

Rightfully so, better be safe than sorry.

In fact, I am glad that the new version of the compiler flagged that error.

FYI, I don’t think removing the compiler error entirely will happen, so even if this kind of regression is addressed, the usefulness of the compiler will not be reduced; as you noted it’s a useful error message, (and also the new check is there to prevent lots of new cases that would otherwise compiler successfully with the newly enabled full NLL-only borrow checking). AFAICT, the only thing still up to discussion is whether or not perhaps the new error should initially only be a lint. Possibly deny-by-default (so it’ll look a lot like an error, but not break downstream code depending on broken crates), and most definitely a future-incompatibility lint, so you (or your dependencies) cannot accidentally (i.e. without noticing it) write new code with such lifetime-annotation-inaccuracies that might be broken later if we do make it a hard error later. (Perhaps also with improved diagnostics to help fixing the issue.)

@aliemjay
Copy link
Member

aliemjay commented Aug 24, 2022

error output under #100976

  --> /tmp/tto6.rs:15:9
   |
8  | impl<'a> Bigger<'a> {
   |      -- lifetime `'a` defined here
9  |     pub fn get_addr(byte_list: &'a mut Vec<u8>) -> &mut u8 {
10 |         byte_list.iter_mut().find_map(|item| {
   |         -------------------- first mutable borrow occurs here
11 |             Self::other(item); // replace with `Bigger`
   |             ----------- type annotation requires that `*byte_list` is borrowed for `'a`
...
15 |         byte_list.push(0);
   |         ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
   |
help: you can remove unnecessary lifetime annotations here
  --> /tmp/tto6.rs:11:13
   |
11 |             Self::other(item); // replace with `Bigger`
   |             ^^^^^^^^^^^
   = help: consider replacing `Self` with `Bigger`

@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Aug 25, 2022
@apiraino apiraino added regression-from-stable-to-beta Performance or correctness regression from stable to beta. and removed regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. labels Aug 25, 2022
@apiraino apiraino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 8, 2022
@Mark-Simulacrum Mark-Simulacrum added this to the 1.64.0 milestone Sep 16, 2022
@apiraino apiraino added regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels Sep 22, 2022
@pnkfelix
Copy link
Member

pnkfelix commented Oct 28, 2022

Visited during P-high 2022 Q3 review.

We agreed that this regression was expected, and the answer here is improving the diagnostics.

Also, we note that this should be resolved when PR #100976 lands.

We're lowering the priority from P-high to P-medium.

@rustbot label: -P-high +P-medium

@rustbot rustbot added P-medium Medium priority and removed P-high High priority labels Oct 28, 2022
@pnkfelix
Copy link
Member

Also reassigning to T-types

@rustbot label: -T-compiler +T-types

@rustbot rustbot added T-types Relevant to the types team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 28, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
C-bug Category: This is a bug. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants