From aadbcffb7c59718834c63c20ab7ce6276aef430c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 26 Aug 2016 19:23:42 +0300 Subject: [PATCH] Issue deprecation warnings for safe accesses to extern statics --- src/doc/book/ffi.md | 2 +- src/libpanic_unwind/seh.rs | 4 +- src/librustc/lint/builtin.rs | 9 ++++- src/librustc/middle/effect.rs | 40 ++++++++++++++----- src/librustc_lint/lib.rs | 4 ++ .../compile-fail/auxiliary/extern-statics.rs | 14 +++++++ src/test/compile-fail/linkage2.rs | 2 +- src/test/compile-fail/linkage3.rs | 2 +- .../compile-fail/safe-extern-statics-mut.rs | 28 +++++++++++++ src/test/compile-fail/safe-extern-statics.rs | 32 +++++++++++++++ .../check-static-recursion-foreign.rs | 2 +- 11 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/extern-statics.rs create mode 100644 src/test/compile-fail/safe-extern-statics-mut.rs create mode 100644 src/test/compile-fail/safe-extern-statics.rs diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 1dea15311ce82..8709c3f4b7b10 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -471,7 +471,7 @@ extern { fn main() { println!("You have readline version {} installed.", - rl_readline_version as i32); + unsafe { rl_readline_version as i32 }); } ``` diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index dd6e92fe9ae19..5896421493008 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -232,13 +232,13 @@ extern "C" { // Again, I'm not entirely sure what this is describing, it just seems to work. #[cfg_attr(not(test), lang = "msvc_try_filter")] static mut TYPE_DESCRIPTOR1: _TypeDescriptor = _TypeDescriptor { - pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _, + pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: 0 as *mut _, name: imp::NAME1, }; static mut TYPE_DESCRIPTOR2: _TypeDescriptor = _TypeDescriptor { - pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _, + pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: 0 as *mut _, name: imp::NAME2, }; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index ed94e5fe377c4..fa77c911b4651 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -192,6 +192,12 @@ declare_lint! { "lifetimes or labels named `'_` were erroneously allowed" } +declare_lint! { + pub SAFE_EXTERN_STATICS, + Warn, + "safe access to extern statics was erroneously allowed" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -228,7 +234,8 @@ impl LintPass for HardwiredLints { RENAMED_AND_REMOVED_LINTS, SUPER_OR_SELF_IN_GLOBAL_PATH, HR_LIFETIME_IN_ASSOC_TYPE, - LIFETIME_UNDERSCORE + LIFETIME_UNDERSCORE, + SAFE_EXTERN_STATICS ) } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index a7af0b50b8494..082db569e18c6 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -15,6 +15,7 @@ use self::RootUnsafeContext::*; use dep_graph::DepNode; use ty::{self, Ty, TyCtxt}; use ty::MethodCall; +use lint; use syntax::ast; use syntax_pos::Span; @@ -57,16 +58,25 @@ struct EffectCheckVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { - fn require_unsafe(&mut self, span: Span, description: &str) { + fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span, + description: &str, is_lint: bool) { if self.unsafe_context.push_unsafe_count > 0 { return; } match self.unsafe_context.root { SafeContext => { - // Report an error. - struct_span_err!( - self.tcx.sess, span, E0133, - "{} requires unsafe function or block", description) - .span_label(span, &description) - .emit(); + if is_lint { + self.tcx.sess.add_lint(lint::builtin::SAFE_EXTERN_STATICS, + node_id, + span, + format!("{} requires unsafe function or \ + block (error E0133)", description)); + } else { + // Report an error. + struct_span_err!( + self.tcx.sess, span, E0133, + "{} requires unsafe function or block", description) + .span_label(span, &description) + .emit(); + } } UnsafeBlock(block_id) => { // OK, but record this. @@ -76,6 +86,10 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { UnsafeFn => {} } } + + fn require_unsafe(&mut self, span: Span, description: &str) { + self.require_unsafe_ext(ast::DUMMY_NODE_ID, span, description, false) + } } impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { @@ -173,8 +187,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { self.require_unsafe(expr.span, "use of inline assembly"); } hir::ExprPath(..) => { - if let Def::Static(_, true) = self.tcx.expect_def(expr.id) { - self.require_unsafe(expr.span, "use of mutable static"); + if let Def::Static(def_id, mutbl) = self.tcx.expect_def(expr.id) { + if mutbl { + self.require_unsafe(expr.span, "use of mutable static"); + } else if match self.tcx.map.get_if_local(def_id) { + Some(hir::map::NodeForeignItem(..)) => true, + Some(..) => false, + None => self.tcx.sess.cstore.is_foreign_item(def_id), + } { + self.require_unsafe_ext(expr.id, expr.span, "use of extern static", true); + } } } hir::ExprField(ref base_expr, field) => { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index b9817cc6ff45a..bc2979c806f65 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -201,6 +201,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LIFETIME_UNDERSCORE), reference: "RFC 1177 ", }, + FutureIncompatibleInfo { + id: LintId::of(SAFE_EXTERN_STATICS), + reference: "issue 36247 ", + }, ]); // Register renamed and removed lints diff --git a/src/test/compile-fail/auxiliary/extern-statics.rs b/src/test/compile-fail/auxiliary/extern-statics.rs new file mode 100644 index 0000000000000..07f70b177b3b5 --- /dev/null +++ b/src/test/compile-fail/auxiliary/extern-statics.rs @@ -0,0 +1,14 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { + pub static XA: u8; + pub static mut XB: u8; +} diff --git a/src/test/compile-fail/linkage2.rs b/src/test/compile-fail/linkage2.rs index 2a127d937eaaa..afae4a451d699 100644 --- a/src/test/compile-fail/linkage2.rs +++ b/src/test/compile-fail/linkage2.rs @@ -16,5 +16,5 @@ extern { } fn main() { - println!("{}", foo); + println!("{}", unsafe { foo }); } diff --git a/src/test/compile-fail/linkage3.rs b/src/test/compile-fail/linkage3.rs index 8343f718902dc..c222989ed6677 100644 --- a/src/test/compile-fail/linkage3.rs +++ b/src/test/compile-fail/linkage3.rs @@ -16,5 +16,5 @@ extern { } fn main() { - println!("{:?}", foo); + println!("{:?}", unsafe { foo }); } diff --git a/src/test/compile-fail/safe-extern-statics-mut.rs b/src/test/compile-fail/safe-extern-statics-mut.rs new file mode 100644 index 0000000000000..b5f3b4535df92 --- /dev/null +++ b/src/test/compile-fail/safe-extern-statics-mut.rs @@ -0,0 +1,28 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:extern-statics.rs + +#![allow(unused)] +#![deny(safe_extern_statics)] + +extern crate extern_statics; +use extern_statics::*; + +extern { + static mut B: u8; +} + +fn main() { + let b = B; //~ ERROR use of mutable static requires unsafe function or block + let rb = &B; //~ ERROR use of mutable static requires unsafe function or block + let xb = XB; //~ ERROR use of mutable static requires unsafe function or block + let xrb = &XB; //~ ERROR use of mutable static requires unsafe function or block +} diff --git a/src/test/compile-fail/safe-extern-statics.rs b/src/test/compile-fail/safe-extern-statics.rs new file mode 100644 index 0000000000000..7e96897ee882b --- /dev/null +++ b/src/test/compile-fail/safe-extern-statics.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:extern-statics.rs + +#![allow(unused)] +#![deny(safe_extern_statics)] + +extern crate extern_statics; +use extern_statics::*; + +extern { + static A: u8; +} + +fn main() { + let a = A; //~ ERROR use of extern static requires unsafe function or block + //~^ WARN this was previously accepted by the compiler + let ra = &A; //~ ERROR use of extern static requires unsafe function or block + //~^ WARN this was previously accepted by the compiler + let xa = XA; //~ ERROR use of extern static requires unsafe function or block + //~^ WARN this was previously accepted by the compiler + let xra = &XA; //~ ERROR use of extern static requires unsafe function or block + //~^ WARN this was previously accepted by the compiler +} diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs index 554853ade5be6..8e718f328ff91 100644 --- a/src/test/run-pass/check-static-recursion-foreign.rs +++ b/src/test/run-pass/check-static-recursion-foreign.rs @@ -27,6 +27,6 @@ extern "C" { static test_static: c_int; } -static B: &'static c_int = &test_static; +static B: &'static c_int = unsafe { &test_static }; pub fn main() {}