Skip to content

fix(coroutine): split overlapping state assignments#155841

Open
MilkBlock wants to merge 5 commits intorust-lang:mainfrom
MilkBlock:fix-overlapping-memory-lint-in-coroutine
Open

fix(coroutine): split overlapping state assignments#155841
MilkBlock wants to merge 5 commits intorust-lang:mainfrom
MilkBlock:fix-overlapping-memory-lint-in-coroutine

Conversation

@MilkBlock
Copy link
Copy Markdown

@MilkBlock MilkBlock commented Apr 26, 2026

r? @cijiugechu

Fix #149748

coroutine.rs generated self-assign stmt when crossing yield stmt, which confused the linter.

This PR inserts additional temporary variable to make linter happy.

Before Patch

  bb1: {
      StorageLive(_3);
      _3 = copy ((*_1).0: &i32);
      StorageLive(_4);
      _4 = copy ((*_1).1: &i32);
      nop;
      (((*_1) as variant#3).0: &i32) = copy ((*_1).2: &i32);
      StorageLive(_6);
      StorageLive(_7);
      _7 = copy _4;
      _0 = Option::<&i32>::Some(move _7);
  }
  

After Patch

  bb1: {
      StorageLive(_3);
      _3 = copy ((*_1).0: &i32);
      StorageLive(_4);
      _4 = copy ((*_1).1: &i32);
      nop;
      _10 = copy ((*_1).2: &i32);
      (((*_1) as variant#3).0: &i32) = move _10;
      StorageLive(_6);
      StorageLive(_7);
      _7 = copy _4;
      _0 = Option::<&i32>::Some(move _7);
  }

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 26, 2026

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 26, 2026
@rust-log-analyzer

This comment has been minimized.

@saethlin
Copy link
Copy Markdown
Member

saethlin commented Apr 26, 2026

r? saethlin (the person you selected is not a compiler reviewer)

Did you check that the ICE reported still happens? I can't make the compiler hit it.

@rustbot rustbot assigned saethlin and unassigned cijiugechu Apr 26, 2026
@MilkBlock
Copy link
Copy Markdown
Author

r? saethlin (the person you selected is not a compiler reviewer)

Did you check that the ICE reported still happens? I can't make the compiler hit it.

This can be reproduced by

rustc +nightly --edition=2024 \
    -Zmir-enable-passes=+Inline,+ReferencePropagation \
    -Zlint-mir \
    ./tests/ui/coroutine/issue-149748.rs
rustc +nightly --version
rustc 1.97.0-nightly (ca9a134e0 2026-04-26)

given code in issue-149748.rs

//@ edition:2024
//@ compile-flags: -Zmir-enable-passes=+Inline,+ReferencePropagation -Zlint-mir
//@ check-pass

#![feature(gen_blocks)]
#![allow(unused_variables, path_statements)]

struct NonCopy(i32);

gen fn refs<'a, 'b>(x: &'a i32, y: &'b i32, z: &'b i32) -> &'b i32 {
    yield y;
    z;
}

gen fn moves(x: NonCopy, y: NonCopy, z: NonCopy) -> NonCopy {
    yield y;
    z;
}

fn main() {
    let z = 3;
    let mut refs_iter = refs(&1, &2, &z);
    assert_eq!(refs_iter.next(), Some(&3));

    let mut moves_iter = moves(NonCopy(1), NonCopy(2), NonCopy(3));
    assert!(matches!(moves_iter.next(), Some(_)));
}

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@Amanieu
Copy link
Copy Markdown
Member

Amanieu commented May 1, 2026

I think the lint is just wrong here, the assignment isn't overlapping: it's copying from 2 disjoint fields of the same local.

@MilkBlock
Copy link
Copy Markdown
Author

I think the lint is just wrong here, the assignment isn't overlapping: it's copying from 2 disjoint fields of the same local.

I think so. But how should we process this issue? Do revision on linter is not recommended I think.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 2, 2026

☔ The latest upstream changes (presumably #154341) made this pull request unmergeable. Please resolve the merge conflicts.

@Amanieu
Copy link
Copy Markdown
Member

Amanieu commented May 3, 2026

I think that the lint should be updated to use something like this to determine whether 2 places alias:

fn places_alias<'tcx>(
    tcx: TyCtxt<'tcx>,
    local_decls: &IndexVec<Local, LocalDecl<'tcx>>,
    a: Place<'tcx>,
    b: Place<'tcx>,
) -> bool {
    if a.local != b.local || a.is_indirect() || b.is_indirect() {
        return false;
    }

    for ((prefix, elem_a), (_, elem_b)) in a.iter_projections().zip(b.iter_projections()) {
        // Continue until we find the first mismatching projection.
        if elem_a == elem_b {
            continue;
        }

        match (elem_a, elem_b) {
            // Disjoint fields don't alias except if they are union fields.
            (PlaceElem::Field(_, _), PlaceElem::Field(_, _)) => {
                let ty = prefix.ty(local_decls, tcx).ty;
                return ty.is_union();
            }

            // Disjoint slice elements don't alias.
            (
                PlaceElem::ConstantIndex { offset: offset_a, min_length: _, from_end: from_end_a },
                PlaceElem::ConstantIndex { offset: offset_b, min_length: _, from_end: from_end_b },
            ) if from_end_a == from_end_b && offset_a != offset_b => {
                return false;
            }

            // Conservatively assume the places may alias.
            _ => return true,
        }
    }

    // If the projections are identical *or* one is a prefix of the other then
    // the places alias.
    true
}

@saethlin
Copy link
Copy Markdown
Member

saethlin commented May 4, 2026

The "linter" here is looking for bugs not for style, so in this case it is more appropriate to modify the lint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICE: statement with overlapping memory

6 participants