Skip to content

Commit 8bdb11c

Browse files
committed
Forbid the creation of mutable borrows to fields of layout constrained types
1 parent 693c553 commit 8bdb11c

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
187187
kind: UnsafetyViolationKind::BorrowPacked(lint_root)
188188
}], &[]);
189189
}
190+
if context.is_mutating_use() {
191+
self.check_mut_borrowing_layout_constrained_field(place);
192+
}
190193
}
191194
let old_source_info = self.source_info;
192195
if let &Place::Local(local) = base {
@@ -350,6 +353,43 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
350353
(node_id, is_used && !within_unsafe)
351354
}));
352355
}
356+
fn check_mut_borrowing_layout_constrained_field(
357+
&mut self,
358+
mut place: &Place<'tcx>,
359+
) {
360+
while let &Place::Projection(box Projection {
361+
ref base, ref elem
362+
}) = place {
363+
match *elem {
364+
ProjectionElem::Field(..) => {
365+
let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
366+
match ty.sty {
367+
ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
368+
(Bound::Unbounded, Bound::Unbounded) => {},
369+
_ => {
370+
let source_info = self.source_info;
371+
self.register_violations(&[UnsafetyViolation {
372+
source_info,
373+
description: Symbol::intern(
374+
"borrow of layout constrained field",
375+
).as_interned_str(),
376+
details:
377+
Symbol::intern(
378+
"references to fields of layout constrained fields \
379+
lose the constraints",
380+
).as_interned_str(),
381+
kind: UnsafetyViolationKind::MinConstFn,
382+
}], &[]);
383+
}
384+
},
385+
_ => {}
386+
}
387+
}
388+
_ => {}
389+
}
390+
place = base;
391+
}
392+
}
353393
}
354394

355395
pub(crate) fn provide(providers: &mut Providers) {

src/test/ui/unsafe/ranged_ints.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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 _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
8+
}

src/test/ui/unsafe/ranged_ints.stderr

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
2+
--> $DIR/ranged_ints.rs:7:14
3+
|
4+
LL | let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
5+
| ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
6+
|
7+
= note: initializing `NonZero` with a `0` violates layout constraints and is undefined behavior
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0133`.

src/test/ui/unsafe/ranged_ints2.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+
let y = &mut x.0; //~ ERROR borrow 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]: borrow of layout constrained field is unsafe and requires unsafe function or block
2+
--> $DIR/ranged_ints2.rs:8:13
3+
|
4+
LL | let y = &mut x.0; //~ ERROR borrow of layout constrained field is unsafe
5+
| ^^^^^^^^ borrow of layout constrained field
6+
|
7+
= note: references to fields of layout constrained fields lose the constraints
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)