diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-08-10 21:00:17 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-09-03 13:39:34 +0300 |
| commit | 641d8e9e4c12b3753cf4e2a9ac901ad08ea90e00 (patch) | |
| tree | d58d261fd624fd9248657aad6c7757854752ef5f /src | |
| parent | a014323e456c00f93134d03b4af95844b2ed4b95 (diff) | |
| download | rust-641d8e9e4c12b3753cf4e2a9ac901ad08ea90e00.tar.gz rust-641d8e9e4c12b3753cf4e2a9ac901ad08ea90e00.zip | |
Some better support for unions through the compiler
Diffstat (limited to 'src')
51 files changed, 243 insertions, 134 deletions
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 53624702c84..a2d4239388a 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -18,6 +18,7 @@ use syntax::visit::Visitor; enum Target { Fn, Struct, + Union, Enum, Other, } @@ -27,6 +28,7 @@ impl Target { match item.node { ast::ItemKind::Fn(..) => Target::Fn, ast::ItemKind::Struct(..) => Target::Struct, + ast::ItemKind::Union(..) => Target::Union, ast::ItemKind::Enum(..) => Target::Enum, _ => Target::Other, } @@ -62,8 +64,10 @@ impl<'a> CheckAttrVisitor<'a> { let message = match &*name { "C" => { conflicting_reprs += 1; - if target != Target::Struct && target != Target::Enum { - "attribute should be applied to struct or enum" + if target != Target::Struct && + target != Target::Union && + target != Target::Enum { + "attribute should be applied to struct, enum or union" } else { continue } @@ -71,8 +75,9 @@ impl<'a> CheckAttrVisitor<'a> { "packed" => { // Do not increment conflicting_reprs here, because "packed" // can be used to modify another repr hint - if target != Target::Struct { - "attribute should be applied to struct" + if target != Target::Struct && + target != Target::Union { + "attribute should be applied to struct or union" } else { continue } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 389d0a1d50d..29fb19fd421 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -331,7 +331,8 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { }); } } - hir::ItemStruct(ref struct_def, _) => { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { // If this is a tuple-like struct, register the constructor. if !struct_def.is_struct() { this.create_def(struct_def.id(), diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 0cd39882b7c..efce0c8354b 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -105,6 +105,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match item.node { hir::ItemImpl(..) => "impl", hir::ItemStruct(..) => "struct", + hir::ItemUnion(..) => "union", hir::ItemEnum(..) => "enum", hir::ItemTrait(..) => "trait", hir::ItemFn(..) => "function body", @@ -1370,7 +1371,8 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { } hir::TyPath(ref maybe_qself, ref path) => { match self.tcx.expect_def(cur_ty.id) { - Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { + Def::Enum(did) | Def::TyAlias(did) | + Def::Struct(did) | Def::Union(did) => { let generics = self.tcx.lookup_generics(did); let expected = diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 824383b11af..9a63ad4b985 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn lookup_and_handle_definition(&mut self, id: ast::NodeId) { - use ty::TypeVariants::{TyEnum, TyStruct}; + use ty::TypeVariants::{TyEnum, TyStruct, TyUnion}; let def = self.tcx.expect_def(id); @@ -96,7 +96,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { if self.tcx.trait_of_item(def.def_id()).is_some() => { if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { match substs.substs.type_at(0).sty { - TyEnum(tyid, _) | TyStruct(tyid, _) => { + TyEnum(tyid, _) | TyStruct(tyid, _) | TyUnion(tyid, _) => { self.check_def_id(tyid.did) } _ => {} @@ -132,10 +132,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty { - self.insert_def_id(def.struct_variant().field_named(name).did); - } else { - span_bug!(lhs.span, "named field access on non-struct") + match self.tcx.expr_ty_adjusted(lhs).sty { + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { + self.insert_def_id(def.struct_variant().field_named(name).did); + } + _ => span_bug!(lhs.span, "named field access on non-struct"), } } @@ -148,7 +149,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, pats: &[codemap::Spanned<hir::FieldPat>]) { let variant = match self.tcx.node_id_to_type(lhs.id).sty { - ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => { + ty::TyStruct(adt, _) | ty::TyUnion(adt, _) | ty::TyEnum(adt, _) => { adt.variant_of_def(self.tcx.expect_def(lhs.id)) } _ => span_bug!(lhs.span, "non-ADT in struct pattern") @@ -185,7 +186,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { match *node { ast_map::NodeItem(item) => { match item.node { - hir::ItemStruct(..) => { + hir::ItemStruct(..) | hir::ItemUnion(..) => { self.struct_has_extern_repr = item.attrs.iter().any(|attr| { attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr) .contains(&attr::ReprExtern) @@ -423,7 +424,8 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { | hir::ItemConst(..) | hir::ItemFn(..) | hir::ItemEnum(..) - | hir::ItemStruct(..) => true, + | hir::ItemStruct(..) + | hir::ItemUnion(..) => true, _ => false }; let ctor_id = get_struct_ctor_id(item); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 798702e6fd6..7214049f6cd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -672,30 +672,36 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - if let ty::TyStruct(def, substs) = with_cmt.ty.sty { - // Consume those fields of the with expression that are needed. - for with_field in &def.struct_variant().fields { - if !contains_field_named(with_field, fields) { - let cmt_field = self.mc.cat_field( - &*with_expr, - with_cmt.clone(), - with_field.name, - with_field.ty(self.tcx(), substs) - ); - self.delegate_consume(with_expr.id, with_expr.span, cmt_field); + match with_cmt.ty.sty { + ty::TyStruct(def, substs) => { + // Consume those fields of the with expression that are needed. + for with_field in &def.struct_variant().fields { + if !contains_field_named(with_field, fields) { + let cmt_field = self.mc.cat_field( + &*with_expr, + with_cmt.clone(), + with_field.name, + with_field.ty(self.tcx(), substs) + ); + self.delegate_consume(with_expr.id, with_expr.span, cmt_field); + } } } - } else { - // the base expression should always evaluate to a - // struct; however, when EUV is run during typeck, it - // may not. This will generate an error earlier in typeck, - // so we can just ignore it. - if !self.tcx().sess.has_errors() { - span_bug!( - with_expr.span, - "with expression doesn't evaluate to a struct"); + ty::TyUnion(..) => { + unimplemented_unions!(); } - }; + _ => { + // the base expression should always evaluate to a + // struct; however, when EUV is run during typeck, it + // may not. This will generate an error earlier in typeck, + // so we can just ignore it. + if !self.tcx().sess.has_errors() { + span_bug!( + with_expr.span, + "with expression doesn't evaluate to a struct"); + } + } + } // walk the with expression so that complex expressions // are properly handled. @@ -1012,7 +1018,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); delegate.matched_pat(pat, downcast_cmt, match_mode); } - Some(Def::Struct(..)) | Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => { + Some(Def::Struct(..)) | Some(Def::Union(..)) | + Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => { debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); delegate.matched_pat(pat, cmt_pat, match_mode); } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c20fcc3fe1d..e6979c25453 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -561,7 +561,9 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, hir::ExprField(ref base_e, ref field) => { span = field.span; match tcx.expr_ty_adjusted(base_e).sty { - ty::TyStruct(def, _) => def.struct_variant().field_named(field.node).did, + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { + def.struct_variant().field_named(field.node).did + } _ => span_bug!(e.span, "stability::check_expr: named field access on non-struct") } @@ -579,7 +581,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, hir::ExprStruct(_, ref expr_fields, _) => { let type_ = tcx.expr_ty(e); match type_.sty { - ty::TyStruct(def, _) => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { // check the stability of each field that appears // in the construction expression. for field in expr_fields { @@ -647,7 +649,8 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat, if is_internal(tcx, pat.span) { return; } let v = match tcx.pat_ty_opt(pat) { - Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) => def.struct_variant(), + Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) | + Some(&ty::TyS { sty: ty::TyUnion(def, _), .. }) => def.struct_variant(), Some(_) | None => return, }; match pat.node { diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index f856e110ea2..0a7d3e6e76d 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -224,7 +224,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { match ty.sty { ty::TyBox(..) | ty::TyRef(..) => true, - ty::TyEnum(def, _) | ty::TyStruct(def, _) => + ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) => def.is_fundamental(), ty::TyTrait(ref data) => tcx.has_attr(data.principal.def_id(), "fundamental"), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 95e83d404a7..e5ebe96932d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -174,6 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (type_category(a), type_category(b)) { (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { (&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) | + (&ty::TyUnion(def_a, _), &ty::TyUnion(def_b, _)) | (&ty::TyEnum(def_a, _), &ty::TyEnum(def_b, _)) => def_a == def_b, _ => cat_a == cat_b diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 42ec2b18fb0..ba8d3328509 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -263,6 +263,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // anything other than a simple path. match self_ty.sty { ty::TyStruct(adt_def, substs) | + ty::TyUnion(adt_def, substs) | ty::TyEnum(adt_def, substs) => { if substs.types().next().is_none() { // ignore regions self.push_item_path(buffer, adt_def.did); diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 622966ca5ab..ac5e3c6fa70 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1256,6 +1256,9 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> { } } + ty::TyUnion(..) => { + unimplemented_unions!(); + } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { // Only newtypes and enums w/ nullable pointer optimization. if def.variants.is_empty() || def.variants.len() > 2 { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4cda7491113..ee2188e8e11 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -948,6 +948,7 @@ impl<'tcx> TraitPredicate<'tcx> { .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { ty::TyStruct(adt_def, _) | + ty::TyUnion(adt_def, _) | ty::TyEnum(adt_def, _) => Some(adt_def.did), _ => @@ -1341,6 +1342,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } hir::ItemEnum(..) | hir::ItemStruct(..) | + hir::ItemUnion(..) | hir::ItemTy(..) | hir::ItemImpl(..) | hir::ItemConst(..) | @@ -1615,7 +1617,8 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> { /// Asserts this is a struct and returns the struct's unique /// variant. pub fn struct_variant(&self) -> &VariantDefData<'gcx, 'container> { - assert_eq!(self.adt_kind(), AdtKind::Struct); + let adt_kind = self.adt_kind(); + assert!(adt_kind == AdtKind::Struct || adt_kind == AdtKind::Union); &self.variants[0] } @@ -1674,7 +1677,8 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> { pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> { match def { Def::Variant(_, vid) => self.variant_with_id(vid), - Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(), + Def::Struct(..) | Def::Union(..) | + Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) } } @@ -2413,7 +2417,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Def::Variant(enum_did, did) => { self.lookup_adt_def(enum_did).variant_with_id(did) } - Def::Struct(did) => { + Def::Struct(did) | Def::Union(did) => { self.lookup_adt_def(did).struct_variant() } _ => bug!("expect_variant_def used with unexpected def {:?}", def) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 5c157ff32e7..dfae19487b6 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -447,6 +447,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_struct(a_def, substs)) } + (&ty::TyUnion(a_def, a_substs), &ty::TyUnion(b_def, b_substs)) + if a_def == b_def => + { + let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?; + Ok(tcx.mk_union(a_def, substs)) + } + (&ty::TyClosure(a_id, a_substs), &ty::TyClosure(b_id, b_substs)) if a_id == b_id => diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index b023cdad9ee..165f86fbef5 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -922,7 +922,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { // FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made // more complete. match self.sty { - TyEnum(def, _) | TyStruct(def, _) => def.is_empty(), + TyEnum(def, _) | TyStruct(def, _) | TyUnion(def, _) => def.is_empty(), // FIXME(canndrew): There's no reason why these can't be uncommented, they're tested // and they don't break anything. But I'm keeping my changes small for now. @@ -985,7 +985,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_structural(&self) -> bool { match self.sty { - TyStruct(..) | TyTuple(_) | TyEnum(..) | + TyStruct(..) | TyUnion(..) | TyTuple(..) | TyEnum(..) | TyArray(..) | TyClosure(..) => true, _ => self.is_slice() | self.is_trait() } @@ -1204,6 +1204,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { match self.sty { TyTrait(ref tt) => Some(tt.principal.def_id()), TyStruct(def, _) | + TyUnion(def, _) | TyEnum(def, _) => Some(def.did), TyClosure(id, _) => Some(id), _ => None @@ -1212,7 +1213,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> { match self.sty { - TyStruct(adt, _) | TyEnum(adt, _) => Some(adt), + TyStruct(adt, _) | TyUnion(adt, _) | TyEnum(adt, _) => Some(adt), _ => None } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 971fc2cee80..ad209094600 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -138,7 +138,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { // FIXME: (@jroesch) float this code up tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| { let adt = match self_type.sty { - ty::TyStruct(struct_def, substs) => { + ty::TyStruct(struct_def, substs) | ty::TyUnion(struct_def, substs) => { for field in struct_def.all_fields() { let field_ty = field.ty(tcx, substs); if infcx.type_moves_by_default(field_ty, span) { @@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { + ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => { for field in def.all_fields() { let field_ty = field.ty(self, substs); if let TyError = field_ty.sty { @@ -203,7 +203,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { i: usize, variant: Option<DefId>) -> Option<Ty<'tcx>> { match (&ty.sty, variant) { - (&TyStruct(def, substs), None) => { + (&TyStruct(def, substs), None) | + (&TyUnion(def, substs), None) => { def.struct_variant().fields.get(i).map(|f| f.ty(self, substs)) } (&TyEnum(def, substs), Some(vid)) => { @@ -225,7 +226,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { n: Name, variant: Option<DefId>) -> Option<Ty<'tcx>> { match (&ty.sty, variant) { - (&TyStruct(def, substs), None) => { + (&TyStruct(def, substs), None) | + (&TyUnion(def, substs), None) => { def.struct_variant().find_field_named(n).map(|f| f.ty(self, substs)) } (&TyEnum(def, substs), Some(vid)) => { @@ -661,7 +663,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyArray(ty, _) => { is_type_structurally_recursive(tcx, sp, seen, ty) } - TyStruct(def, substs) | TyEnum(def, substs) => { + TyStruct(def, substs) | TyUnion(def, substs) | TyEnum(def, substs) => { find_nonrepresentable(tcx, sp, seen, @@ -678,7 +680,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool { match ty.sty { - TyStruct(ty_def, _) | TyEnum(ty_def, _) => { + TyStruct(ty_def, _) | TyUnion(ty_def, _) | TyEnum(ty_def, _) => { ty_def == def } _ => false @@ -688,6 +690,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match (&a.sty, &b.sty) { (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) | + (&TyUnion(did_a, ref substs_a), &TyUnion(did_b, ref substs_b)) | (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => { if did_a != did_b { return false; @@ -710,7 +713,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { debug!("is_type_structurally_recursive: {:?}", ty); match ty.sty { - TyStruct(def, _) | TyEnum(def, _) => { + TyStruct(def, _) | TyUnion(def, _) | TyEnum(def, _) => { { // Iterate through stack of previously seen types. let mut iter = seen.iter(); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index e86fa9a05f3..b4c6689c24b 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -796,7 +796,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => { match lp_base.to_type().sty { - ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { + ty::TyStruct(def, _) | + ty::TyUnion(def, _) | + ty::TyEnum(def, _) if def.has_dtor() => { // In the case where the owner implements drop, then // the path must be initialized to prevent a case of // partial reinitialization diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 9431dcdbcac..3cf02fc85a4 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -178,7 +178,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Interior(ref b, mc::InteriorField(_)) | Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => { match b.ty.sty { - ty::TyStruct(def, _) | ty::TyEnum(def, _) => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) => { if def.has_dtor() { Some(cmt.clone()) } else { diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index fc17633d63b..61c85e393d2 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -149,6 +149,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Interior(ref b, mc::InteriorField(_)) => { match b.ty.sty { ty::TyStruct(def, _) | + ty::TyUnion(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { let mut err = struct_span_err!(bccx, move_from.span, E0509, "cannot move out of type `{}`, \ diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 885bbe856c8..c5d10345379 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -709,7 +709,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock { let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx); match ty.sty { - ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { + ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => { self.open_drop_for_adt(c, def, substs) } ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts { @@ -893,7 +893,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx); match ty.sty { - ty::TyStruct(def, _) | ty::TyEnum(def, _) => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) => { if def.has_dtor() { self.tcx.sess.span_warn( c.source_info.span, diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 887c7deb86b..be408e2db5c 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -261,7 +261,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx lv, ty); true } - ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => false", lv, ty); true diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index e71a780dd89..de28cbb7c9c 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -566,7 +566,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, let pat = match left_ty.sty { ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None), - ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { + ty::TyEnum(adt, _) | ty::TyStruct(adt, _) | ty::TyUnion(adt, _) => { let v = ctor.variant_for_adt(adt); match v.kind { VariantKind::Struct => { @@ -792,7 +792,8 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => match cx.tcx.expect_def(pat.id) { Def::Variant(_, id) => vec![Variant(id)], - Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single], + Def::Struct(..) | Def::Union(..) | + Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single], Def::Const(..) | Def::AssociatedConst(..) => span_bug!(pat.span, "const pattern should've been rewritten"), def => span_bug!(pat.span, "pat_constructors: unexpected definition {:?}", def), @@ -836,7 +837,7 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us _ => bug!() }, ty::TyRef(..) => 1, - ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { + ty::TyEnum(adt, _) | ty::TyStruct(adt, _) | ty::TyUnion(adt, _) => { ctor.variant_for_adt(adt).fields.len() } ty::TyArray(_, n) => n, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index d71add3258f..81fe19812ca 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -258,7 +258,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, format!("floating point constants cannot be used in patterns")); } ty::TyEnum(adt_def, _) | - ty::TyStruct(adt_def, _) => { + ty::TyStruct(adt_def, _) | + ty::TyUnion(adt_def, _) => { if !tcx.has_attr(adt_def.did, "structural_match") { tcx.sess.add_lint( lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 460a6e68a5c..9f5f82c144c 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -220,6 +220,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { hir::ItemEnum(..) | hir::ItemStruct(..) | + hir::ItemUnion(..) | hir::ItemTrait(..) | hir::ItemImpl(..) | hir::ItemDefaultImpl(..) => { diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index c1158dc2d5f..d4a3ab59f9c 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -419,6 +419,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { Def::AssociatedTy(..) | Def::TyParam(..) | Def::Struct(..) | + Def::Union(..) | Def::Trait(..) | Def::Method(..) | Def::Const(..) | diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 0e130c3bb66..1094d0ee12b 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -111,7 +111,7 @@ impl LateLintPass for NonCamelCaseTypes { } match it.node { - hir::ItemTy(..) | hir::ItemStruct(..) => { + hir::ItemTy(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => { self.check_case(cx, "type", it.name, it.span) } hir::ItemTrait(..) => { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index a103386e2c9..571d1222baa 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -116,7 +116,8 @@ impl LateLintPass for BoxPointers { hir::ItemFn(..) | hir::ItemTy(..) | hir::ItemEnum(..) | - hir::ItemStruct(..) => + hir::ItemStruct(..) | + hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)), _ => () @@ -124,7 +125,8 @@ impl LateLintPass for BoxPointers { // If it's a struct, we also have to check the fields' types match it.node { - hir::ItemStruct(ref struct_def, _) => { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { for struct_field in struct_def.fields() { self.check_heap_type(cx, struct_field.span, cx.tcx.node_id_to_type(struct_field.id)); @@ -348,6 +350,7 @@ impl LateLintPass for MissingDoc { hir::ItemMod(..) => "a module", hir::ItemEnum(..) => "an enum", hir::ItemStruct(..) => "a struct", + hir::ItemUnion(..) => "a union", hir::ItemTrait(_, _, _, ref items) => { // Issue #11592, traits are always considered exported, even when private. if it.vis == hir::Visibility::Inherited { @@ -467,6 +470,14 @@ impl LateLintPass for MissingCopyImplementations { let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); (def, cx.tcx.mk_struct(def, Substs::empty(cx.tcx))) } + hir::ItemUnion(_, ref ast_generics) => { + if ast_generics.is_parameterized() { + return; + } + let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); + (def, cx.tcx.mk_union(def, + cx.tcx.mk_substs(Substs::empty()))) + } hir::ItemEnum(_, ref ast_generics) => { if ast_generics.is_parameterized() { return; @@ -523,7 +534,7 @@ impl LateLintPass for MissingDebugImplementations { } match item.node { - hir::ItemStruct(..) | hir::ItemEnum(..) => {}, + hir::ItemStruct(..) | hir::ItemUnion(..) | hir::ItemEnum(..) => {}, _ => return, } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 924b768958d..44f1cf7b533 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -137,6 +137,7 @@ impl LateLintPass for UnusedResults { ty::TyNever => return, ty::TyBool => return, ty::TyStruct(def, _) | + ty::TyUnion(def, _) | ty::TyEnum(def, _) => { let attrs = cx.tcx.get_attrs(def.did); check_must_use(cx, &attrs[..], s.span) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 6e8a5771eea..0469d44de4b 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -477,6 +477,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }) } } + ty::TyUnion(..) => { + unimplemented_unions!(); + } ty::TyEnum(adt, substs) => { match cx.tcx.expect_def(expr.id) { Def::Variant(enum_id, variant_id) => { @@ -579,7 +582,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, body: block::to_expr_ref(cx, body) }, hir::ExprField(ref source, name) => { let index = match cx.tcx.expr_ty_adjusted(source).sty { - ty::TyStruct(adt_def, _) => + ty::TyStruct(adt_def, _) | ty::TyUnion(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node), ref ty => span_bug!( diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 0bd22cd2d93..30f79796aaa 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -217,7 +217,9 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { PatKind::Struct(_, ref fields, _) => { let pat_ty = self.cx.tcx.node_id_to_type(pat.id); let adt_def = match pat_ty.sty { - ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def, + ty::TyStruct(adt_def, _) | + ty::TyUnion(adt_def, _) | + ty::TyEnum(adt_def, _) => adt_def, _ => { span_bug!( pat.span, @@ -313,7 +315,8 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } } - Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => { + Def::Struct(..) | Def::Union(..) | + Def::TyAlias(..) | Def::AssociatedTy(..) => { PatternKind::Leaf { subpatterns: subpatterns } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 21d4ae595e8..55bd51cd75b 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -281,7 +281,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { (&adt_def.variants[variant_index], substs) } LvalueTy::Ty { ty } => match ty.sty { - ty::TyStruct(adt_def, substs) | ty::TyEnum(adt_def, substs) + ty::TyStruct(adt_def, substs) | + ty::TyUnion(adt_def, substs) | + ty::TyEnum(adt_def, substs) if adt_def.is_univariant() => { (&adt_def.variants[0], substs) } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 2d1b6e1315f..c3749bf4546 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -440,6 +440,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) { match node_ty.sty { ty::TyStruct(def, _) | + ty::TyUnion(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { v.add_qualif(ConstQualif::NEEDS_DROP); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cd2eb4d2b58..25601b6bfec 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -174,7 +174,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { self.update(trait_item.id, item_level); } } - hir::ItemStruct(ref def, _) => { + hir::ItemStruct(ref def, _) | hir::ItemUnion(ref def, _) => { if !def.is_struct() { self.update(def.id(), item_level); } @@ -321,8 +321,8 @@ impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor< if let hir::TyPath(_, ref path) = ty.node { let def = self.ev.tcx.expect_def(ty.id); match def { - Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) | - Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { + Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) | + Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) { let item = self.ev.tcx.map.expect_item(node_id); if let Def::TyAlias(..) = def { @@ -943,8 +943,8 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, // free type aliases, but this isn't done yet. return } - Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) | - Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { + Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) | + Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { // Non-local means public (private items can't leave their crate, modulo bugs) if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { let item = self.tcx.map.expect_item(node_id); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1224c694a4e..db0704db33f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2187,6 +2187,7 @@ impl<'a> Resolver<'a> { Def::Trait(_) | Def::Enum(_) | Def::Struct(_) | + Def::Union(_) | Def::TyAlias(_) => true, _ => false, }, @@ -2389,7 +2390,7 @@ impl<'a> Resolver<'a> { PatKind::Struct(ref path, _, _) => { self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| { match def { - Def::Struct(..) | Def::Variant(..) | + Def::Struct(..) | Def::Union(..) | Def::Variant(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => true, _ => false, } @@ -2735,7 +2736,7 @@ impl<'a> Resolver<'a> { // Look for a field with the same name in the current self_type. if let Some(resolution) = self.def_map.get(&node_id) { match resolution.base_def { - Def::Enum(did) | Def::TyAlias(did) | + Def::Enum(did) | Def::TyAlias(did) | Def::Union(did) | Def::Struct(did) | Def::Variant(_, did) if resolution.depth == 0 => { if let Some(fields) = self.structs.get(&did) { if fields.iter().any(|&field_name| name == field_name) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index db535e22f19..47f3a06de1b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -404,7 +404,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } }; match self.tcx.expr_ty_adjusted(&hir_node).sty { - ty::TyStruct(def, _) => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); filter!(self.span_utils, sub_span, expr.span, None); @@ -423,7 +423,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::Struct(ref path, _, _) => { match self.tcx.expr_ty_adjusted(&hir_node).sty { - ty::TyStruct(def, _) => { + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); Some(Data::TypeRefData(TypeRefData { @@ -487,6 +487,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { })) } Def::Struct(def_id) | + Def::Union(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) | Def::Trait(def_id) | diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 2fb7a69d361..069eef7895c 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -176,6 +176,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(mk_struct(cx, &ftys[..], packed, t)) } + ty::TyUnion(..) => { + unimplemented_unions!(); + } ty::TyClosure(_, ref substs) => { Univariant(mk_struct(cx, &substs.upvar_tys, false, t)) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 47b3bb36cb9..4bea5d7e87f 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -744,6 +744,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // monomorphized Drop::drop() implementation. let destructor_did = match ty.sty { ty::TyStruct(def, _) | + ty::TyUnion(def, _) | ty::TyEnum(def, _) => def.destructor(), _ => None }; diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index f4682de7dff..6ae6f8aead7 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -88,8 +88,8 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - return false; } match ty.sty { - ty::TyStruct(..) | ty::TyEnum(..) | ty::TyTuple(..) | ty::TyArray(_, _) | - ty::TyClosure(..) => { + ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) | + ty::TyTuple(..) | ty::TyArray(..) | ty::TyClosure(..) => { let llty = sizing_type_of(ccx, ty); llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type()) } @@ -205,7 +205,7 @@ impl<'a, 'tcx> VariantInfo<'tcx> { -> Self { match ty.sty { - ty::TyStruct(adt, substs) | ty::TyEnum(adt, substs) => { + ty::TyStruct(adt, substs) | ty::TyUnion(adt, substs) | ty::TyEnum(adt, substs) => { let variant = match opt_def { None => adt.struct_variant(), Some(def) => adt.variant_of_def(def) diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 67d4a0e044c..f30880ac9be 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -184,6 +184,10 @@ impl<'tcx> TypeMap<'tcx> { unique_type_id.push_str("struct "); from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id); }, + ty::TyUnion(def, substs) => { + unique_type_id.push_str("union "); + from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id); + }, ty::TyTuple(component_types) if component_types.is_empty() => { push_debuginfo_type_name(cx, type_, false, &mut unique_type_id); }, @@ -781,6 +785,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, unique_type_id, usage_site_span).finalize(cx) } + ty::TyUnion(..) => { + unimplemented_unions!(); + } ty::TyTuple(ref elements) => { prepare_tuple_metadata(cx, t, diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 9e1e415f62a..5da9ef3646e 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -470,6 +470,9 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None) } } + ty::TyUnion(..) => { + unimplemented_unions!(); + } ty::TyTrait(..) => { // No support in vtable for distinguishing destroying with // versus without calling Drop::drop. Assert caller is diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index d5d8f049681..b5565109306 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -331,7 +331,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // If this was an enum or struct, fill in the type now. match t.sty { - ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..) + ty::TyEnum(..) | ty::TyStruct(..) | ty::TyUnion(..) | ty::TyClosure(..) if !t.is_simd() => { let repr = adt::represent_type(cx, t); adt::finish_type_of(cx, &repr, &mut llty); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6c9cc5f5e13..c445455ef2b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1476,7 +1476,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span, partition_bounds(tcx, span, &[])) } - Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { + Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => { tcx.prohibit_type_params(base_segments.split_last().unwrap().1); self.ast_path_to_ty(rscope, span, diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f8a2e82edc2..5fdfa19190b 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -510,7 +510,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type check subpatterns. let substs = match pat_ty.sty { - ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs, + ty::TyStruct(_, substs) | ty::TyUnion(_, substs) | ty::TyEnum(_, substs) => substs, _ => span_bug!(pat.span, "struct variant is not an ADT") }; self.check_struct_pat_fields(pat.span, fields, variant, substs, etc); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index bd47ff0b00b..3e37602169a 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -45,6 +45,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did); match dtor_self_type.sty { ty::TyEnum(adt_def, self_to_impl_substs) | + ty::TyUnion(adt_def, self_to_impl_substs) | ty::TyStruct(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond(ccx, drop_impl_did, @@ -495,7 +496,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.sty { - ty::TyEnum(def, _) | ty::TyStruct(def, _) => { + ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) => { def.is_dtorck(tcx) } ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 2e2cb2765d9..edee7300868 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -293,7 +293,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.assemble_inherent_impl_candidates_for_type(data.principal.def_id()); } ty::TyEnum(def, _) | - ty::TyStruct(def, _) => { + ty::TyStruct(def, _) | + ty::TyUnion(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); } ty::TyBox(_) => { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 46b3f503b6e..6d8a73b8a6a 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -164,30 +164,33 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // give a helping note that it has to be called as (x.f)(...). if let Some(expr) = rcvr_expr { for (ty, _) in self.autoderef(span, rcvr_ty) { - if let ty::TyStruct(def, substs) = ty.sty { - if let Some(field) = def.struct_variant().find_field_named(item_name) { - let snippet = tcx.sess.codemap().span_to_snippet(expr.span); - let expr_string = match snippet { - Ok(expr_string) => expr_string, - _ => "s".into() // Default to a generic placeholder for the - // expression when we can't generate a - // string snippet - }; - - let field_ty = field.ty(tcx, substs); - - if self.is_fn_ty(&field_ty, span) { - err.span_note(span, &format!( - "use `({0}.{1})(...)` if you meant to call the function \ - stored in the `{1}` field", - expr_string, item_name)); - } else { - err.span_note(span, &format!( - "did you mean to write `{0}.{1}`?", - expr_string, item_name)); + match ty.sty { + ty::TyStruct(def, substs) | ty::TyUnion(def, substs) => { + if let Some(field) = def.struct_variant().find_field_named(item_name) { + let snippet = tcx.sess.codemap().span_to_snippet(expr.span); + let expr_string = match snippet { + Ok(expr_string) => expr_string, + _ => "s".into() // Default to a generic placeholder for the + // expression when we can't generate a + // string snippet + }; + + let field_ty = field.ty(tcx, substs); + + if self.is_fn_ty(&field_ty, span) { + err.span_note(span, &format!( + "use `({0}.{1})(...)` if you meant to call the function \ + stored in the `{1}` field", + expr_string, item_name)); + } else { + err.span_note(span, &format!( + "did you mean to write `{0}.{1}`?", + expr_string, item_name)); + } + break; } - break; } + _ => {} } } } @@ -355,7 +358,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { rcvr_expr: Option<&hir::Expr>) -> bool { fn is_local(ty: Ty) -> bool { match ty.sty { - ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(), + ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) => { + def.did.is_local() + } ty::TyTrait(ref tr) => tr.principal.def_id().is_local(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index be33f836cc6..679ced1987e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -762,6 +762,9 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { hir::ItemStruct(..) => { check_struct(ccx, it.id, it.span); } + hir::ItemUnion(..) => { + unimplemented_unions!(); + } hir::ItemTy(_, ref generics) => { let pty_ty = ccx.tcx.node_id_to_type(it.id); check_bounds_are_used(ccx, generics, pty_ty); @@ -2942,18 +2945,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, expr_t); while let Some((base_t, autoderefs)) = autoderef.next() { - if let ty::TyStruct(base_def, substs) = base_t.sty { - debug!("struct named {:?}", base_t); - if let Some(field) = base_def.struct_variant().find_field_named(field.node) { - let field_ty = self.field_ty(expr.span, field, substs); - if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { - autoderef.finalize(lvalue_pref, Some(base)); - self.write_ty(expr.id, field_ty); - self.write_autoderef_adjustment(base.id, autoderefs); - return; + match base_t.sty { + ty::TyStruct(base_def, substs) | ty::TyUnion(base_def, substs) => { + debug!("struct named {:?}", base_t); + if let Some(field) = base_def.struct_variant().find_field_named(field.node) { + let field_ty = self.field_ty(expr.span, field, substs); + if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { + autoderef.finalize(lvalue_pref, Some(base)); + self.write_ty(expr.id, field_ty); + self.write_autoderef_adjustment(base.id, autoderefs); + return; + } + private_candidate = Some((base_def.did, field_ty)); } - private_candidate = Some((base_def.did, field_ty)); } + _ => {} } } autoderef.unambiguous_final_ty(); @@ -2986,12 +2992,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { but no field with that name was found", field.node, actual) }, expr_t); - if let ty::TyRawPtr(..) = expr_t.sty { - err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \ - `(*{0}).{1}`", pprust::expr_to_string(base), field.node)); - } - if let ty::TyStruct(def, _) = expr_t.sty { - Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]); + match expr_t.sty { + ty::TyStruct(def, _) | ty::TyUnion(def, _) => { + Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]); + } + ty::TyRawPtr(..) => { + err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \ + `(*{0}).{1}`", pprust::expr_to_string(base), field.node)); + } + _ => {} } err.emit(); self.write_error(expr.id); @@ -3125,7 +3134,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { check_completeness: bool) { let tcx = self.tcx; let substs = match adt_ty.sty { - ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs, + ty::TyStruct(_, substs) | ty::TyUnion(_, substs) | ty::TyEnum(_, substs) => substs, _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") }; @@ -3217,7 +3226,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); return None; } - Def::Variant(type_did, _) | Def::Struct(type_did) => { + Def::Variant(type_did, _) | Def::Struct(type_did) | Def::Union(type_did) => { Some((type_did, self.tcx.expect_variant_def(def))) } Def::TyAlias(did) => { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 435442bd30a..19bee13b6f6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -142,6 +142,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { self.check_variances_for_type_defn(item, ast_generics); } + hir::ItemUnion(..) => { + unimplemented_unions!(); + } hir::ItemEnum(ref enum_def, ref ast_generics) => { self.check_type_defn(item, |fcx| { fcx.enum_variants(enum_def) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index a20195bd801..fba145efa95 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -242,7 +242,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let self_type = tcx.lookup_item_type(impl_did); match self_type.ty.sty { ty::TyEnum(type_def, _) | - ty::TyStruct(type_def, _) => { + ty::TyStruct(type_def, _) | + ty::TyUnion(type_def, _) => { type_def.set_destructor(method_def_id.def_id()); } _ => { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index bcce64cb110..4c38475335c 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -76,7 +76,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { let self_ty = self.tcx.lookup_item_type(def_id).ty; match self_ty.sty { ty::TyEnum(def, _) | - ty::TyStruct(def, _) => { + ty::TyStruct(def, _) | + ty::TyUnion(def, _) => { self.check_def_id(item, def.did); } ty::TyTrait(ref data) => { @@ -293,7 +294,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { { let self_ty = trait_ref.self_ty(); let opt_self_def_id = match self_ty.sty { - ty::TyStruct(self_def, _) | ty::TyEnum(self_def, _) => + ty::TyStruct(self_def, _) | + ty::TyUnion(self_def, _) | + ty::TyEnum(self_def, _) => Some(self_def.did), ty::TyBox(..) => self.tcx.lang_items.owned_box(), diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index f60fb9583a6..c4d925372f1 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -97,7 +97,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { - hir::ItemEnum(..) | hir::ItemStruct(..) => { + hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => { let type_def_id = self.tcx.map.local_def_id(item.id); self.check_for_overlapping_inherent_impls(type_def_id); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7f9de2becee..1d260b9dbb2 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -931,7 +931,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), trait_item_def_ids); }, - hir::ItemStruct(ref struct_def, _) => { + hir::ItemStruct(ref struct_def, _) | + hir::ItemUnion(ref struct_def, _) => { let def_id = ccx.tcx.map.local_def_id(it.id); let scheme = type_scheme_of_def_id(ccx, def_id); let predicates = predicates_of_item(ccx, it); diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index e20e74be67c..24eb29f45a5 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -185,6 +185,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | + hir::ItemUnion(..) | hir::ItemTrait(..) => is_inferred = true, hir::ItemFn(..) => is_inferred = false, _ => cannot_happen!(), |
