about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2015-08-15 21:03:10 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2015-08-15 21:03:10 +0300
commit91be1258993b592531e8e66181f26ad23ab5b2f4 (patch)
tree5ae529f6afc901c5b4d07b3d7ef5082aea8666bc
parentba98228b4d4c2676edd074e39029952d8e841502 (diff)
downloadrust-91be1258993b592531e8e66181f26ad23ab5b2f4.tar.gz
rust-91be1258993b592531e8e66181f26ad23ab5b2f4.zip
prevent non-dict-structs from being intialized via FRU
Fixes #27831
-rw-r--r--src/librustc_typeck/check/mod.rs17
-rw-r--r--src/test/compile-fail/issue-27831.rs34
-rw-r--r--src/test/compile-fail/issue-4736.rs2
3 files changed, 47 insertions, 6 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index facd60de6c2..74df7d8e58a 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1415,24 +1415,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Return the dict-like variant corresponding to a given `Def`.
     pub fn def_struct_variant(&self,
                               def: def::Def)
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
-        match def {
+        let (adt, variant) = match def {
             def::DefVariant(enum_id, variant_id, true) => {
                 let adt = self.tcx().lookup_adt_def(enum_id);
-                Some((adt, adt.variant_with_id(variant_id)))
+                (adt, adt.variant_with_id(variant_id))
             }
             def::DefTy(did, _) | def::DefStruct(did) => {
                 let typ = self.tcx().lookup_item_type(did);
                 if let ty::TyStruct(adt, _) = typ.ty.sty {
-                    Some((adt, adt.struct_variant()))
+                    (adt, adt.struct_variant())
                 } else {
-                    None
+                    return None;
                 }
             }
-            _ => None
+            _ => return None
+        };
+
+        if let ty::VariantKind::Dict = variant.kind() {
+            Some((adt, variant))
+        } else {
+            None
         }
     }
 
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
new file mode 100644
index 00000000000..336368cf8a4
--- /dev/null
+++ b/src/test/compile-fail/issue-27831.rs
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+struct Foo(u32);
+struct Bar;
+
+enum Enum {
+    Foo(u32),
+    Bar
+}
+
+fn main() {
+    let x = Foo(1);
+    Foo { ..x }; //~ ERROR `Foo` does not name a structure
+    let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
+
+    let x = Bar;
+    Bar { ..x }; //~ ERROR `Bar` does not name a structure
+    let Bar { .. } = x; //~ ERROR `Bar` does not name a struct
+
+    match Enum::Bar {
+        Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
+           => {}
+        Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
+           => {}
+    }
+}
diff --git a/src/test/compile-fail/issue-4736.rs b/src/test/compile-fail/issue-4736.rs
index b63db7c5a30..843ff38df49 100644
--- a/src/test/compile-fail/issue-4736.rs
+++ b/src/test/compile-fail/issue-4736.rs
@@ -11,5 +11,5 @@
 struct NonCopyable(());
 
 fn main() {
-    let z = NonCopyable{ p: () }; //~ ERROR structure `NonCopyable` has no field named `p`
+    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a structure
 }