Skip to content

Commit 1a2d443

Browse files
arielb1Ariel Ben-Yehuda
authored and
Ariel Ben-Yehuda
committed
make accessing packed fields a future-compat warning
1 parent 06eb5a6 commit 1a2d443

File tree

7 files changed

+119
-19
lines changed

7 files changed

+119
-19
lines changed

src/librustc/ich/impls_mir.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,28 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
3333
});
3434
impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
3535
impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
36-
impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, lint_node_id });
36+
impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind });
3737
impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
3838

39+
impl<'gcx> HashStable<StableHashingContext<'gcx>>
40+
for mir::UnsafetyViolationKind {
41+
#[inline]
42+
fn hash_stable<W: StableHasherResult>(&self,
43+
hcx: &mut StableHashingContext<'gcx>,
44+
hasher: &mut StableHasher<W>) {
45+
46+
mem::discriminant(self).hash_stable(hcx, hasher);
47+
48+
match *self {
49+
mir::UnsafetyViolationKind::General => {}
50+
mir::UnsafetyViolationKind::ExternStatic(lint_node_id) |
51+
mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
52+
lint_node_id.hash_stable(hcx, hasher);
53+
}
54+
55+
}
56+
}
57+
}
3958
impl<'gcx> HashStable<StableHashingContext<'gcx>>
4059
for mir::Terminator<'gcx> {
4160
#[inline]

src/librustc/lint/builtin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ declare_lint! {
155155
"safe access to extern statics was erroneously allowed"
156156
}
157157

158+
declare_lint! {
159+
pub SAFE_PACKED_BORROWS,
160+
Warn,
161+
"safe borrows of fields of packed structs were was erroneously allowed"
162+
}
163+
158164
declare_lint! {
159165
pub PATTERNS_IN_FNS_WITHOUT_BODY,
160166
Warn,
@@ -247,6 +253,7 @@ impl LintPass for HardwiredLints {
247253
RENAMED_AND_REMOVED_LINTS,
248254
RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
249255
SAFE_EXTERN_STATICS,
256+
SAFE_PACKED_BORROWS,
250257
PATTERNS_IN_FNS_WITHOUT_BODY,
251258
LEGACY_DIRECTORY_OWNERSHIP,
252259
LEGACY_IMPORTS,

src/librustc/mir/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1722,11 +1722,18 @@ impl Location {
17221722
}
17231723
}
17241724

1725+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1726+
pub enum UnsafetyViolationKind {
1727+
General,
1728+
ExternStatic(ast::NodeId),
1729+
BorrowPacked(ast::NodeId),
1730+
}
1731+
17251732
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
17261733
pub struct UnsafetyViolation {
17271734
pub source_info: SourceInfo,
17281735
pub description: &'static str,
1729-
pub lint_node_id: Option<ast::NodeId>,
1736+
pub kind: UnsafetyViolationKind,
17301737
}
17311738

17321739
#[derive(Clone, Debug, PartialEq, Eq, Hash)]

src/librustc_lint/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
243243
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
244244
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
245245
},
246+
FutureIncompatibleInfo {
247+
id: LintId::of(SAFE_PACKED_BORROWS),
248+
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
249+
},
250+
246251
]);
247252

248253
// Register renamed and removed lints

src/librustc_mir/transform/check_unsafety.rs

+34-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc::ty::maps::Providers;
1515
use rustc::ty::{self, TyCtxt};
1616
use rustc::hir;
1717
use rustc::hir::def_id::DefId;
18-
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, UNUSED_UNSAFE};
18+
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
1919
use rustc::mir::*;
2020
use rustc::mir::visit::{LvalueContext, Visitor};
2121

@@ -140,7 +140,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
140140
location: Location) {
141141
if let LvalueContext::Borrow { .. } = context {
142142
if util::is_disaligned(self.tcx, self.mir, self.param_env, lvalue) {
143-
self.require_unsafe("borrow of packed field")
143+
let source_info = self.source_info;
144+
let lint_root =
145+
self.visibility_scope_info[source_info.scope].lint_root;
146+
self.register_violations(&[UnsafetyViolation {
147+
source_info,
148+
description: "borrow of packed field",
149+
kind: UnsafetyViolationKind::BorrowPacked(lint_root)
150+
}], &[]);
144151
}
145152
}
146153

@@ -203,7 +210,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
203210
self.register_violations(&[UnsafetyViolation {
204211
source_info,
205212
description: "use of extern static",
206-
lint_node_id: Some(lint_root)
213+
kind: UnsafetyViolationKind::ExternStatic(lint_root)
207214
}], &[]);
208215
}
209216
}
@@ -218,7 +225,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
218225
{
219226
let source_info = self.source_info;
220227
self.register_violations(&[UnsafetyViolation {
221-
source_info, description, lint_node_id: None
228+
source_info, description, kind: UnsafetyViolationKind::General
222229
}], &[]);
223230
}
224231

@@ -380,21 +387,31 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
380387
} = tcx.unsafety_check_result(def_id);
381388

382389
for &UnsafetyViolation {
383-
source_info, description, lint_node_id
390+
source_info, description, kind
384391
} in violations.iter() {
385392
// Report an error.
386-
if let Some(lint_node_id) = lint_node_id {
387-
tcx.lint_node(SAFE_EXTERN_STATICS,
388-
lint_node_id,
389-
source_info.span,
390-
&format!("{} requires unsafe function or \
391-
block (error E0133)", description));
392-
} else {
393-
struct_span_err!(
394-
tcx.sess, source_info.span, E0133,
395-
"{} requires unsafe function or block", description)
396-
.span_label(source_info.span, description)
397-
.emit();
393+
match kind {
394+
UnsafetyViolationKind::General => {
395+
struct_span_err!(
396+
tcx.sess, source_info.span, E0133,
397+
"{} requires unsafe function or block", description)
398+
.span_label(source_info.span, description)
399+
.emit();
400+
}
401+
UnsafetyViolationKind::ExternStatic(lint_node_id) => {
402+
tcx.lint_node(SAFE_EXTERN_STATICS,
403+
lint_node_id,
404+
source_info.span,
405+
&format!("{} requires unsafe function or \
406+
block (error E0133)", description));
407+
}
408+
UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
409+
tcx.lint_node(SAFE_PACKED_BORROWS,
410+
lint_node_id,
411+
source_info.span,
412+
&format!("{} requires unsafe function or \
413+
block (error E0133)", description));
414+
}
398415
}
399416
}
400417

src/test/compile-fail/issue-27060.rs

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct JustArray {
2020
array: [u32]
2121
}
2222

23+
#[deny(safe_packed_borrows)]
2324
fn main() {
2425
let good = Good {
2526
data: &0,
@@ -33,7 +34,9 @@ fn main() {
3334
}
3435

3536
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
37+
//~| hard error
3638
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
39+
//~| hard error
3740
let _ = &*good.data; // ok, behind a pointer
3841
let _ = &good.aligned; // ok, has align 1
3942
let _ = &good.aligned[2]; // ok, has align 1

src/test/run-pass/issue-27060.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[repr(packed)]
12+
pub struct Good {
13+
data: &'static u32,
14+
data2: [&'static u32; 2],
15+
aligned: [u8; 32],
16+
}
17+
18+
#[repr(packed)]
19+
pub struct JustArray {
20+
array: [u32]
21+
}
22+
23+
// kill this test when that turns to a hard error
24+
#[allow(safe_packed_borrows)]
25+
fn main() {
26+
let good = Good {
27+
data: &0,
28+
data2: [&0, &0],
29+
aligned: [0; 32]
30+
};
31+
32+
unsafe {
33+
let _ = &good.data; // ok
34+
let _ = &good.data2[0]; // ok
35+
}
36+
37+
let _ = &good.data;
38+
let _ = &good.data2[0];
39+
let _ = &*good.data; // ok, behind a pointer
40+
let _ = &good.aligned; // ok, has align 1
41+
let _ = &good.aligned[2]; // ok, has align 1
42+
}

0 commit comments

Comments
 (0)