Make accesses to union fields unsafe

This commit is contained in:
Vadim Petrochenkov 2016-08-18 20:12:28 +03:00
parent f3b41c18a8
commit e88d4ca0e1
4 changed files with 63 additions and 18 deletions

View file

@ -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>) {

View file

@ -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
}

View 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);
}
}

View 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);
}
}
}
}