Skip to content

Commit 55abc0b

Browse files
committed
Also prevent mutation fields directly
1 parent 1894a5f commit 55abc0b

File tree

7 files changed

+57
-25
lines changed

7 files changed

+57
-25
lines changed

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,15 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
187187
kind: UnsafetyViolationKind::BorrowPacked(lint_root)
188188
}], &[]);
189189
}
190-
let is_freeze = base
191-
.ty(self.mir, self.tcx)
192-
.to_ty(self.tcx)
193-
.is_freeze(self.tcx, self.param_env, self.source_info.span);
194-
if context.is_mutating_use() || !is_freeze {
195-
self.check_mut_borrowing_layout_constrained_field(place);
196-
}
190+
}
191+
let is_borrow_of_interior_mut = context.is_borrow() && !base
192+
.ty(self.mir, self.tcx)
193+
.to_ty(self.tcx)
194+
.is_freeze(self.tcx, self.param_env, self.source_info.span);
195+
if context.is_mutating_use() || is_borrow_of_interior_mut {
196+
self.check_mut_borrowing_layout_constrained_field(
197+
place, context.is_mutating_use(),
198+
);
197199
}
198200
let old_source_info = self.source_info;
199201
if let &Place::Local(local) = base {
@@ -360,6 +362,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
360362
fn check_mut_borrowing_layout_constrained_field(
361363
&mut self,
362364
mut place: &Place<'tcx>,
365+
is_mut_use: bool,
363366
) {
364367
while let &Place::Projection(box Projection {
365368
ref base, ref elem
@@ -371,17 +374,26 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
371374
ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
372375
(Bound::Unbounded, Bound::Unbounded) => {},
373376
_ => {
377+
let (description, details) = if is_mut_use {
378+
(
379+
"mutation of layout constrained field",
380+
"mutating layout constrained fields cannot statically be \
381+
checked for valid values",
382+
)
383+
} else {
384+
(
385+
"borrow of layout constrained field with interior \
386+
mutability",
387+
"references to fields of layout constrained fields \
388+
lose the constraints. Coupled with interior mutability, \
389+
the field can be changed to invalid values",
390+
)
391+
};
374392
let source_info = self.source_info;
375393
self.register_violations(&[UnsafetyViolation {
376394
source_info,
377-
description: Symbol::intern(
378-
"borrow of layout constrained field",
379-
).as_interned_str(),
380-
details:
381-
Symbol::intern(
382-
"references to fields of layout constrained fields \
383-
lose the constraints",
384-
).as_interned_str(),
395+
description: Symbol::intern(description).as_interned_str(),
396+
details: Symbol::intern(details).as_interned_str(),
385397
kind: UnsafetyViolationKind::MinConstFn,
386398
}], &[]);
387399
}

src/test/ui/unsafe/ranged_ints2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
pub(crate) struct NonZero<T>(pub(crate) T);
66
fn main() {
77
let mut x = unsafe { NonZero(1) };
8-
let y = &mut x.0; //~ ERROR borrow of layout constrained field is unsafe
8+
let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
99
}

src/test/ui/unsafe/ranged_ints2.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0133]: borrow of layout constrained field is unsafe and requires unsafe function or block
1+
error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
22
--> $DIR/ranged_ints2.rs:8:13
33
|
4-
LL | let y = &mut x.0; //~ ERROR borrow of layout constrained field is unsafe
5-
| ^^^^^^^^ borrow of layout constrained field
4+
LL | let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
5+
| ^^^^^^^^ mutation of layout constrained field
66
|
7-
= note: references to fields of layout constrained fields lose the constraints
7+
= note: mutating layout constrained fields cannot statically be checked for valid values
88

99
error: aborting due to previous error
1010

src/test/ui/unsafe/ranged_ints3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ use std::cell::Cell;
77
pub(crate) struct NonZero<T>(pub(crate) T);
88
fn main() {
99
let mut x = unsafe { NonZero(Cell::new(1)) };
10-
let y = &x.0; //~ ERROR borrow of layout constrained field is unsafe
10+
let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability
1111
}

src/test/ui/unsafe/ranged_ints3.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0133]: borrow of layout constrained field is unsafe and requires unsafe function or block
1+
error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
22
--> $DIR/ranged_ints3.rs:10:13
33
|
4-
LL | let y = &x.0; //~ ERROR borrow of layout constrained field is unsafe
5-
| ^^^^ borrow of layout constrained field
4+
LL | let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability
5+
| ^^^^ borrow of layout constrained field with interior mutability
66
|
7-
= note: references to fields of layout constrained fields lose the constraints
7+
= note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
88

99
error: aborting due to previous error
1010

src/test/ui/unsafe/ranged_ints4.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(rustc_attrs)]
2+
3+
#[rustc_layout_scalar_valid_range_start(1)]
4+
#[repr(transparent)]
5+
pub(crate) struct NonZero<T>(pub(crate) T);
6+
fn main() {
7+
let mut x = unsafe { NonZero(1) };
8+
x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
2+
--> $DIR/ranged_ints4.rs:8:5
3+
|
4+
LL | x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe
5+
| ^^^^^^^ mutation of layout constrained field
6+
|
7+
= note: mutating layout constrained fields cannot statically be checked for valid values
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)