]> git.lizzy.rs Git - rust.git/commitdiff
Add union types
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 6 Aug 2016 22:09:00 +0000 (01:09 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 3 Sep 2016 10:37:25 +0000 (13:37 +0300)
29 files changed:
src/librustc/infer/freshen.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/select.rs
src/librustc/ty/contents.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_lint/types.rs
src/librustc_metadata/tyencode.rs
src/librustc_trans/collector.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs

index f793d489cab064866ce927a07b32a8f707bf396a..8aeb0757f5de29a3d525b902f35b873c688a7f59 100644 (file)
@@ -168,6 +168,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::TyFnPtr(_) |
             ty::TyTrait(..) |
             ty::TyStruct(..) |
+            ty::TyUnion(..) |
             ty::TyClosure(..) |
             ty::TyNever |
             ty::TyTuple(..) |
index a5a415dd27c650a1debb9ea50b0bd4e47facc89d..f856e110ea2a52bbd6e7180887a1dc49b1581231 100644 (file)
@@ -261,7 +261,8 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
         }
 
         ty::TyEnum(def, _) |
-        ty::TyStruct(def, _) => {
+        ty::TyStruct(def, _) |
+        ty::TyUnion(def, _) => {
             def.did.is_local()
         }
 
index 6d6d7c2b3ba0a830e0237e6e44a9c41d1aeeeba5..95e83d404a74cdfb02d2b2c61134b818f8d7c571 100644 (file)
@@ -166,6 +166,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::TyParam(..) => Some(14),
                 ty::TyAnon(..) => Some(15),
                 ty::TyNever => Some(16),
+                ty::TyUnion(..) => Some(17),
                 ty::TyInfer(..) | ty::TyError => None
             }
         }
index 0573f0c5bbaa0b144b49ce6ad7b2e1f0a4e090fc..f8f10d9c26541996cf63ae80a1c96cd473d14fd1 100644 (file)
@@ -1780,7 +1780,8 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(tys.last().into_iter().cloned().collect()))
             }
 
-            ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+            ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
+            ty::TyEnum(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
                 Where(ty::Binder(match sized_crit.sty {
@@ -1836,7 +1837,7 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(tys.to_vec()))
             }
 
-            ty::TyStruct(..) | ty::TyEnum(..) |
+            ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) |
             ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
@@ -1933,7 +1934,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
                 substs.types().collect()
             }
 
-            ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+            ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
                 def.all_fields()
                     .map(|f| f.ty(self.tcx(), substs))
                     .collect()
index 53bf046d6b597ed74acdb37792d5afd7c79f1492..d7d4693c1165f2e5c988022686d9ee347daad161 100644 (file)
@@ -224,7 +224,8 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         |ty| tc_ty(tcx, *ty, cache))
                 }
 
-                ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+                ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
+                ty::TyEnum(def, substs) => {
                     let mut res =
                         TypeContents::union(&def.variants, |v| {
                             TypeContents::union(&v.fields, |f| {
index 725bbf6adfd42c333d1433286a386c13d7f7ec1a..8dd7bc562d7c1f44d93d483055109dbb14e00224 100644 (file)
@@ -1032,8 +1032,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
-            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
-            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
+            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyTrait,
+            TyStruct, TyUnion, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
index 3d60d326b2b0f640f477f4436a60a6b50cf18ea0..0e33e396f7e187f7a8bfccceb58b64961d81c966 100644 (file)
@@ -247,6 +247,9 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             ty::TyStruct(def, _) => {
                 format!("struct `{}`", tcx.item_path_str(def.did))
             }
+            ty::TyUnion(def, _) => {
+                format!("union `{}`", tcx.item_path_str(def.did))
+            }
             ty::TyClosure(..) => "closure".to_string(),
             ty::TyTuple(_) => "tuple".to_string(),
             ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
index f7472d611befe30732f07bbca9ea9986732ee436..23678d1e37742e62c29d70ab0955629d176bf908 100644 (file)
@@ -66,6 +66,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyStruct(def, _) => {
             Some(StructSimplifiedType(def.did))
         }
+        ty::TyUnion(..) => {
+            unimplemented_unions!();
+        }
         ty::TyRef(_, mt) => {
             // since we introduce auto-refs during method lookup, we
             // just treat &T and T as equivalent from the point of
index 1afd49ab47fbfeb686252bb807173bac5fc2a248..ce6e4d6516ec6977601588d2cd0baa0fb8288c86 100644 (file)
@@ -102,7 +102,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 }
             }
 
-            &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => {
+            &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) | &ty::TyUnion(_, substs) => {
                 self.add_substs(substs);
             }
 
index 62bd30e2555921b029f69df921ac07254320ff24..42ec2b18fb0224377ffd8eeea1957d2619c0bb44 100644 (file)
@@ -320,6 +320,7 @@ fn parent_def_id(&self, def_id: DefId) -> Option<DefId> {
 pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
     match ty.sty {
         ty::TyStruct(adt_def, _) |
+        ty::TyUnion(adt_def, _) |
         ty::TyEnum(adt_def, _) => Some(adt_def.did),
 
         ty::TyTrait(ref data) => Some(data.principal.def_id()),
index 1ede8545e08e873a5ffa95dd9c236f097e67d8ba..622966ca5aba62af97278b13377628407f75096b 100644 (file)
@@ -896,6 +896,9 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     non_zero: Some(def.did) == tcx.lang_items.non_zero()
                 }
             }
+            ty::TyUnion(..) => {
+                unimplemented_unions!();
+            }
             ty::TyEnum(def, substs) => {
                 let hint = *tcx.lookup_repr_hints(def.did).get(0)
                     .unwrap_or(&attr::ReprAny);
index e9c01f5bad66ecab0273b09683dd971033d360c4..ddf25538ee4d07ed5b3dc20c11cc9978fca5c6f7 100644 (file)
@@ -1421,6 +1421,7 @@ pub struct TypeScheme<'tcx> {
         const IS_PHANTOM_DATA     = 1 << 3,
         const IS_SIMD             = 1 << 4,
         const IS_FUNDAMENTAL      = 1 << 5,
+        const IS_UNION            = 1 << 7,
     }
 }
 
@@ -1818,7 +1819,7 @@ fn sized_constraint_for_ty(
                 }
             }
 
-            TyEnum(adt, substs) | TyStruct(adt, substs) => {
+            TyEnum(adt, substs) | TyStruct(adt, substs) | TyUnion(adt, substs) => {
                 // recursive case
                 let adt = tcx.lookup_adt_def_master(adt.did);
                 adt.calculate_sized_constraint_inner(tcx, stack);
index 4d5b38212f600ee43c18bb29500b01c52dfa5853..a7bb0374b75bf3810f49ff514d2ed9ca095d4e8f 100644 (file)
@@ -174,6 +174,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::TyNever |           // ...
             ty::TyEnum(..) |        // OutlivesNominalType
             ty::TyStruct(..) |      // OutlivesNominalType
+            ty::TyUnion(..) |      // OutlivesNominalType
             ty::TyBox(..) |         // OutlivesNominalType (ish)
             ty::TyAnon(..) |        // OutlivesNominalType (ish)
             ty::TyStr |             // OutlivesScalar (ish)
index ad3769605abd90023b76362cc4ce16e5a504cb9c..952641f6832f90b373f9fd46966e4a0ea0a78822 100644 (file)
@@ -495,6 +495,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ty::TyRef(r.fold_with(folder), tm.fold_with(folder))
             }
             ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)),
+            ty::TyUnion(did, substs) => ty::TyUnion(did, substs.fold_with(folder)),
             ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
             ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
             ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
@@ -524,6 +525,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
             ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
+            ty::TyUnion(_did, ref substs) => substs.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
             ty::TyProjection(ref data) => data.visit_with(visitor),
             ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
index 0e3f18c4474eaed1b91788ee56b3c298eb38f7aa..b023cdad9ee2331ec5f6d2665609c2132bed6d99 100644 (file)
@@ -120,6 +120,11 @@ pub enum TypeVariants<'tcx> {
     /// See warning about substitutions for enumerated types.
     TyStruct(AdtDef<'tcx>, &'tcx Substs<'tcx>),
 
+    /// A union type, defined with `union`.
+    ///
+    /// See warning about substitutions for enumerated types.
+    TyUnion(AdtDef<'tcx>, &'tcx Substs<'tcx>),
+
     /// `Box<T>`; this is nominally a struct in the documentation, but is
     /// special-cased internally. For example, it is possible to implicitly
     /// move the contents of a box out of that box, and methods of any type
@@ -1227,6 +1232,7 @@ pub fn regions(&self) -> Vec<&'tcx ty::Region> {
             }
             TyEnum(_, substs) |
             TyStruct(_, substs) |
+            TyUnion(_, substs) |
             TyAnon(_, substs) => {
                 substs.regions().collect()
             }
index 77d16287fedc6d5296f2c0063419f29d23d77d73..971fc2cee804f94c55a29145f9cac4f4bc639b82 100644 (file)
@@ -430,6 +430,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyUint(u) => self.hash(u),
             TyFloat(f) => self.hash(f),
             TyStruct(d, _) |
+            TyUnion(d, _) |
             TyEnum(d, _) => self.def_id(d.did),
             TyArray(_, n) => self.hash(n),
             TyRawPtr(m) |
@@ -558,7 +559,7 @@ pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }) => Some(true),
 
             TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
-            TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) |
+            TyClosure(..) | TyEnum(..) | TyStruct(..) | TyUnion(..) | TyAnon(..) |
             TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
         }.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
 
@@ -598,7 +599,7 @@ fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             TyStr | TyTrait(..) | TySlice(_) => Some(false),
 
-            TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
+            TyEnum(..) | TyStruct(..) | TyUnion(..) | TyProjection(..) | TyParam(..) |
             TyInfer(..) | TyAnon(..) | TyError => None
         }.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
 
index 409f5a85997bda10eb0fff2eb5b76b28862d6a61..cea3bd6348dbe9bb5927839076dc0232ad79eb32 100644 (file)
@@ -95,6 +95,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
         }
         ty::TyEnum(_, ref substs) |
         ty::TyStruct(_, ref substs) |
+        ty::TyUnion(_, ref substs) |
         ty::TyAnon(_, ref substs) => {
             stack.extend(substs.types().rev());
         }
index aef646a7aacafdfda6ab9be099be93e046d2342f..599e2be4db247f0e4e133375749eafdfc2b79cf0 100644 (file)
@@ -337,7 +337,8 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                 }
 
                 ty::TyEnum(def, substs) |
-                ty::TyStruct(def, substs) => {
+                ty::TyStruct(def, substs) |
+                ty::TyUnion(def, substs) => {
                     // WfNominalType
                     let obligations = self.nominal_obligations(def.did, substs);
                     self.out.extend(obligations);
index 7e2cc2938ca9e4b1763c336288673c36b0181b12..d0e02f2e8acdd05cdf95baf5695609b4bc72e3fc 100644 (file)
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use hir::def_id::DefId;
 use ty::subst::{self, Subst, Substs};
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
-use ty::{TyBool, TyChar, TyStruct, TyEnum};
+use ty::{TyBool, TyChar, TyStruct, TyUnion, TyEnum};
 use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
 use ty::TyClosure;
@@ -869,7 +868,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             TyInfer(infer_ty) => write!(f, "{}", infer_ty),
             TyError => write!(f, "[type error]"),
             TyParam(ref param_ty) => write!(f, "{}", param_ty),
-            TyEnum(def, substs) | TyStruct(def, substs) => {
+            TyEnum(def, substs) | TyStruct(def, substs) | TyUnion(def, substs) => {
                 ty::tls::with(|tcx| {
                     if def.did.is_local() &&
                           !tcx.tcache.borrow().contains_key(&def.did) {
index 40e78c007ccfd652ed9d53eae876f05b10767fc4..54cec3fd7e135b04a4775d92d4eeb0294a99ef03 100644 (file)
@@ -377,7 +377,8 @@ enum FfiResult {
     FfiSafe,
     FfiUnsafe(&'static str),
     FfiBadStruct(DefId, &'static str),
-    FfiBadEnum(DefId, &'static str)
+    FfiBadUnion(DefId, &'static str),
+    FfiBadEnum(DefId, &'static str),
 }
 
 /// Check if this enum can be safely exported based on the
@@ -452,12 +453,32 @@ fn check_type_for_ffi(&self,
                     let r = self.check_type_for_ffi(cache, field_ty);
                     match r {
                         FfiSafe => {}
-                        FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+                        FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
                         FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
                     }
                 }
                 FfiSafe
             }
+            ty::TyUnion(def, substs) => {
+                if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
+                    return FfiUnsafe(
+                        "found union without foreign-function-safe \
+                         representation annotation in foreign module, \
+                         consider adding a #[repr(C)] attribute to \
+                         the type");
+                }
+
+                for field in &def.struct_variant().fields {
+                    let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
+                    let r = self.check_type_for_ffi(cache, field_ty);
+                    match r {
+                        FfiSafe => {}
+                        FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
+                        FfiUnsafe(s) => { return FfiBadUnion(def.did, s); }
+                    }
+                }
+                FfiSafe
+            }
             ty::TyEnum(def, substs) => {
                 if def.variants.is_empty() {
                     // Empty enums are okay... although sort of useless.
@@ -507,7 +528,7 @@ fn check_type_for_ffi(&self,
                         let r = self.check_type_for_ffi(cache, arg);
                         match r {
                             FfiSafe => {}
-                            FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+                            FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
                             FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
                         }
                     }
@@ -614,6 +635,13 @@ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
                     &format!("found non-foreign-function-safe member in \
                               struct marked #[repr(C)]: {}", s));
             }
+            FfiResult::FfiBadUnion(_, s) => {
+                // FIXME: This diagnostic is difficult to read, and doesn't
+                // point at the relevant field.
+                self.cx.span_lint(IMPROPER_CTYPES, sp,
+                    &format!("found non-foreign-function-safe member in \
+                              union marked #[repr(C)]: {}", s));
+            }
             FfiResult::FfiBadEnum(_, s) => {
                 // FIXME: This diagnostic is difficult to read, and doesn't
                 // point at the relevant variant.
index 954ca878c01ef7919ea945681528fbca1af3448d..b334a21c07c7a93196ebeb0d360a5ca10273362f 100644 (file)
@@ -170,6 +170,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
             enc_substs(w, cx, substs);
             write!(w, "]");
         }
+        ty::TyUnion(def, substs) => {
+            write!(w, "u[{}|", (cx.ds)(cx.tcx, def.did));
+            enc_substs(w, cx, substs);
+            write!(w, "]");
+        }
         ty::TyClosure(def, substs) => {
             write!(w, "k[{}|", (cx.ds)(cx.tcx, def));
             enc_substs(w, cx, substs.func_substs);
index bea6f30faec306978fb45e578441613a62ab03d0..47b3bb36cb9302bdc1fc2add1ed3c189df4e4624 100644 (file)
@@ -798,6 +798,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
             /* nothing to do */
         }
         ty::TyStruct(ref adt_def, substs) |
+        ty::TyUnion(ref adt_def, substs) |
         ty::TyEnum(ref adt_def, substs) => {
             for field in adt_def.all_fields() {
                 let field_type = monomorphize::apply_param_substs(scx,
index f757578e6954def808863c0a174668972d89c17b..bd839243e201f73a277aa3544d13cb3cc8aa366a 100644 (file)
@@ -45,6 +45,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
         ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
         ty::TyStruct(def, substs) |
+        ty::TyUnion(def, substs) |
         ty::TyEnum(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
             push_type_params(cx, substs, output);
index 8a0f37230c8dfa21730fda3bd4e725c7cf7a7169..deef0b09a17b032dfa1b63b06c5e11418310afec 100644 (file)
@@ -397,6 +397,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
         ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
         ty::TyStruct(adt_def, substs) |
+        ty::TyUnion(adt_def, substs) |
         ty::TyEnum(adt_def, substs) => {
             push_item_name(tcx, adt_def.did, output);
             push_type_params(tcx, substs, &[], output);
index 6605d12e2e127b3c27f497015bae54e4c0944598..d5d8f049681dadc27bd533bb5299b664621ce8e6 100644 (file)
@@ -89,27 +89,23 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             Type::nil(cx)
         }
 
-        ty::TyTuple(..) | ty::TyEnum(..) | ty::TyClosure(..) => {
-            let repr = adt::represent_type(cx, t);
-            adt::sizing_type_of(cx, &repr, false)
+        ty::TyStruct(..) if t.is_simd() => {
+            let e = t.simd_type(cx.tcx());
+            if !e.is_machine() {
+                cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
+                                          a non-machine element type `{}`",
+                                         t, e))
+            }
+            let llet = type_of(cx, e);
+            let n = t.simd_size(cx.tcx()) as u64;
+            ensure_array_fits_in_address_space(cx, llet, n, t);
+            Type::vector(&llet, n)
         }
 
-        ty::TyStruct(..) => {
-            if t.is_simd() {
-                let e = t.simd_type(cx.tcx());
-                if !e.is_machine() {
-                    cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
-                                              a non-machine element type `{}`",
-                                             t, e))
-                }
-                let llet = type_of(cx, e);
-                let n = t.simd_size(cx.tcx()) as u64;
-                ensure_array_fits_in_address_space(cx, llet, n, t);
-                Type::vector(&llet, n)
-            } else {
-                let repr = adt::represent_type(cx, t);
-                adt::sizing_type_of(cx, &repr, false)
-            }
+        ty::TyTuple(..) | ty::TyStruct(..) | ty::TyUnion(..) |
+        ty::TyEnum(..) | ty::TyClosure(..) => {
+            let repr = adt::represent_type(cx, t);
+            adt::sizing_type_of(cx, &repr, false)
         }
 
         ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
@@ -244,15 +240,6 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
       ty::TyUint(t) => Type::uint_from_ty(cx, t),
       ty::TyFloat(t) => Type::float_from_ty(cx, t),
       ty::TyNever => Type::nil(cx),
-      ty::TyEnum(def, ref substs) => {
-          // Only create the named struct, but don't fill it in. We
-          // fill it in *after* placing it into the type cache. This
-          // avoids creating more than one copy of the enum when one
-          // of the enum's variants refers to the enum itself.
-          let repr = adt::represent_type(cx, t);
-          let name = llvm_type_name(cx, def.did, substs);
-          adt::incomplete_type_of(cx, &repr, &name[..])
-      }
       ty::TyClosure(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache.
@@ -307,26 +294,28 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           let repr = adt::represent_type(cx, t);
           adt::type_of(cx, &repr)
       }
-      ty::TyStruct(def, ref substs) => {
-          if t.is_simd() {
-              let e = t.simd_type(cx.tcx());
-              if !e.is_machine() {
-                  cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
-                                            a non-machine element type `{}`",
-                                           t, e))
-              }
-              let llet = in_memory_type_of(cx, e);
-              let n = t.simd_size(cx.tcx()) as u64;
-              ensure_array_fits_in_address_space(cx, llet, n, t);
-              Type::vector(&llet, n)
-          } else {
-              // Only create the named struct, but don't fill it in. We fill it
-              // in *after* placing it into the type cache. This prevents
-              // infinite recursion with recursive struct types.
-              let repr = adt::represent_type(cx, t);
-              let name = llvm_type_name(cx, def.did, substs);
-              adt::incomplete_type_of(cx, &repr, &name[..])
+      ty::TyStruct(..) if t.is_simd() => {
+          let e = t.simd_type(cx.tcx());
+          if !e.is_machine() {
+              cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
+                                        a non-machine element type `{}`",
+                                       t, e))
           }
+          let llet = in_memory_type_of(cx, e);
+          let n = t.simd_size(cx.tcx()) as u64;
+          ensure_array_fits_in_address_space(cx, llet, n, t);
+          Type::vector(&llet, n)
+      }
+      ty::TyStruct(def, ref substs) |
+      ty::TyUnion(def, ref substs) |
+      ty::TyEnum(def, ref substs) => {
+          // Only create the named struct, but don't fill it in. We
+          // fill it in *after* placing it into the type cache. This
+          // avoids creating more than one copy of the enum when one
+          // of the enum's variants refers to the enum itself.
+          let repr = adt::represent_type(cx, t);
+          let name = llvm_type_name(cx, def.did, substs);
+          adt::incomplete_type_of(cx, &repr, &name[..])
       }
 
       ty::TyInfer(..) |
index 3a6076774330dcd26fad834b0fd871d402493478..b73b8b9988766b7fb46575bdb3f0e93ac0ecba71 100644 (file)
@@ -439,7 +439,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
                 cx, context, ity, depth+1)
         }
 
-        ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+        ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
             let did = def.did;
             for variant in &def.variants {
                 for field in variant.fields.iter() {
index f743ef21875611434fb9de7de52911f2f8bf2d49..a20195bd801d932bcc8a8f413e19639c88fa32e8 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
 use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
 use rustc::ty::{TyParam, TyRawPtr};
-use rustc::ty::{TyRef, TyStruct, TyTrait, TyNever, TyTuple};
+use rustc::ty::{TyRef, TyStruct, TyUnion, TyTrait, TyNever, TyTuple};
 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
 use rustc::ty::{TyProjection, TyAnon};
@@ -70,7 +70,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
     fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
         match ty.sty {
             TyEnum(def, _) |
-            TyStruct(def, _) => {
+            TyStruct(def, _) |
+            TyUnion(def, _) => {
                 Some(def.did)
             }
 
index 888709d257246567ecb8d8c8c3ccd0a3f30af8b4..e20e74be67cd39a3e7489349d0d9a25c0fd5ef4f 100644 (file)
@@ -344,7 +344,8 @@ fn add_constraints_from_ty(&mut self,
             }
 
             ty::TyEnum(def, substs) |
-            ty::TyStruct(def, substs) => {
+            ty::TyStruct(def, substs) |
+            ty::TyUnion(def, substs) => {
                 let item_type = self.tcx().lookup_item_type(def.did);
 
                 // This edge is actually implied by the call to
index e4b6a30d5bcb3b35c3f55954ee9cb09545b561e5..92bb265ca995ae3b7cca9f4fda3624cecbc27983 100644 (file)
@@ -1801,6 +1801,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                 decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
                 abi: fty.abi,
             }),
+            ty::TyUnion(..) => unimplemented_unions!(),
             ty::TyStruct(def, substs) |
             ty::TyEnum(def, substs) => {
                 let did = def.did;