]> git.lizzy.rs Git - rust.git/commitdiff
Forbid the creation of mutable borrows to fields of layout constrained types
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Sat, 3 Nov 2018 15:30:05 +0000 (16:30 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Tue, 4 Dec 2018 09:17:36 +0000 (10:17 +0100)
src/librustc_mir/transform/check_unsafety.rs
src/test/ui/unsafe/ranged_ints.rs [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints.stderr [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints2.rs [new file with mode: 0644]
src/test/ui/unsafe/ranged_ints2.stderr [new file with mode: 0644]

index 1e90f5a9584b22c9c2f51289d299a5daab96921d..05052c8a8c8c901e4d47a0ddaef63f68c9a0b16a 100644 (file)
@@ -187,6 +187,9 @@ fn visit_place(&mut self,
                             kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                         }], &[]);
                     }
+                    if context.is_mutating_use() {
+                        self.check_mut_borrowing_layout_constrained_field(place);
+                    }
                 }
                 let old_source_info = self.source_info;
                 if let &Place::Local(local) = base {
@@ -350,6 +353,43 @@ fn register_violations(&mut self,
             (node_id, is_used && !within_unsafe)
         }));
     }
+    fn check_mut_borrowing_layout_constrained_field(
+        &mut self,
+        mut place: &Place<'tcx>,
+    ) {
+        while let &Place::Projection(box Projection {
+            ref base, ref elem
+        }) = place {
+            match *elem {
+                ProjectionElem::Field(..) => {
+                    let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
+                    match ty.sty {
+                        ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
+                            (Bound::Unbounded, Bound::Unbounded) => {},
+                            _ => {
+                                let source_info = self.source_info;
+                                self.register_violations(&[UnsafetyViolation {
+                                    source_info,
+                                    description: Symbol::intern(
+                                        "borrow of layout constrained field",
+                                    ).as_interned_str(),
+                                    details:
+                                        Symbol::intern(
+                                            "references to fields of layout constrained fields \
+                                            lose the constraints",
+                                        ).as_interned_str(),
+                                    kind: UnsafetyViolationKind::MinConstFn,
+                                }], &[]);
+                            }
+                        },
+                        _ => {}
+                    }
+                }
+                _ => {}
+            }
+            place = base;
+        }
+    }
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/src/test/ui/unsafe/ranged_ints.rs b/src/test/ui/unsafe/ranged_ints.rs
new file mode 100644 (file)
index 0000000..c9fdade
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
+}
\ No newline at end of file
diff --git a/src/test/ui/unsafe/ranged_ints.stderr b/src/test/ui/unsafe/ranged_ints.stderr
new file mode 100644 (file)
index 0000000..c28adba
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints.rs:7:14
+   |
+LL |     let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
+   |              ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+   |
+   = note: initializing `NonZero` with a `0` violates layout constraints and is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs
new file mode 100644 (file)
index 0000000..9e1acb1
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+    let mut x = unsafe { NonZero(1) };
+    let y = &mut x.0; //~ ERROR borrow of layout constrained field is unsafe
+}
\ No newline at end of file
diff --git a/src/test/ui/unsafe/ranged_ints2.stderr b/src/test/ui/unsafe/ranged_ints2.stderr
new file mode 100644 (file)
index 0000000..77313f2
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:8:13
+   |
+LL |     let y = &mut x.0; //~ ERROR borrow of layout constrained field is unsafe
+   |             ^^^^^^^^ borrow of layout constrained field
+   |
+   = note: references to fields of layout constrained fields lose the constraints
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.