Skip to content

Commit c6aaf2c

Browse files
committed
auto merge of #12419 : huonw/rust/compiler-unsafe, r=alexcrichton
Previously an `unsafe` block created by the compiler (like those in the formatting macros) would be "ignored" if surrounded by `unsafe`, that is, the internal unsafety would be being legitimised by the external block: unsafe { println!("...") } =(expansion)=> unsafe { ... unsafe { ... } } And the code in the inner block would be using the outer block, making it considered used (and the inner one considered unused). This patch forces the compiler to create a new unsafe context for compiler generated blocks, so that their internal unsafety doesn't escape to external blocks. Fixes #12418.
2 parents 2fa7d6b + 5ec1183 commit c6aaf2c

File tree

6 files changed

+59
-35
lines changed

6 files changed

+59
-35
lines changed

src/librustc/middle/effect.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,28 @@ impl Visitor<()> for EffectCheckVisitor {
106106

107107
fn visit_block(&mut self, block: &ast::Block, _:()) {
108108
let old_unsafe_context = self.unsafe_context;
109-
let is_unsafe = match block.rules {
110-
ast::UnsafeBlock(..) => true, ast::DefaultBlock => false
111-
};
112-
if is_unsafe && self.unsafe_context == SafeContext {
113-
self.unsafe_context = UnsafeBlock(block.id)
109+
match block.rules {
110+
ast::DefaultBlock => {}
111+
ast::UnsafeBlock(source) => {
112+
// By default only the outermost `unsafe` block is
113+
// "used" and so nested unsafe blocks are pointless
114+
// (the inner ones are unnecessary and we actually
115+
// warn about them). As such, there are two cases when
116+
// we need to create a new context, when we're
117+
// - outside `unsafe` and found a `unsafe` block
118+
// (normal case)
119+
// - inside `unsafe` but found an `unsafe` block
120+
// created internally to the compiler
121+
//
122+
// The second case is necessary to ensure that the
123+
// compiler `unsafe` blocks don't accidentally "use"
124+
// external blocks (e.g. `unsafe { println("") }`,
125+
// expands to `unsafe { ... unsafe { ... } }` where
126+
// the inner one is compiler generated).
127+
if self.unsafe_context == SafeContext || source == ast::CompilerGenerated {
128+
self.unsafe_context = UnsafeBlock(block.id)
129+
}
130+
}
114131
}
115132

116133
visit::walk_block(self, block, ());

src/librustc/middle/trans/base.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,9 @@ pub fn invoke<'a>(
918918
}
919919

920920
if need_invoke(bcx) {
921-
unsafe {
922-
debug!("invoking {} at {}", llfn, bcx.llbb);
923-
for &llarg in llargs.iter() {
924-
debug!("arg: {}", llarg);
925-
}
921+
debug!("invoking {} at {}", llfn, bcx.llbb);
922+
for &llarg in llargs.iter() {
923+
debug!("arg: {}", llarg);
926924
}
927925
let normal_bcx = bcx.fcx.new_temp_block("normal-return");
928926
let landing_pad = bcx.fcx.get_landing_pad();
@@ -940,11 +938,9 @@ pub fn invoke<'a>(
940938
attributes);
941939
return (llresult, normal_bcx);
942940
} else {
943-
unsafe {
944-
debug!("calling {} at {}", llfn, bcx.llbb);
945-
for &llarg in llargs.iter() {
946-
debug!("arg: {}", llarg);
947-
}
941+
debug!("calling {} at {}", llfn, bcx.llbb);
942+
for &llarg in llargs.iter() {
943+
debug!("arg: {}", llarg);
948944
}
949945

950946
match call_info {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -991,9 +991,7 @@ impl RegionScope for infer::InferCtxt {
991991

992992
impl FnCtxt {
993993
pub fn tag(&self) -> ~str {
994-
unsafe {
995-
format!("{}", self as *FnCtxt)
996-
}
994+
format!("{}", self as *FnCtxt)
997995
}
998996

999997
pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {

src/libstd/comm/shared.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,12 @@ impl<T: Send> Packet<T> {
486486
#[unsafe_destructor]
487487
impl<T: Send> Drop for Packet<T> {
488488
fn drop(&mut self) {
489-
unsafe {
490-
// Note that this load is not only an assert for correctness about
491-
// disconnection, but also a proper fence before the read of
492-
// `to_wake`, so this assert cannot be removed with also removing
493-
// the `to_wake` assert.
494-
assert_eq!(self.cnt.load(atomics::SeqCst), DISCONNECTED);
495-
assert_eq!(self.to_wake.load(atomics::SeqCst), 0);
496-
assert_eq!(self.channels.load(atomics::SeqCst), 0);
497-
}
489+
// Note that this load is not only an assert for correctness about
490+
// disconnection, but also a proper fence before the read of
491+
// `to_wake`, so this assert cannot be removed with also removing
492+
// the `to_wake` assert.
493+
assert_eq!(self.cnt.load(atomics::SeqCst), DISCONNECTED);
494+
assert_eq!(self.to_wake.load(atomics::SeqCst), 0);
495+
assert_eq!(self.channels.load(atomics::SeqCst), 0);
498496
}
499497
}

src/libstd/comm/stream.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -471,13 +471,11 @@ impl<T: Send> Packet<T> {
471471
#[unsafe_destructor]
472472
impl<T: Send> Drop for Packet<T> {
473473
fn drop(&mut self) {
474-
unsafe {
475-
// Note that this load is not only an assert for correctness about
476-
// disconnection, but also a proper fence before the read of
477-
// `to_wake`, so this assert cannot be removed with also removing
478-
// the `to_wake` assert.
479-
assert_eq!(self.cnt.load(atomics::SeqCst), DISCONNECTED);
480-
assert_eq!(self.to_wake.load(atomics::SeqCst), 0);
481-
}
474+
// Note that this load is not only an assert for correctness about
475+
// disconnection, but also a proper fence before the read of
476+
// `to_wake`, so this assert cannot be removed with also removing
477+
// the `to_wake` assert.
478+
assert_eq!(self.cnt.load(atomics::SeqCst), DISCONNECTED);
479+
assert_eq!(self.to_wake.load(atomics::SeqCst), 0);
482480
}
483481
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// issue #12418
12+
13+
#[deny(unused_unsafe)];
14+
15+
fn main() {
16+
unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
17+
}

0 commit comments

Comments
 (0)