make accessing packed fields a future-compat warning
This commit is contained in:
parent
06eb5a6645
commit
1a2d443f55
7 changed files with 119 additions and 19 deletions
|
@ -33,9 +33,28 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
|
||||||
});
|
});
|
||||||
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
|
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::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::UnsafetyViolation { source_info, description, kind });
|
||||||
impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
|
impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
|
||||||
|
|
||||||
|
impl<'gcx> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for mir::UnsafetyViolationKind {
|
||||||
|
#[inline]
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
mir::UnsafetyViolationKind::General => {}
|
||||||
|
mir::UnsafetyViolationKind::ExternStatic(lint_node_id) |
|
||||||
|
mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
|
||||||
|
lint_node_id.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<'gcx> HashStable<StableHashingContext<'gcx>>
|
impl<'gcx> HashStable<StableHashingContext<'gcx>>
|
||||||
for mir::Terminator<'gcx> {
|
for mir::Terminator<'gcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -155,6 +155,12 @@ declare_lint! {
|
||||||
"safe access to extern statics was erroneously allowed"
|
"safe access to extern statics was erroneously allowed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
pub SAFE_PACKED_BORROWS,
|
||||||
|
Warn,
|
||||||
|
"safe borrows of fields of packed structs were was erroneously allowed"
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub PATTERNS_IN_FNS_WITHOUT_BODY,
|
pub PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
Warn,
|
Warn,
|
||||||
|
@ -247,6 +253,7 @@ impl LintPass for HardwiredLints {
|
||||||
RENAMED_AND_REMOVED_LINTS,
|
RENAMED_AND_REMOVED_LINTS,
|
||||||
RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
||||||
SAFE_EXTERN_STATICS,
|
SAFE_EXTERN_STATICS,
|
||||||
|
SAFE_PACKED_BORROWS,
|
||||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
LEGACY_DIRECTORY_OWNERSHIP,
|
LEGACY_DIRECTORY_OWNERSHIP,
|
||||||
LEGACY_IMPORTS,
|
LEGACY_IMPORTS,
|
||||||
|
|
|
@ -1722,11 +1722,18 @@ impl Location {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum UnsafetyViolationKind {
|
||||||
|
General,
|
||||||
|
ExternStatic(ast::NodeId),
|
||||||
|
BorrowPacked(ast::NodeId),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct UnsafetyViolation {
|
pub struct UnsafetyViolation {
|
||||||
pub source_info: SourceInfo,
|
pub source_info: SourceInfo,
|
||||||
pub description: &'static str,
|
pub description: &'static str,
|
||||||
pub lint_node_id: Option<ast::NodeId>,
|
pub kind: UnsafetyViolationKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -243,6 +243,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||||
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
|
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
|
||||||
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
|
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
|
||||||
},
|
},
|
||||||
|
FutureIncompatibleInfo {
|
||||||
|
id: LintId::of(SAFE_PACKED_BORROWS),
|
||||||
|
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
|
||||||
|
},
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Register renamed and removed lints
|
// Register renamed and removed lints
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc::ty::maps::Providers;
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, UNUSED_UNSAFE};
|
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::visit::{LvalueContext, Visitor};
|
use rustc::mir::visit::{LvalueContext, Visitor};
|
||||||
|
|
||||||
|
@ -140,7 +140,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
location: Location) {
|
location: Location) {
|
||||||
if let LvalueContext::Borrow { .. } = context {
|
if let LvalueContext::Borrow { .. } = context {
|
||||||
if util::is_disaligned(self.tcx, self.mir, self.param_env, lvalue) {
|
if util::is_disaligned(self.tcx, self.mir, self.param_env, lvalue) {
|
||||||
self.require_unsafe("borrow of packed field")
|
let source_info = self.source_info;
|
||||||
|
let lint_root =
|
||||||
|
self.visibility_scope_info[source_info.scope].lint_root;
|
||||||
|
self.register_violations(&[UnsafetyViolation {
|
||||||
|
source_info,
|
||||||
|
description: "borrow of packed field",
|
||||||
|
kind: UnsafetyViolationKind::BorrowPacked(lint_root)
|
||||||
|
}], &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +210,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
self.register_violations(&[UnsafetyViolation {
|
self.register_violations(&[UnsafetyViolation {
|
||||||
source_info,
|
source_info,
|
||||||
description: "use of extern static",
|
description: "use of extern static",
|
||||||
lint_node_id: Some(lint_root)
|
kind: UnsafetyViolationKind::ExternStatic(lint_root)
|
||||||
}], &[]);
|
}], &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,7 +225,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
let source_info = self.source_info;
|
let source_info = self.source_info;
|
||||||
self.register_violations(&[UnsafetyViolation {
|
self.register_violations(&[UnsafetyViolation {
|
||||||
source_info, description, lint_node_id: None
|
source_info, description, kind: UnsafetyViolationKind::General
|
||||||
}], &[]);
|
}], &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,21 +387,31 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
|
||||||
} = tcx.unsafety_check_result(def_id);
|
} = tcx.unsafety_check_result(def_id);
|
||||||
|
|
||||||
for &UnsafetyViolation {
|
for &UnsafetyViolation {
|
||||||
source_info, description, lint_node_id
|
source_info, description, kind
|
||||||
} in violations.iter() {
|
} in violations.iter() {
|
||||||
// Report an error.
|
// Report an error.
|
||||||
if let Some(lint_node_id) = lint_node_id {
|
match kind {
|
||||||
tcx.lint_node(SAFE_EXTERN_STATICS,
|
UnsafetyViolationKind::General => {
|
||||||
lint_node_id,
|
struct_span_err!(
|
||||||
source_info.span,
|
tcx.sess, source_info.span, E0133,
|
||||||
&format!("{} requires unsafe function or \
|
"{} requires unsafe function or block", description)
|
||||||
block (error E0133)", description));
|
.span_label(source_info.span, description)
|
||||||
} else {
|
.emit();
|
||||||
struct_span_err!(
|
}
|
||||||
tcx.sess, source_info.span, E0133,
|
UnsafetyViolationKind::ExternStatic(lint_node_id) => {
|
||||||
"{} requires unsafe function or block", description)
|
tcx.lint_node(SAFE_EXTERN_STATICS,
|
||||||
.span_label(source_info.span, description)
|
lint_node_id,
|
||||||
.emit();
|
source_info.span,
|
||||||
|
&format!("{} requires unsafe function or \
|
||||||
|
block (error E0133)", description));
|
||||||
|
}
|
||||||
|
UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
|
||||||
|
tcx.lint_node(SAFE_PACKED_BORROWS,
|
||||||
|
lint_node_id,
|
||||||
|
source_info.span,
|
||||||
|
&format!("{} requires unsafe function or \
|
||||||
|
block (error E0133)", description));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct JustArray {
|
||||||
array: [u32]
|
array: [u32]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deny(safe_packed_borrows)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let good = Good {
|
let good = Good {
|
||||||
data: &0,
|
data: &0,
|
||||||
|
@ -33,7 +34,9 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
|
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
|
||||||
|
//~| hard error
|
||||||
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
|
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
|
||||||
|
//~| hard error
|
||||||
let _ = &*good.data; // ok, behind a pointer
|
let _ = &*good.data; // ok, behind a pointer
|
||||||
let _ = &good.aligned; // ok, has align 1
|
let _ = &good.aligned; // ok, has align 1
|
||||||
let _ = &good.aligned[2]; // ok, has align 1
|
let _ = &good.aligned[2]; // ok, has align 1
|
||||||
|
|
42
src/test/run-pass/issue-27060.rs
Normal file
42
src/test/run-pass/issue-27060.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct Good {
|
||||||
|
data: &'static u32,
|
||||||
|
data2: [&'static u32; 2],
|
||||||
|
aligned: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct JustArray {
|
||||||
|
array: [u32]
|
||||||
|
}
|
||||||
|
|
||||||
|
// kill this test when that turns to a hard error
|
||||||
|
#[allow(safe_packed_borrows)]
|
||||||
|
fn main() {
|
||||||
|
let good = Good {
|
||||||
|
data: &0,
|
||||||
|
data2: [&0, &0],
|
||||||
|
aligned: [0; 32]
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let _ = &good.data; // ok
|
||||||
|
let _ = &good.data2[0]; // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = &good.data;
|
||||||
|
let _ = &good.data2[0];
|
||||||
|
let _ = &*good.data; // ok, behind a pointer
|
||||||
|
let _ = &good.aligned; // ok, has align 1
|
||||||
|
let _ = &good.aligned[2]; // ok, has align 1
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue