Skip to content

fix(mut_mutex_lock): FP in projection chains#16261

Closed
ada4a wants to merge 9 commits into
rust-lang:masterfrom
ada4a:mut_mutex_lock
Closed

fix(mut_mutex_lock): FP in projection chains#16261
ada4a wants to merge 9 commits into
rust-lang:masterfrom
ada4a:mut_mutex_lock

Conversation

@ada4a

@ada4a ada4a commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

fixes #16253

changelog: [mut_mutex_lock]: fix FP in projection chains

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Dec 18, 2025
@rustbot

rustbot commented Dec 18, 2025

Copy link
Copy Markdown
Collaborator

r? @samueltardieu

rustbot has assigned @samueltardieu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@github-actions

github-actions Bot commented Dec 18, 2025

Copy link
Copy Markdown

No changes for 37d8ef4

@Jarcho

Jarcho commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

So this is still wrong. The thing this needs to check for is that each adjustment to the place could have been a mutable adjustment rather than an immutable one. Would be something like (not quite real code and please write it better):

let mut e = recv;
'outer: loop {
  if !expr_adjustments(e)
    .take_while(|a| match a.kind {
        Adjust::Deref(x) => Some((a.target, x)),
        _ => None,
    }).try_fold(expr_ty(e), |ty, (target, deref)| match deref {
      None => (!ty.is_imm_ref()).then(target),
      Some(_) => impls_deref_mut(ty).then(target),
    }).is_some()
  {
    return;
  }
  loop {
      match e.kind {
        ExprKind::Field(base, _) => e = base,
        ExprKind::Index(base, idx) if impls_idx_mut(expr_ty_adjusted(base), expr_ty_adjusted(idx)) => e = base,
        // `base` here can't actually have adjustments
        ExprKind::UnOp(UnOp::Deref, base) if impls_deref_mut(expr_ty_adjusted(base)) => {
            e = base;
            continue;
        },
        _ => break 'outer,
      }
      continue 'outer;
  }
}

@ada4a

ada4a commented Dec 19, 2025

Copy link
Copy Markdown
Contributor Author

Okay so I took your code, fixed some small bugs/typos, but importantly also removed the inner loop, because, as you implied yourself, it made the code a lot more confusing for imo (?) little benefit. I did keep each step as a separate commit though, so I can easily remove some of the changes if you prefer.

Looking at the first couple of dogfood results, they do seem to be legit -- apart from the one in entry_unfixable.rs where we lint on a Mutex stored in a static, which I think is an FP? I'll go take care of the other cases for now. (EDIT: hah, Lintcheck is all just this static mutex case now)

since there won't be any adjustments after an explicit deref, the
adjustment checking step should finish pretty fast
@ada4a

ada4a commented Dec 19, 2025

Copy link
Copy Markdown
Contributor Author

I implemented a pretty basic check for statics, but I think there ought to be a more robust approach -- especially given that this statics thing didn't happen before

@samueltardieu

Copy link
Copy Markdown
Member

r? Jarcho since they reviewed it already and I haven't started yet.

@rustbot rustbot assigned Jarcho and unassigned samueltardieu Jan 18, 2026
@Jarcho

Jarcho commented Jan 18, 2026

Copy link
Copy Markdown
Contributor

Rethinking this, indexing and field accesses should just not lint. Both would take exclusive access to only part of a value which would conflict with any immutable reborrow over the whole value. The code I gave you also didn't make sure the base of the projection was actually a mutable reference. We don't want to suggest on x.lock() when x is an owned value since it has a good chance of already having another active borrow.

@ada4a

ada4a commented Jan 21, 2026

Copy link
Copy Markdown
Contributor Author

That's a pretty big change to the PR, so I've decided to open a v2 instead of force-pushing over everything: #16435

@ada4a ada4a closed this Jan 21, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mut_mutex_lock: FP on struct.mutex where struct is behind &

4 participants