]> git.lizzy.rs Git - rust.git/commitdiff
Make accesses to union fields unsafe
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 18 Aug 2016 17:12:28 +0000 (20:12 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 3 Sep 2016 10:39:34 +0000 (13:39 +0300)
src/librustc/middle/effect.rs
src/test/compile-fail/union-unsafe.rs [new file with mode: 0644]
src/test/run-pass/union-basic.rs
src/test/run-pass/union-pat-refutability.rs

index 250ad80f5af6c98b738cf28c3aa0f3da7c6562c9..e52eba68da19871f7f77da88ea6fb266485ce86c 100644 (file)
 use self::RootUnsafeContext::*;
 
 use dep_graph::DepNode;
-use hir::def::Def;
 use ty::{self, Ty, TyCtxt};
 use ty::MethodCall;
 
 use syntax::ast;
 use syntax_pos::Span;
-use hir;
-use hir::intravisit;
-use hir::intravisit::{FnKind, Visitor};
+use hir::{self, PatKind};
+use hir::def::Def;
+use hir::intravisit::{self, FnKind, Visitor};
 
 #[derive(Copy, Clone)]
 struct UnsafeContext {
@@ -178,11 +177,28 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
             }
+            hir::ExprField(ref base_expr, field) => {
+                if let ty::TyUnion(..) = self.tcx.expr_ty_adjusted(base_expr).sty {
+                    self.require_unsafe(field.span, "access to union field");
+                }
+            }
             _ => {}
         }
 
         intravisit::walk_expr(self, expr);
     }
+
+    fn visit_pat(&mut self, pat: &hir::Pat) {
+        if let PatKind::Struct(_, ref fields, _) = pat.node {
+            if let ty::TyUnion(..) = self.tcx.pat_ty(pat).sty {
+                for field in fields {
+                    self.require_unsafe(field.span, "matching on union field");
+                }
+            }
+        }
+
+        intravisit::walk_pat(self, pat);
+    }
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
diff --git a/src/test/compile-fail/union-unsafe.rs b/src/test/compile-fail/union-unsafe.rs
new file mode 100644 (file)
index 0000000..762ac5d
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+#![feature(untagged_unions)]
+
+union U {
+    a: u8
+}
+
+fn main() {
+    let u = U { a: 10 }; // OK
+    let a = u.a; //~ ERROR access to union field requires unsafe function or block
+    let U { a } = u; //~ ERROR matching on union field requires unsafe function or block
+    if let U { a: 11 } = u {} //~ ERROR matching on union field requires unsafe function or block
+    let U { .. } = u; // OK
+}
index dee86b232b4857d6cd1da7434117992d4b3b8c30..afbfe5bf92be792a09145fe440a7ca17c127beef 100644 (file)
@@ -42,14 +42,18 @@ fn main() {
     assert_eq!(align_of::<Y>(), 2);
 
     let u = U { a: 10 };
-    assert_eq!(u.a, 10);
-    let U { a } = u;
-    assert_eq!(a, 10);
+    unsafe {
+        assert_eq!(u.a, 10);
+        let U { a } = u;
+        assert_eq!(a, 10);
+    }
 
     let mut w: W = unsafe { zeroed() };
-    assert_eq!(w.a, 0);
-    assert_eq!(w.b, 0);
-    // w.a = 1;
-    // assert_eq!(w.a, 0);
-    // assert_eq!(w.b, 0);
+    unsafe {
+        assert_eq!(w.a, 0);
+        assert_eq!(w.b, 0);
+        // w.a = 1;
+        // assert_eq!(w.a, 0);
+        // assert_eq!(w.b, 0);
+    }
 }
index 6b39eed7ac942c3a580ef87e22f8db9fb4288e64..a57c1103a9b4ad7ac2dfdea2054817641c2da6ff 100644 (file)
@@ -41,12 +41,14 @@ union W {
 }
 
 fn refut(w: W) {
-    match w {
-        W { a: 10 } => {
-            panic!();
-        }
-        W { b } => {
-            assert_eq!(b, 11);
+    unsafe {
+        match w {
+            W { a: 10 } => {
+                panic!();
+            }
+            W { b } => {
+                assert_eq!(b, 11);
+            }
         }
     }
 }