about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2017-07-22 01:17:53 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2017-08-05 22:02:45 +0200
commit46fe8e99665d6a210f6dc16590127ee808e60366 (patch)
treec9f3cf5951f079c650db79f43bce0c5b7df79d9b
parent5a5a32a4a82027b3f4112919fa307dbae744069b (diff)
downloadrust-46fe8e99665d6a210f6dc16590127ee808e60366.tar.gz
rust-46fe8e99665d6a210f6dc16590127ee808e60366.zip
Don't warn on unused field on union
-rw-r--r--src/librustc/middle/dead.rs18
-rw-r--r--src/test/ui/union-fields.rs29
-rw-r--r--src/test/ui/union-fields.stderr14
3 files changed, 58 insertions, 3 deletions
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 2238e464cbc..91d25c680d8 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -13,7 +13,7 @@
 // from live codes are live, and everything else is dead.
 
 use hir::map as hir_map;
-use hir::{self, PatKind};
+use hir::{self, Item_, PatKind};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 
@@ -558,8 +558,20 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
 
     fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
         if self.should_warn_about_field(&field) {
-            self.warn_dead_code(field.id, field.span,
-                                field.name, "field");
+            let did = self.tcx.hir.get_parent_did(field.id);
+            if if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
+                match self.tcx.hir.find(node_id) {
+                    Some(hir_map::NodeItem(item)) => match item.node {
+                        Item_::ItemUnion(_, _) => false,
+                        _ => true,
+                    },
+                    _ => true,
+                }
+            } else {
+                true
+            } {
+                self.warn_dead_code(field.id, field.span, field.name, "field");
+            }
         }
 
         intravisit::walk_struct_field(self, field);
diff --git a/src/test/ui/union-fields.rs b/src/test/ui/union-fields.rs
new file mode 100644
index 00000000000..87a61730133
--- /dev/null
+++ b/src/test/ui/union-fields.rs
@@ -0,0 +1,29 @@
+// Copyright 2017 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.
+
+#![deny(dead_code)]
+
+union U {
+    x: u32,
+    y: f32,
+}
+
+struct V {
+    x: u32,
+    y: u32,
+}
+
+fn main() {
+    let u = U { x: 0x3f800000 };
+    let _f = unsafe { u.y };
+    let v = V { x: 0, y: 0 };
+    println!("{}", v.x);
+}
+
diff --git a/src/test/ui/union-fields.stderr b/src/test/ui/union-fields.stderr
new file mode 100644
index 00000000000..d0f1a921425
--- /dev/null
+++ b/src/test/ui/union-fields.stderr
@@ -0,0 +1,14 @@
+error: field is never used: `y`
+  --> $DIR/union-fields.rs:20:5
+   |
+20 |     y: u32,
+   |     ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/union-fields.rs:11:9
+   |
+11 | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+