about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm/mod.rs
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-01-24 23:25:46 +0100
committerGitHub <noreply@github.com>2025-01-24 23:25:46 +0100
commit99e34a4ea0592d53496900ec9918018e16f67992 (patch)
treea1be987475e7a44f532b23e5de09558c17f8de13 /compiler/rustc_codegen_llvm/src/llvm/mod.rs
parent8824ae6a6c14636a4937f89e9caee80da53a45dc (diff)
parent9b82f2026133642f884ff9f019edcf9eb270894b (diff)
downloadrust-99e34a4ea0592d53496900ec9918018e16f67992.tar.gz
rust-99e34a4ea0592d53496900ec9918018e16f67992.zip
Rollup merge of #135976 - WaffleLapkin:tailcall-nodrop, r=oli-obk
Don't drop types with no drop glue when building drops for tailcalls

this is required as otherwise drops of `&mut` refs count as a usage of a
'two-phase temporary' causing an ICE.

fixes #128097

The underlying issue is that the current code generates drops for `&mut` which are later counted as a second use of a two-phase temporary:

`bat t.rs -p`
```rust
#![expect(incomplete_features)]
#![feature(explicit_tail_calls)]

fn f(x: &mut ()) {
    let _y = String::new();
    become f(x);
}

fn main() {}
```
`rustc t.rs -Zdump_mir=f`
```text
error: internal compiler error: compiler/rustc_borrowck/src/borrow_set.rs:298:17: found two uses for 2-phase borrow temporary _4: bb2[1] and bb3[0]
 --> t.rs:6:5
  |
6 |     become f(x);
  |     ^^^^^^^^^^^

thread 'rustc' panicked at compiler/rustc_borrowck/src/borrow_set.rs:298:17:
Box<dyn Any>
stack backtrace:
[REDACTED]

error: aborting due to 1 previous error
```
`bat ./mir_dump/t.f.-------.renumber.0.mir -p -lrust`
```rust
// MIR for `f` 0 renumber

fn f(_1: &mut ()) -> () {
    debug x => _1;
    let mut _0: ();
    let mut _2: !;
    let _3: std::string::String;
    let mut _4: &mut ();
    scope 1 {
        debug _y => _3;
    }

    bb0: {
        StorageLive(_3);
        _3 = String::new() -> [return: bb1, unwind: bb4];
    }

    bb1: {
        FakeRead(ForLet(None), _3);
        StorageLive(_4);
        _4 = &mut (*_1);
        drop(_3) -> [return: bb2, unwind: bb3];
    }

    bb2: {
        StorageDead(_3);
        tailcall f(Spanned { node: move _4, span: t.rs:6:14: 6:15 (#0) });
    }

    bb3 (cleanup): {
        drop(_4) -> [return: bb4, unwind terminate(cleanup)];
    }

    bb4 (cleanup): {
        resume;
    }
}
```

Note how `_4 is moved into the tail call in `bb2` and dropped in `bb3`.

This PR adds a check that the locals we drop need dropping.

r? `@oli-obk` (feel free to reassign, I'm not sure who would be a good reviewer, but thought you might have an idea)
cc `@beepster4096,` since you wrote the original drop implementation.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm/mod.rs')
0 files changed, 0 insertions, 0 deletions