diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 250ad80f5af6..e52eba68da19 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -13,15 +13,14 @@ 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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { 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 index 000000000000..762ac5d87513 --- /dev/null +++ b/src/test/compile-fail/union-unsafe.rs @@ -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 or the MIT license +// , 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 +} diff --git a/src/test/run-pass/union-basic.rs b/src/test/run-pass/union-basic.rs index dee86b232b48..afbfe5bf92be 100644 --- a/src/test/run-pass/union-basic.rs +++ b/src/test/run-pass/union-basic.rs @@ -42,14 +42,18 @@ fn main() { assert_eq!(align_of::(), 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); + } } diff --git a/src/test/run-pass/union-pat-refutability.rs b/src/test/run-pass/union-pat-refutability.rs index 6b39eed7ac94..a57c1103a9b4 100644 --- a/src/test/run-pass/union-pat-refutability.rs +++ b/src/test/run-pass/union-pat-refutability.rs @@ -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); + } } } }