]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45785 - arielb1:unsafe-fixes, r=eddyb
authorbors <bors@rust-lang.org>
Fri, 10 Nov 2017 11:37:32 +0000 (11:37 +0000)
committerbors <bors@rust-lang.org>
Fri, 10 Nov 2017 11:37:32 +0000 (11:37 +0000)
fixes to MIR effectck

r? @eddyb

beta-nominating because regression (MIR effectck is new)

12 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/ich/impls_mir.rs
src/librustc/mir/mod.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/mod.rs
src/test/compile-fail/issue-45087-unreachable-unsafe.rs [new file with mode: 0644]
src/test/compile-fail/issue-45729-unsafe-in-generator.rs [new file with mode: 0644]
src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs [new file with mode: 0644]
src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr [new file with mode: 0644]
src/test/ui/span/lint-unused-unsafe.stderr

index 89ce4bf928ad859e8ecc4424ef55cc9dd6595a56..b391b353632aad28c1b19b4d5a891c8e7d0c51e9 100644 (file)
@@ -469,6 +469,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     // Represents the MIR for a fn; also used as the task node for
     // things read/modify that MIR.
     [] MirConstQualif(DefId),
+    [] MirBuilt(DefId),
     [] MirConst(DefId),
     [] MirValidated(DefId),
     [] MirOptimized(DefId),
@@ -477,7 +478,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] BorrowCheckKrate,
     [] BorrowCheck(DefId),
     [] MirBorrowCheck(DefId),
-    [] UnsafetyViolations(DefId),
+    [] UnsafetyCheckResult(DefId),
 
     [] Reachability,
     [] MirKeys,
@@ -782,4 +783,3 @@ pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId {
 impl_stable_hash_for!(struct ::dep_graph::WorkProductId {
     hash
 });
-
index 05436201e7a6e56ab75eca6eb8bd18117cd90ffe..8ae26d81442a2be9c42917afe87ad313a39cb6fd 100644 (file)
@@ -34,6 +34,7 @@
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
 impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, lint_node_id });
+impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::Terminator<'gcx> {
index 2fc27de137faa13de7c59eb400e13ddc7e510711..0fa40f5619699a743e9aef56ef8aa8bded566e2b 100644 (file)
@@ -33,6 +33,7 @@
 use std::fmt::{self, Debug, Formatter, Write};
 use std::{iter, u32};
 use std::ops::{Index, IndexMut};
+use std::rc::Rc;
 use std::vec::IntoIter;
 use syntax::ast::{self, Name};
 use syntax_pos::Span;
@@ -1683,6 +1684,15 @@ pub struct UnsafetyViolation {
     pub lint_node_id: Option<ast::NodeId>,
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct UnsafetyCheckResult {
+    /// Violations that are propagated *upwards* from this function
+    pub violations: Rc<[UnsafetyViolation]>,
+    /// unsafe blocks in this function, along with whether they are used. This is
+    /// used for the "unused_unsafe" lint.
+    pub unsafe_blocks: Rc<[(ast::NodeId, bool)]>,
+}
+
 /// The layout of generator state
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct GeneratorLayout<'tcx> {
index e3fa1e59087d2c2c88f40ace3e118b690b155f91..320f65148498712c3b5cbfdcc87cf914f845e54b 100644 (file)
     /// the value isn't known except to the pass itself.
     [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Rc<IdxSetBuf<mir::Local>>),
 
+    /// Fetch the MIR for a given def-id right after it's built - this includes
+    /// unreachable code.
+    [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
+
     /// Fetch the MIR for a given def-id up till the point where it is
     /// ready for const evaluation.
     ///
     /// expression defining the closure.
     [] fn closure_kind: ClosureKind(DefId) -> ty::ClosureKind,
 
-    /// Unsafety violations for this def ID.
-    [] fn unsafety_violations: UnsafetyViolations(DefId)
-        -> Rc<[mir::UnsafetyViolation]>,
+    /// The result of unsafety-checking this def-id.
+    [] fn unsafety_check_result: UnsafetyCheckResult(DefId) -> mir::UnsafetyCheckResult,
 
     /// The signature of functions and closures.
     [] fn fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>,
index 24148bcc83f37a76924c5ae0e1e87df89c496615..590d5b8e62f1a056268e0632041703a207b0e69c 100644 (file)
@@ -739,6 +739,7 @@ macro_rules! force {
             force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
         },
         DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
+        DepKind::MirBuilt => { force!(mir_built, def_id!()); }
         DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
         DepKind::MirConst => { force!(mir_const, def_id!()); }
         DepKind::MirValidated => { force!(mir_validated, def_id!()); }
@@ -746,7 +747,7 @@ macro_rules! force {
 
         DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
         DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
-        DepKind::UnsafetyViolations => { force!(unsafety_violations, def_id!()); }
+        DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
         DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
         DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
         DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
@@ -879,4 +880,3 @@ macro_rules! force {
 
     true
 }
-
index 80c8f22c1029e0c60ce2873ee54285cdd5aa4983..53a4b2551fd13e189b27910dcea80a60d9ac4a9e 100644 (file)
@@ -34,6 +34,7 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     used_unsafe: FxHashSet<ast::NodeId>,
+    inherited_blocks: Vec<(ast::NodeId, bool)>,
 }
 
 impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
@@ -52,6 +53,7 @@ fn new(mir: &'a Mir<'tcx>,
             tcx,
             param_env,
             used_unsafe: FxHashSet(),
+            inherited_blocks: vec![],
         }
     }
 }
@@ -75,7 +77,7 @@ fn visit_terminator(&mut self,
             TerminatorKind::Return |
             TerminatorKind::Unreachable |
             TerminatorKind::FalseEdges { .. } => {
-                                // safe (at least as emitted during MIR construction)
+                // safe (at least as emitted during MIR construction)
             }
 
             TerminatorKind::Call { ref func, .. } => {
@@ -117,12 +119,20 @@ fn visit_rvalue(&mut self,
                     rvalue: &Rvalue<'tcx>,
                     location: Location)
     {
-        if let &Rvalue::Aggregate(
-            box AggregateKind::Closure(def_id, _),
-            _
-        ) = rvalue {
-            let unsafety_violations = self.tcx.unsafety_violations(def_id);
-            self.register_violations(&unsafety_violations);
+        if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
+            match aggregate {
+                &AggregateKind::Array(..) |
+                &AggregateKind::Tuple |
+                &AggregateKind::Adt(..) => {}
+                &AggregateKind::Closure(def_id, _) |
+                &AggregateKind::Generator(def_id, _, _) => {
+                    let UnsafetyCheckResult {
+                        violations, unsafe_blocks
+                    } = self.tcx.unsafety_check_result(def_id);
+                    self.inherited_blocks.extend(unsafe_blocks.iter().cloned());
+                    self.register_violations(&violations, &unsafe_blocks);
+                }
+            }
         }
         self.super_rvalue(rvalue, location);
     }
@@ -189,7 +199,7 @@ fn visit_lvalue(&mut self,
                         source_info,
                         description: "use of extern static",
                         lint_node_id: Some(lint_root)
-                    }]);
+                    }], &[]);
                 }
             }
         }
@@ -222,41 +232,49 @@ fn require_unsafe(&mut self,
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info, description, lint_node_id: None
-        }]);
+        }], &[]);
     }
 
-    fn register_violations(&mut self, violations: &[UnsafetyViolation]) {
-        match self.visibility_scope_info[self.source_info.scope].safety {
+    fn register_violations(&mut self,
+                           violations: &[UnsafetyViolation],
+                           unsafe_blocks: &[(ast::NodeId, bool)]) {
+        let within_unsafe = match self.visibility_scope_info[self.source_info.scope].safety {
             Safety::Safe => {
                 for violation in violations {
                     if !self.violations.contains(violation) {
                         self.violations.push(violation.clone())
                     }
                 }
+
+                false
             }
-            Safety::BuiltinUnsafe | Safety::FnUnsafe => {}
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
             Safety::ExplicitUnsafe(node_id) => {
                 if !violations.is_empty() {
                     self.used_unsafe.insert(node_id);
                 }
+                true
             }
-        }
+        };
+        self.inherited_blocks.extend(unsafe_blocks.iter().map(|&(node_id, is_used)| {
+            (node_id, is_used && !within_unsafe)
+        }));
     }
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
-        unsafety_violations,
+        unsafety_check_result,
         ..*providers
     };
 }
 
-struct UnusedUnsafeVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    used_unsafe: FxHashSet<ast::NodeId>
+struct UnusedUnsafeVisitor<'a> {
+    used_unsafe: &'a FxHashSet<ast::NodeId>,
+    unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>,
 }
 
-impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a, 'tcx> {
+impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
     fn nested_visit_map<'this>(&'this mut self) ->
         hir::intravisit::NestedVisitorMap<'this, 'tcx>
     {
@@ -267,50 +285,15 @@ fn visit_block(&mut self, block: &'tcx hir::Block) {
         hir::intravisit::walk_block(self, block);
 
         if let hir::UnsafeBlock(hir::UserProvided) = block.rules {
-            if !self.used_unsafe.contains(&block.id) {
-                self.report_unused_unsafe(block);
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx> UnusedUnsafeVisitor<'a, 'tcx> {
-    /// Return the NodeId for an enclosing scope that is also `unsafe`
-    fn is_enclosed(&self, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
-        let parent_id = self.tcx.hir.get_parent_node(id);
-        if parent_id != id {
-            if self.used_unsafe.contains(&parent_id) {
-                Some(("block".to_string(), parent_id))
-            } else if let Some(hir::map::NodeItem(&hir::Item {
-                node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
-                ..
-            })) = self.tcx.hir.find(parent_id) {
-                Some(("fn".to_string(), parent_id))
-            } else {
-                self.is_enclosed(parent_id)
-            }
-        } else {
-            None
-        }
-    }
-
-    fn report_unused_unsafe(&self, block: &'tcx hir::Block) {
-        let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE,
-                                                    block.id,
-                                                    block.span,
-                                                    "unnecessary `unsafe` block");
-        db.span_label(block.span, "unnecessary `unsafe` block");
-        if let Some((kind, id)) = self.is_enclosed(block.id) {
-            db.span_note(self.tcx.hir.span(id),
-                         &format!("because it's nested under this `unsafe` {}", kind));
+            self.unsafe_blocks.push((block.id, self.used_unsafe.contains(&block.id)));
         }
-        db.emit();
     }
 }
 
 fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  def_id: DefId,
-                                 used_unsafe: FxHashSet<ast::NodeId>)
+                                 used_unsafe: &FxHashSet<ast::NodeId>,
+                                 unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>)
 {
     let body_id =
         tcx.hir.as_local_node_id(def_id).and_then(|node_id| {
@@ -328,25 +311,27 @@ fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})",
            def_id, body, used_unsafe);
 
-    hir::intravisit::Visitor::visit_body(
-        &mut UnusedUnsafeVisitor { tcx, used_unsafe },
-        body);
+    let mut visitor =  UnusedUnsafeVisitor { used_unsafe, unsafe_blocks };
+    hir::intravisit::Visitor::visit_body(&mut visitor, body);
 }
 
-fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ->
-    Rc<[UnsafetyViolation]>
+fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                                   -> UnsafetyCheckResult
 {
     debug!("unsafety_violations({:?})", def_id);
 
     // NB: this borrow is valid because all the consumers of
-    // `mir_const` force this.
-    let mir = &tcx.mir_const(def_id).borrow();
+    // `mir_built` force this.
+    let mir = &tcx.mir_built(def_id).borrow();
 
     let visibility_scope_info = match mir.visibility_scope_info {
         ClearOnDecode::Set(ref data) => data,
         ClearOnDecode::Clear => {
             debug!("unsafety_violations: {:?} - remote, skipping", def_id);
-            return Rc::new([])
+            return UnsafetyCheckResult {
+                violations: Rc::new([]),
+                unsafe_blocks: Rc::new([])
+            }
         }
     };
 
@@ -355,8 +340,43 @@ fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ->
         mir, visibility_scope_info, tcx, param_env);
     checker.visit_mir(mir);
 
-    check_unused_unsafe(tcx, def_id, checker.used_unsafe);
-    checker.violations.into()
+    check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
+    UnsafetyCheckResult {
+        violations: checker.violations.into(),
+        unsafe_blocks: checker.inherited_blocks.into()
+    }
+}
+
+/// Return the NodeId for an enclosing scope that is also `unsafe`
+fn is_enclosed(tcx: TyCtxt,
+               used_unsafe: &FxHashSet<ast::NodeId>,
+               id: ast::NodeId) -> Option<(String, ast::NodeId)> {
+    let parent_id = tcx.hir.get_parent_node(id);
+    if parent_id != id {
+        if used_unsafe.contains(&parent_id) {
+            Some(("block".to_string(), parent_id))
+        } else if let Some(hir::map::NodeItem(&hir::Item {
+            node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+            ..
+        })) = tcx.hir.find(parent_id) {
+            Some(("fn".to_string(), parent_id))
+        } else {
+            is_enclosed(tcx, used_unsafe, parent_id)
+        }
+    } else {
+        None
+    }
+}
+
+fn report_unused_unsafe(tcx: TyCtxt, used_unsafe: &FxHashSet<ast::NodeId>, id: ast::NodeId) {
+    let span = tcx.hir.span(id);
+    let mut db = tcx.struct_span_lint_node(UNUSED_UNSAFE, id, span, "unnecessary `unsafe` block");
+    db.span_label(span, "unnecessary `unsafe` block");
+    if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) {
+        db.span_note(tcx.hir.span(id),
+                     &format!("because it's nested under this `unsafe` {}", kind));
+    }
+    db.emit();
 }
 
 pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
@@ -367,9 +387,14 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         _ => {}
     };
 
+    let UnsafetyCheckResult {
+        violations,
+        unsafe_blocks
+    } = tcx.unsafety_check_result(def_id);
+
     for &UnsafetyViolation {
         source_info, description, lint_node_id
-    } in &*tcx.unsafety_violations(def_id) {
+    } in violations.iter() {
         // Report an error.
         if let Some(lint_node_id) = lint_node_id {
             tcx.lint_node(SAFE_EXTERN_STATICS,
@@ -385,4 +410,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                 .emit();
         }
     }
+
+    let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
+    unsafe_blocks.sort();
+    let used_unsafe: FxHashSet<_> = unsafe_blocks.iter()
+        .flat_map(|&&(id, used)| if used { Some(id) } else { None })
+        .collect();
+    for &(block_id, is_used) in unsafe_blocks {
+        if !is_used {
+            report_unused_unsafe(tcx, &used_unsafe, block_id);
+        }
+    }
 }
index 322f46cf02b6332b6877c29617eae386875fd858..34cc3a289d18949b3a043dd8d77f651383594057 100644 (file)
@@ -50,6 +50,7 @@ pub(crate) fn provide(providers: &mut Providers) {
     self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
+        mir_built,
         mir_const,
         mir_validated,
         optimized_mir,
@@ -103,9 +104,17 @@ fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
     Rc::new(set)
 }
 
+fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+    let mir = build::mir_build(tcx, def_id);
+    tcx.alloc_steal_mir(mir)
+}
+
 fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
-    let mut mir = build::mir_build(tcx, def_id);
+    // Unsafety check uses the raw mir, so make sure it is run
+    let _ = tcx.unsafety_check_result(def_id);
+
     let source = MirSource::from_local_def_id(tcx, def_id);
+    let mut mir = tcx.mir_built(def_id).steal();
     transform::run_suite(tcx, source, MIR_CONST, &mut mir);
     tcx.alloc_steal_mir(mir)
 }
@@ -117,7 +126,6 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         // this point, before we steal the mir-const result.
         let _ = tcx.mir_const_qualif(def_id);
     }
-    let _ = tcx.unsafety_violations(def_id);
 
     let mut mir = tcx.mir_const(def_id).steal();
     transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
diff --git a/src/test/compile-fail/issue-45087-unreachable-unsafe.rs b/src/test/compile-fail/issue-45087-unreachable-unsafe.rs
new file mode 100644 (file)
index 0000000..eeb66fa
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    return;
+    *(1 as *mut u32) = 42;
+    //~^ ERROR dereference of raw pointer requires unsafe
+}
diff --git a/src/test/compile-fail/issue-45729-unsafe-in-generator.rs b/src/test/compile-fail/issue-45729-unsafe-in-generator.rs
new file mode 100644 (file)
index 0000000..489e917
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+
+fn main() {
+    let _ = || {
+        *(1 as *mut u32) = 42;
+        //~^ ERROR dereference of raw pointer requires unsafe
+        yield;
+    };
+}
diff --git a/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.rs
new file mode 100644 (file)
index 0000000..833fc28
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deny(unused_unsafe)]
+fn main() {
+    let mut v = Vec::<i32>::with_capacity(24);
+
+    unsafe {
+        let f = |v: &mut Vec<_>| {
+            unsafe {
+                v.set_len(24);
+                |w: &mut Vec<u32>| { unsafe {
+                    w.set_len(32);
+                } };
+            }
+            |x: &mut Vec<u32>| { unsafe {
+                x.set_len(40);
+            } };
+        };
+
+        v.set_len(0);
+        f(&mut v);
+    }
+
+    |y: &mut Vec<u32>| { unsafe {
+        y.set_len(48);
+    } };
+}
diff --git a/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr b/src/test/ui/issue-45107-unnecessary-unsafe-in-closure.stderr
new file mode 100644 (file)
index 0000000..5c58b19
--- /dev/null
@@ -0,0 +1,71 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:17:13
+   |
+17 | /             unsafe {
+18 | |                 v.set_len(24);
+19 | |                 |w: &mut Vec<u32>| { unsafe {
+20 | |                     w.set_len(32);
+21 | |                 } };
+22 | |             }
+   | |_____________^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:11:8
+   |
+11 | #[deny(unused_unsafe)]
+   |        ^^^^^^^^^^^^^
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:15:5
+   |
+15 | /     unsafe {
+16 | |         let f = |v: &mut Vec<_>| {
+17 | |             unsafe {
+18 | |                 v.set_len(24);
+...  |
+29 | |         f(&mut v);
+30 | |     }
+   | |_____^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:19:38
+   |
+19 |                   |w: &mut Vec<u32>| { unsafe {
+   |  ______________________________________^
+20 | |                     w.set_len(32);
+21 | |                 } };
+   | |_________________^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:17:13
+   |
+17 | /             unsafe {
+18 | |                 v.set_len(24);
+19 | |                 |w: &mut Vec<u32>| { unsafe {
+20 | |                     w.set_len(32);
+21 | |                 } };
+22 | |             }
+   | |_____________^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:23:34
+   |
+23 |               |x: &mut Vec<u32>| { unsafe {
+   |  __________________________________^
+24 | |                 x.set_len(40);
+25 | |             } };
+   | |_____________^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:15:5
+   |
+15 | /     unsafe {
+16 | |         let f = |v: &mut Vec<_>| {
+17 | |             unsafe {
+18 | |                 v.set_len(24);
+...  |
+29 | |         f(&mut v);
+30 | |     }
+   | |_____^
+
+error: aborting due to 6 previous errors
+
index 1fa5f94aa4ca6e29970c2932c13aa9814a57e299..f4998e08907a387f55b897ab80f5cc47e203d540 100644 (file)
@@ -65,12 +65,14 @@ note: because it's nested under this `unsafe` block
    | |_____^
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:40:9
+  --> $DIR/lint-unused-unsafe.rs:39:5
    |
-40 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+39 | /     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
-   | |_________^ unnecessary `unsafe` block
+43 | |     }
+   | |_____^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1
@@ -85,14 +87,12 @@ note: because it's nested under this `unsafe` fn
    | |_^
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:39:5
+  --> $DIR/lint-unused-unsafe.rs:40:9
    |
-39 | /     unsafe {                             //~ ERROR: unnecessary `unsafe` block
-40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+40 | /         unsafe {                         //~ ERROR: unnecessary `unsafe` block
 41 | |             unsf()
 42 | |         }
-43 | |     }
-   | |_____^ unnecessary `unsafe` block
+   | |_________^ unnecessary `unsafe` block
    |
 note: because it's nested under this `unsafe` fn
   --> $DIR/lint-unused-unsafe.rs:38:1