Skip to content

Unelaborate the &mut deref temps GVN rewrites into copies - #351

Open
coord-e wants to merge 1 commit into
mainfrom
claude/gifted-bohr-8y7kuk
Open

coord-e wants to merge 1 commit into
mainfrom
claude/gifted-bohr-8y7kuk

Conversation

@coord-e

@coord-e coord-e commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Fixes the &mut side of #244 (details in #244 (comment)). The Box side is handled separately by #245.

From -C opt-level=1 upward, GVN rewrites a deref temp _t = deref_copy P of a &mut-typed place into _t = copy P. extract_elaborated_deref only recognized CopyForDeref, so the temp survived as its own local. Each such copy was then analyzed as a separate borrow of P. In fn bump(w: &mut &mut i64) { **w += 3; } there are two of them, one read and one written. Their prophecies contradict each other, so the body becomes vacuous and any caller verifies, assert!(false) included (also ensures(false) on bump, and *self.r += 3 on a struct holding a &mut).

This PR treats a copy of a projected place of &mut type as such a deref temp. Whole-local copies (_3 = copy _1) are left alone: rustc emits those for ordinary moves of a &mut local even at opt-level 0 (take_max), and matching them would break take_max.rs / return_mut.rs.

Tests: tests/ui/{pass,fail}/mut_ref_deref_optimized.rs at -C opt-level=1. Without the fix, the fail case verifies as safe. The full cargo test suite passes locally (Z3 5.0.0 + the pinned PCSat), and cargo fmt --check and cargo clippy -D warnings are clean.


Generated by Claude Code

From `-C opt-level=1`, GVN rewrites a deref temp `_t = deref_copy P` of a
`&mut`-typed place into `_t = copy P`. `extract_elaborated_deref` only
recognized `CopyForDeref`, so `_t` survived as an independent local and
each such copy was analyzed as its own borrow of `P`. With two of them
alive at once (`**w += 3` reads through one and writes through the other)
the prophecies contradict, the body is vacuous, and callers verify any
assertion, `assert!(false)` included.

Treat a copy of a projected `&mut`-typed place as such a deref temp.
Whole-local copies are left alone: rustc emits those for ordinary moves
of a `&mut` local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKfGn15ekWG5r4cKqzoP9a
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-22T21:37:35.871112Z 7be8e8a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7be8e8add8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/analyze/local_def.rs
Comment on lines +421 to +422
if !place.projection.is_empty() && ty.ref_mutability() == Some(mir::Mutability::Mut) {
return Some((lhs_local, *place));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict copy unelaboration to actual deref temps

Projected copies are not exclusive to GVN-generated deref temps: rustc also emits them for ordinary mutable bindings such as let mut r = &mut *w.a. If r is later reassigned from w.b, ReplacePlacesVisitor retains the permanent r -> w.a replacement, so the reassignment's destination is rewritten into w.a itself. For a borrowed aggregate this makes Thrust analyze the function as changing the caller's reference field even though the real program only reassigns a local, which can corrupt post-state constraints and accept an invalid assertion or reject a valid one. Check that lhs_local is marked as a DerefTemp rather than classifying every projected &mut copy.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
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.

2 participants