about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs32
1 files changed, 30 insertions, 2 deletions
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 971b6dd9e1c..d1aaabe92ed 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -213,6 +213,30 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     self.requires_unsafe(expr.span, CastOfPointerToInt);
                 }
             }
+            ExprKind::Closure {
+                closure_id,
+                substs: _,
+                upvars: _,
+                movability: _,
+                fake_reads: _,
+            } => {
+                let closure_id = closure_id.expect_local();
+                let closure_def = if let Some((did, const_param_id)) =
+                    ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
+                {
+                    ty::WithOptConstParam { did, const_param_did: Some(const_param_id) }
+                } else {
+                    ty::WithOptConstParam::unknown(closure_id)
+                };
+                let (closure_thir, expr) = self.tcx.thir_body(closure_def);
+                let closure_thir = &closure_thir.borrow();
+                let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
+                let mut closure_visitor =
+                    UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
+                closure_visitor.visit_expr(&closure_thir[expr]);
+                // Unsafe blocks can be used in closures, make sure to take it into account
+                self.safety_context = closure_visitor.safety_context;
+            }
             _ => {}
         }
 
@@ -335,14 +359,18 @@ impl UnsafeOpKind {
     }
 }
 
-// FIXME: checking unsafety for closures should be handled by their parent body,
-// as they inherit their "safety context" from their declaration site.
 pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {
     // THIR unsafeck is gated under `-Z thir-unsafeck`
     if !tcx.sess.opts.debugging_opts.thir_unsafeck {
         return;
     }
 
+    // Closures are handled by their parent function
+    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 (thir, expr) = tcx.thir_body(def);
     let thir = &thir.borrow();
     // If `thir` is empty, a type error occured, skip this body.