make accessing packed fields a future-compat warning

This commit is contained in:
Ariel Ben-Yehuda 2017-11-16 20:12:23 +02:00 committed by Ariel Ben-Yehuda
parent 06eb5a6645
commit 1a2d443f55
7 changed files with 119 additions and 19 deletions

View File

@ -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]

View File

@ -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,

View File

@ -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)]

View File

@ -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

View File

@ -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,21 +387,31 @@ 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 {
struct_span_err!(
tcx.sess, source_info.span, E0133,
"{} requires unsafe function or block", description)
.span_label(source_info.span, description)
.emit();
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));
}
}
}

View File

@ -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

View 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
}