Skip to content

Commit e88d4ca

Browse files
committed
Make accesses to union fields unsafe
1 parent f3b41c1 commit e88d4ca

File tree

4 files changed

+63
-18
lines changed

4 files changed

+63
-18
lines changed

src/librustc/middle/effect.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@
1313
use self::RootUnsafeContext::*;
1414

1515
use dep_graph::DepNode;
16-
use hir::def::Def;
1716
use ty::{self, Ty, TyCtxt};
1817
use ty::MethodCall;
1918

2019
use syntax::ast;
2120
use syntax_pos::Span;
22-
use hir;
23-
use hir::intravisit;
24-
use hir::intravisit::{FnKind, Visitor};
21+
use hir::{self, PatKind};
22+
use hir::def::Def;
23+
use hir::intravisit::{self, FnKind, Visitor};
2524

2625
#[derive(Copy, Clone)]
2726
struct UnsafeContext {
@@ -178,11 +177,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
178177
self.require_unsafe(expr.span, "use of mutable static");
179178
}
180179
}
180+
hir::ExprField(ref base_expr, field) => {
181+
if let ty::TyUnion(..) = self.tcx.expr_ty_adjusted(base_expr).sty {
182+
self.require_unsafe(field.span, "access to union field");
183+
}
184+
}
181185
_ => {}
182186
}
183187

184188
intravisit::walk_expr(self, expr);
185189
}
190+
191+
fn visit_pat(&mut self, pat: &hir::Pat) {
192+
if let PatKind::Struct(_, ref fields, _) = pat.node {
193+
if let ty::TyUnion(..) = self.tcx.pat_ty(pat).sty {
194+
for field in fields {
195+
self.require_unsafe(field.span, "matching on union field");
196+
}
197+
}
198+
}
199+
200+
intravisit::walk_pat(self, pat);
201+
}
186202
}
187203

188204
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {

src/test/compile-fail/union-unsafe.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 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+
#![feature(untagged_unions)]
12+
13+
union U {
14+
a: u8
15+
}
16+
17+
fn main() {
18+
let u = U { a: 10 }; // OK
19+
let a = u.a; //~ ERROR access to union field requires unsafe function or block
20+
let U { a } = u; //~ ERROR matching on union field requires unsafe function or block
21+
if let U { a: 11 } = u {} //~ ERROR matching on union field requires unsafe function or block
22+
let U { .. } = u; // OK
23+
}

src/test/run-pass/union-basic.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ fn main() {
4242
assert_eq!(align_of::<Y>(), 2);
4343

4444
let u = U { a: 10 };
45-
assert_eq!(u.a, 10);
46-
let U { a } = u;
47-
assert_eq!(a, 10);
45+
unsafe {
46+
assert_eq!(u.a, 10);
47+
let U { a } = u;
48+
assert_eq!(a, 10);
49+
}
4850

4951
let mut w: W = unsafe { zeroed() };
50-
assert_eq!(w.a, 0);
51-
assert_eq!(w.b, 0);
52-
// w.a = 1;
53-
// assert_eq!(w.a, 0);
54-
// assert_eq!(w.b, 0);
52+
unsafe {
53+
assert_eq!(w.a, 0);
54+
assert_eq!(w.b, 0);
55+
// w.a = 1;
56+
// assert_eq!(w.a, 0);
57+
// assert_eq!(w.b, 0);
58+
}
5559
}

src/test/run-pass/union-pat-refutability.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ union W {
4141
}
4242

4343
fn refut(w: W) {
44-
match w {
45-
W { a: 10 } => {
46-
panic!();
47-
}
48-
W { b } => {
49-
assert_eq!(b, 11);
44+
unsafe {
45+
match w {
46+
W { a: 10 } => {
47+
panic!();
48+
}
49+
W { b } => {
50+
assert_eq!(b, 11);
51+
}
5052
}
5153
}
5254
}

0 commit comments

Comments
 (0)