Skip to content

Borrow checking for static methods became more strict #100725

Description

@Andrepuel

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

Activity

  1. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    and removed
    regression-untriagedUntriaged performance or correctness regression.
    on Aug 18, 2022
  2. steffahn commented on Aug 18, 2022

    @steffahn
    Member

    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.

  3. steffahn commented on Aug 18, 2022

    @steffahn
    Member

    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.

  4. Andrepuel commented on Aug 18, 2022

    @Andrepuel
    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.

  5. steffahn commented on Aug 18, 2022

    @steffahn
    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.)

  6. aliemjay commented on Aug 24, 2022

    @aliemjay
    Contributor

    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`
  7. apiraino commented on Aug 25, 2022

    @apiraino
    Contributor

    WG-prioritization assigning priority (Zulip discussion).

    @rustbot label -I-prioritize +P-high

  8. added
    P-highHigh priority
    and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Aug 25, 2022
  9. added and removed on Aug 25, 2022
  10. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Sep 8, 2022
  11. added this to the 1.64.0 milestone on Sep 16, 2022
  12. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed on Sep 22, 2022
  13. pnkfelix commented on Oct 28, 2022

    @pnkfelix
    Contributor

    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

  14. added and removed
    P-highHigh priority
    on Oct 28, 2022
  15. pnkfelix commented on Oct 28, 2022

    @pnkfelix
    Contributor

    Also reassigning to T-types

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

  16. added
    T-typesRelevant to the types team, which will review and decide on the PR/issue.
    and removed
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.P-mediumMedium priorityT-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions