Skip to content

Commit c089a17

Browse files
committed
Improve the unused unsafe block warning to include unsafe blocks in unsafe functions
1 parent 8708e0c commit c089a17

File tree

3 files changed

+71
-43
lines changed

3 files changed

+71
-43
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use core::prelude::*;
2121

2222
use middle::moves;
23+
use middle::typeck::check::PurityState;
2324
use middle::borrowck::{Loan, bckerr, BorrowckCtxt, inherent_mutability};
2425
use middle::borrowck::{ReqMaps, root_map_key, save_and_restore_managed};
2526
use middle::borrowck::{MoveError, MoveOk, MoveFromIllegalCmt};
@@ -41,11 +42,6 @@ use syntax::codemap::span;
4142
use syntax::print::pprust;
4243
use syntax::visit;
4344

44-
struct PurityState {
45-
def: ast::node_id,
46-
purity: ast::purity
47-
}
48-
4945
struct CheckLoanCtxt {
5046
bccx: @BorrowckCtxt,
5147
req_maps: ReqMaps,
@@ -85,8 +81,7 @@ pub fn check_loans(bccx: @BorrowckCtxt,
8581
bccx: bccx,
8682
req_maps: req_maps,
8783
reported: HashSet::new(),
88-
declared_purity: @mut PurityState { purity: ast::impure_fn,
89-
def: 0 },
84+
declared_purity: @mut PurityState::function(ast::impure_fn, 0),
9085
fn_args: @mut @~[]
9186
};
9287
let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr,
@@ -658,9 +653,7 @@ fn check_loans_in_fn(fk: &visit::fn_kind,
658653
debug!("purity on entry=%?", copy self.declared_purity);
659654
do save_and_restore_managed(self.declared_purity) {
660655
do save_and_restore_managed(self.fn_args) {
661-
self.declared_purity = @mut PurityState {
662-
purity: declared_purity, def: src
663-
};
656+
self.declared_purity = @mut PurityState::function(declared_purity, src);
664657
665658
match *fk {
666659
visit::fk_anon(*) |
@@ -810,17 +803,7 @@ fn check_loans_in_block(blk: &ast::blk,
810803
do save_and_restore_managed(self.declared_purity) {
811804
self.check_for_conflicting_loans(blk.node.id);
812805

813-
match blk.node.rules {
814-
ast::default_blk => {
815-
}
816-
ast::unsafe_blk => {
817-
*self.declared_purity = PurityState {
818-
purity: ast::unsafe_fn,
819-
def: blk.node.id,
820-
};
821-
}
822-
}
823-
806+
*self.declared_purity = self.declared_purity.recurse(blk);
824807
visit::visit_block(blk, self, vt);
825808
}
826809
}

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

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ use core::result::{Result, Ok, Err};
115115
use core::result;
116116
use core::str;
117117
use core::vec;
118+
use core::util::replace;
118119
use std::list::Nil;
119120
use syntax::abi::AbiSet;
120121
use syntax::ast::{provided, required};
@@ -179,9 +180,36 @@ pub enum FnKind {
179180
Vanilla
180181
}
181182

182-
struct PurityState {
183+
pub struct PurityState {
184+
def: ast::node_id,
183185
purity: ast::purity,
184-
from: ast::node_id,
186+
priv from_fn: bool
187+
}
188+
189+
pub impl PurityState {
190+
pub fn function(purity: ast::purity, def: ast::node_id) -> PurityState {
191+
PurityState { def: def, purity: purity, from_fn: true }
192+
}
193+
194+
pub fn recurse(&mut self, blk: &ast::blk) -> PurityState {
195+
match self.purity {
196+
// If this unsafe, then if the outer function was already marked as
197+
// unsafe we shouldn't attribute the unsafe'ness to the block. This
198+
// way the block can be warned about instead of ignoring this
199+
// extraneous block (functions are never warned about).
200+
ast::unsafe_fn if self.from_fn => *self,
201+
202+
purity => {
203+
let (purity, def) = match blk.node.rules {
204+
ast::unsafe_blk => (ast::unsafe_fn, blk.node.id),
205+
ast::default_blk => (purity, self.def),
206+
};
207+
PurityState{ def: def,
208+
purity: purity,
209+
from_fn: false }
210+
}
211+
}
212+
}
185213
}
186214

187215
pub struct FnCtxt {
@@ -243,7 +271,7 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
243271
@mut FnCtxt {
244272
ret_ty: rty,
245273
indirect_ret_ty: None,
246-
ps: PurityState { purity: ast::pure_fn, from: 0 },
274+
ps: PurityState::function(ast::pure_fn, 0),
247275
region_lb: region_bnd,
248276
in_scope_regions: @Nil,
249277
fn_kind: Vanilla,
@@ -348,7 +376,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
348376
@mut FnCtxt {
349377
ret_ty: ret_ty,
350378
indirect_ret_ty: indirect_ret_ty,
351-
ps: PurityState { purity: purity, from: id },
379+
ps: PurityState::function(purity, id),
352380
region_lb: body.node.id,
353381
in_scope_regions: isr,
354382
fn_kind: fn_kind,
@@ -876,8 +904,8 @@ pub impl FnCtxt {
876904
match self.ps.purity {
877905
ast::unsafe_fn => {
878906
// ok, but flag that we used the source of unsafeness
879-
debug!("flagging %? as a used unsafe source", self.ps.from);
880-
self.tcx().used_unsafe.insert(self.ps.from);
907+
debug!("flagging %? as a used unsafe source", self.ps);
908+
self.tcx().used_unsafe.insert(self.ps.def);
881909
}
882910
_ => {
883911
self.ccx.tcx.sess.span_err(
@@ -1689,7 +1717,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
16891717
fcx.write_ty(expr.id, fty);
16901718

16911719
let (inherited_purity, id) =
1692-
ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.from),
1720+
ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.def),
16931721
(purity, expr.id),
16941722
sigil);
16951723

@@ -2929,16 +2957,11 @@ pub fn check_block(fcx0: @mut FnCtxt, blk: &ast::blk) {
29292957
check_block_with_expected(fcx0, blk, None)
29302958
}
29312959

2932-
pub fn check_block_with_expected(fcx0: @mut FnCtxt,
2960+
pub fn check_block_with_expected(fcx: @mut FnCtxt,
29332961
blk: &ast::blk,
29342962
expected: Option<ty::t>) {
2935-
let fcx = match blk.node.rules {
2936-
ast::unsafe_blk => @mut FnCtxt {
2937-
ps: PurityState { purity: ast::unsafe_fn, from: blk.node.id },
2938-
.. copy *fcx0
2939-
},
2940-
ast::default_blk => fcx0
2941-
};
2963+
let prev = replace(&mut fcx.ps, fcx.ps.recurse(blk));
2964+
29422965
do fcx.with_region_lb(blk.node.id) {
29432966
let mut warned = false;
29442967
let mut last_was_bot = false;
@@ -2990,6 +3013,8 @@ pub fn check_block_with_expected(fcx0: @mut FnCtxt,
29903013
}
29913014
};
29923015
}
3016+
3017+
fcx.ps = prev;
29933018
}
29943019

29953020
pub fn check_const(ccx: @mut CrateCtxt,

src/test/compile-fail/unused-unsafe.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,50 @@
1212

1313
#[deny(unused_unsafe)];
1414

15-
use core::libc;
15+
extern mod foo {
16+
fn bar();
17+
}
1618

1719
fn callback<T>(_f: &fn() -> T) -> T { fail!() }
20+
unsafe fn unsf() {}
1821

1922
fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
2023
fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block
21-
unsafe fn bad4() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
22-
fn bad5() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block
24+
unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
25+
fn bad4() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block
26+
unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block
27+
fn bad6() {
28+
unsafe { //~ ERROR: unnecessary `unsafe` block
29+
unsafe { // don't put the warning here
30+
unsf()
31+
}
32+
}
33+
}
34+
unsafe fn bad7() {
35+
unsafe { //~ ERROR: unnecessary `unsafe` block
36+
unsafe { //~ ERROR: unnecessary `unsafe` block
37+
unsf()
38+
}
39+
}
40+
}
2341

24-
unsafe fn good0() { libc::exit(1) }
25-
fn good1() { unsafe { libc::exit(1) } }
42+
unsafe fn good0() { unsf() }
43+
fn good1() { unsafe { unsf() } }
2644
fn good2() {
2745
/* bug uncovered when implementing warning about unused unsafe blocks. Be
2846
sure that when purity is inherited that the source of the unsafe-ness
2947
is tracked correctly */
3048
unsafe {
31-
unsafe fn what() -> ~[~str] { libc::exit(2) }
49+
unsafe fn what() -> ~[~str] { fail!() }
3250

3351
do callback {
3452
what();
3553
}
3654
}
3755
}
56+
unsafe fn good3() { foo::bar() }
57+
fn good4() { unsafe { foo::bar() } }
3858

3959
#[allow(unused_unsafe)] fn allowed() { unsafe {} }
4060

41-
fn main() { }
61+
fn main() {}

0 commit comments

Comments
 (0)