make accessing packed fields a future-compat warning
This commit is contained in:
parent
06eb5a6645
commit
1a2d443f55
@ -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::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<'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>>
|
||||
for mir::Terminator<'gcx> {
|
||||
#[inline]
|
||||
|
@ -155,6 +155,12 @@ declare_lint! {
|
||||
"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! {
|
||||
pub PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
Warn,
|
||||
@ -247,6 +253,7 @@ impl LintPass for HardwiredLints {
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
|
||||
SAFE_EXTERN_STATICS,
|
||||
SAFE_PACKED_BORROWS,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
LEGACY_DIRECTORY_OWNERSHIP,
|
||||
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)]
|
||||
pub struct UnsafetyViolation {
|
||||
pub source_info: SourceInfo,
|
||||
pub description: &'static str,
|
||||
pub lint_node_id: Option<ast::NodeId>,
|
||||
pub kind: UnsafetyViolationKind,
|
||||
}
|
||||
|
||||
#[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),
|
||||
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
|
||||
|
@ -15,7 +15,7 @@ use rustc::ty::maps::Providers;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::hir;
|
||||
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::visit::{LvalueContext, Visitor};
|
||||
|
||||
@ -140,7 +140,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||
location: Location) {
|
||||
if let LvalueContext::Borrow { .. } = context {
|
||||
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 {
|
||||
source_info,
|
||||
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;
|
||||
self.register_violations(&[UnsafetyViolation {
|
||||
source_info, description, lint_node_id: None
|
||||
source_info, description, kind: UnsafetyViolationKind::General
|
||||
}], &[]);
|
||||
}
|
||||
|
||||
@ -380,22 +387,32 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
|
||||
} = tcx.unsafety_check_result(def_id);
|
||||
|
||||
for &UnsafetyViolation {
|
||||
source_info, description, lint_node_id
|
||||
source_info, description, kind
|
||||
} in violations.iter() {
|
||||
// Report an error.
|
||||
if let Some(lint_node_id) = lint_node_id {
|
||||
tcx.lint_node(SAFE_EXTERN_STATICS,
|
||||
lint_node_id,
|
||||
source_info.span,
|
||||
&format!("{} requires unsafe function or \
|
||||
block (error E0133)", description));
|
||||
} else {
|
||||
match kind {
|
||||
UnsafetyViolationKind::General => {
|
||||
struct_span_err!(
|
||||
tcx.sess, source_info.span, E0133,
|
||||
"{} requires unsafe function or block", description)
|
||||
.span_label(source_info.span, description)
|
||||
.emit();
|
||||
}
|
||||
UnsafetyViolationKind::ExternStatic(lint_node_id) => {
|
||||
tcx.lint_node(SAFE_EXTERN_STATICS,
|
||||
lint_node_id,
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect();
|
||||
|
@ -20,6 +20,7 @@ pub struct JustArray {
|
||||
array: [u32]
|
||||
}
|
||||
|
||||
#[deny(safe_packed_borrows)]
|
||||
fn main() {
|
||||
let good = Good {
|
||||
data: &0,
|
||||
@ -33,7 +34,9 @@ fn main() {
|
||||
}
|
||||
|
||||
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
|
||||
//~| hard error
|
||||
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
|
||||
//~| hard error
|
||||
let _ = &*good.data; // ok, behind a pointer
|
||||
let _ = &good.aligned; // 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…
Reference in New Issue
Block a user