Skip to content

Commit

Permalink
Auto merge of rust-lang#86138 - FabianWolff:issue-85871, r=nikomatsakis
Browse files Browse the repository at this point in the history
Check whether the closure's owner is an ADT in thir-unsafeck

This pull request fixes rust-lang#85871. The code in `rustc_mir_build/src/check_unsafety.rs` incorrectly assumes that a closure's owner always has a body, but only functions, closures, and constants have bodies, whereas a closure can also appear inside a struct or enum:
```rust
struct S {
    arr: [(); match || 1 { _ => 42 }]
}

enum E {
    A([(); { || 1; 42 }])
}
```
This pull request fixes the resulting ICE by checking whether the closure's owner is an ADT and only deferring to `thir_check_unsafety(owner)` if it isn't.
  • Loading branch information
bors committed Jun 23, 2021
2 parents 5a78340 + 433c1ae commit f1e691d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
11 changes: 8 additions & 3 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,15 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
return;
}

// Closures are handled by their parent function
// Closures are handled by their owner, if it has a body
if tcx.is_closure(def.did.to_def_id()) {
tcx.ensure().thir_check_unsafety(tcx.hir().local_def_id_to_hir_id(def.did).owner);
return;
let owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
let owner_hir_id = tcx.hir().local_def_id_to_hir_id(owner);

if tcx.hir().maybe_body_owned_by(owner_hir_id).is_some() {
tcx.ensure().thir_check_unsafety(owner);
return;
}
}

let (thir, expr) = tcx.thir_body(def);
Expand Down
20 changes: 20 additions & 0 deletions src/test/ui/thir-unsafeck-issue-85871.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Tests that no ICE occurs when a closure appears inside a node
// that does not have a body when compiling with
// compile-flags: -Zthir-unsafeck=yes
// check-pass

#![allow(dead_code)]

struct Bug {
inner: [(); match || 1 {
_n => 42, // we may not call the closure here (E0015)
}],
}

enum E {
V([(); { let _ = || 1; 42 }]),
}

type Ty = [(); { let _ = || 1; 42 }];

fn main() {}

0 comments on commit f1e691d

Please sign in to comment.