Skip to content

Commit 641d8e9

Browse files
committed
Some better support for unions through the compiler
1 parent a014323 commit 641d8e9

File tree

51 files changed

+243
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+243
-134
lines changed

src/librustc/hir/check_attr.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use syntax::visit::Visitor;
1818
enum Target {
1919
Fn,
2020
Struct,
21+
Union,
2122
Enum,
2223
Other,
2324
}
@@ -27,6 +28,7 @@ impl Target {
2728
match item.node {
2829
ast::ItemKind::Fn(..) => Target::Fn,
2930
ast::ItemKind::Struct(..) => Target::Struct,
31+
ast::ItemKind::Union(..) => Target::Union,
3032
ast::ItemKind::Enum(..) => Target::Enum,
3133
_ => Target::Other,
3234
}
@@ -62,17 +64,20 @@ impl<'a> CheckAttrVisitor<'a> {
6264
let message = match &*name {
6365
"C" => {
6466
conflicting_reprs += 1;
65-
if target != Target::Struct && target != Target::Enum {
66-
"attribute should be applied to struct or enum"
67+
if target != Target::Struct &&
68+
target != Target::Union &&
69+
target != Target::Enum {
70+
"attribute should be applied to struct, enum or union"
6771
} else {
6872
continue
6973
}
7074
}
7175
"packed" => {
7276
// Do not increment conflicting_reprs here, because "packed"
7377
// can be used to modify another repr hint
74-
if target != Target::Struct {
75-
"attribute should be applied to struct"
78+
if target != Target::Struct &&
79+
target != Target::Union {
80+
"attribute should be applied to struct or union"
7681
} else {
7782
continue
7883
}

src/librustc/hir/map/def_collector.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
331331
});
332332
}
333333
}
334-
hir::ItemStruct(ref struct_def, _) => {
334+
hir::ItemStruct(ref struct_def, _) |
335+
hir::ItemUnion(ref struct_def, _) => {
335336
// If this is a tuple-like struct, register the constructor.
336337
if !struct_def.is_struct() {
337338
this.create_def(struct_def.id(),

src/librustc/infer/error_reporting.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
105105
match item.node {
106106
hir::ItemImpl(..) => "impl",
107107
hir::ItemStruct(..) => "struct",
108+
hir::ItemUnion(..) => "union",
108109
hir::ItemEnum(..) => "enum",
109110
hir::ItemTrait(..) => "trait",
110111
hir::ItemFn(..) => "function body",
@@ -1370,7 +1371,8 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
13701371
}
13711372
hir::TyPath(ref maybe_qself, ref path) => {
13721373
match self.tcx.expect_def(cur_ty.id) {
1373-
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
1374+
Def::Enum(did) | Def::TyAlias(did) |
1375+
Def::Struct(did) | Def::Union(did) => {
13741376
let generics = self.tcx.lookup_generics(did);
13751377

13761378
let expected =

src/librustc/middle/dead.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
8686
}
8787

8888
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
89-
use ty::TypeVariants::{TyEnum, TyStruct};
89+
use ty::TypeVariants::{TyEnum, TyStruct, TyUnion};
9090

9191
let def = self.tcx.expect_def(id);
9292

@@ -96,7 +96,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
9696
if self.tcx.trait_of_item(def.def_id()).is_some() => {
9797
if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
9898
match substs.substs.type_at(0).sty {
99-
TyEnum(tyid, _) | TyStruct(tyid, _) => {
99+
TyEnum(tyid, _) | TyStruct(tyid, _) | TyUnion(tyid, _) => {
100100
self.check_def_id(tyid.did)
101101
}
102102
_ => {}
@@ -132,10 +132,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
132132
}
133133

134134
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
135-
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
136-
self.insert_def_id(def.struct_variant().field_named(name).did);
137-
} else {
138-
span_bug!(lhs.span, "named field access on non-struct")
135+
match self.tcx.expr_ty_adjusted(lhs).sty {
136+
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
137+
self.insert_def_id(def.struct_variant().field_named(name).did);
138+
}
139+
_ => span_bug!(lhs.span, "named field access on non-struct"),
139140
}
140141
}
141142

@@ -148,7 +149,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
148149
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
149150
pats: &[codemap::Spanned<hir::FieldPat>]) {
150151
let variant = match self.tcx.node_id_to_type(lhs.id).sty {
151-
ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => {
152+
ty::TyStruct(adt, _) | ty::TyUnion(adt, _) | ty::TyEnum(adt, _) => {
152153
adt.variant_of_def(self.tcx.expect_def(lhs.id))
153154
}
154155
_ => span_bug!(lhs.span, "non-ADT in struct pattern")
@@ -185,7 +186,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
185186
match *node {
186187
ast_map::NodeItem(item) => {
187188
match item.node {
188-
hir::ItemStruct(..) => {
189+
hir::ItemStruct(..) | hir::ItemUnion(..) => {
189190
self.struct_has_extern_repr = item.attrs.iter().any(|attr| {
190191
attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr)
191192
.contains(&attr::ReprExtern)
@@ -423,7 +424,8 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
423424
| hir::ItemConst(..)
424425
| hir::ItemFn(..)
425426
| hir::ItemEnum(..)
426-
| hir::ItemStruct(..) => true,
427+
| hir::ItemStruct(..)
428+
| hir::ItemUnion(..) => true,
427429
_ => false
428430
};
429431
let ctor_id = get_struct_ctor_id(item);

src/librustc/middle/expr_use_visitor.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -672,30 +672,36 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
672672

673673
// Select just those fields of the `with`
674674
// expression that will actually be used
675-
if let ty::TyStruct(def, substs) = with_cmt.ty.sty {
676-
// Consume those fields of the with expression that are needed.
677-
for with_field in &def.struct_variant().fields {
678-
if !contains_field_named(with_field, fields) {
679-
let cmt_field = self.mc.cat_field(
680-
&*with_expr,
681-
with_cmt.clone(),
682-
with_field.name,
683-
with_field.ty(self.tcx(), substs)
684-
);
685-
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
675+
match with_cmt.ty.sty {
676+
ty::TyStruct(def, substs) => {
677+
// Consume those fields of the with expression that are needed.
678+
for with_field in &def.struct_variant().fields {
679+
if !contains_field_named(with_field, fields) {
680+
let cmt_field = self.mc.cat_field(
681+
&*with_expr,
682+
with_cmt.clone(),
683+
with_field.name,
684+
with_field.ty(self.tcx(), substs)
685+
);
686+
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
687+
}
686688
}
687689
}
688-
} else {
689-
// the base expression should always evaluate to a
690-
// struct; however, when EUV is run during typeck, it
691-
// may not. This will generate an error earlier in typeck,
692-
// so we can just ignore it.
693-
if !self.tcx().sess.has_errors() {
694-
span_bug!(
695-
with_expr.span,
696-
"with expression doesn't evaluate to a struct");
690+
ty::TyUnion(..) => {
691+
unimplemented_unions!();
697692
}
698-
};
693+
_ => {
694+
// the base expression should always evaluate to a
695+
// struct; however, when EUV is run during typeck, it
696+
// may not. This will generate an error earlier in typeck,
697+
// so we can just ignore it.
698+
if !self.tcx().sess.has_errors() {
699+
span_bug!(
700+
with_expr.span,
701+
"with expression doesn't evaluate to a struct");
702+
}
703+
}
704+
}
699705

700706
// walk the with expression so that complex expressions
701707
// are properly handled.
@@ -1012,7 +1018,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
10121018
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
10131019
delegate.matched_pat(pat, downcast_cmt, match_mode);
10141020
}
1015-
Some(Def::Struct(..)) | Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
1021+
Some(Def::Struct(..)) | Some(Def::Union(..)) |
1022+
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
10161023
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
10171024
delegate.matched_pat(pat, cmt_pat, match_mode);
10181025
}

src/librustc/middle/stability.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,9 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
561561
hir::ExprField(ref base_e, ref field) => {
562562
span = field.span;
563563
match tcx.expr_ty_adjusted(base_e).sty {
564-
ty::TyStruct(def, _) => def.struct_variant().field_named(field.node).did,
564+
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
565+
def.struct_variant().field_named(field.node).did
566+
}
565567
_ => span_bug!(e.span,
566568
"stability::check_expr: named field access on non-struct")
567569
}
@@ -579,7 +581,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
579581
hir::ExprStruct(_, ref expr_fields, _) => {
580582
let type_ = tcx.expr_ty(e);
581583
match type_.sty {
582-
ty::TyStruct(def, _) => {
584+
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
583585
// check the stability of each field that appears
584586
// in the construction expression.
585587
for field in expr_fields {
@@ -647,7 +649,8 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
647649
if is_internal(tcx, pat.span) { return; }
648650

649651
let v = match tcx.pat_ty_opt(pat) {
650-
Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) => def.struct_variant(),
652+
Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) |
653+
Some(&ty::TyS { sty: ty::TyUnion(def, _), .. }) => def.struct_variant(),
651654
Some(_) | None => return,
652655
};
653656
match pat.node {

src/librustc/traits/coherence.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
224224
match ty.sty {
225225
ty::TyBox(..) | ty::TyRef(..) =>
226226
true,
227-
ty::TyEnum(def, _) | ty::TyStruct(def, _) =>
227+
ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) =>
228228
def.is_fundamental(),
229229
ty::TyTrait(ref data) =>
230230
tcx.has_attr(data.principal.def_id(), "fundamental"),

src/librustc/traits/error_reporting.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
174174
match (type_category(a), type_category(b)) {
175175
(Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) {
176176
(&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) |
177+
(&ty::TyUnion(def_a, _), &ty::TyUnion(def_b, _)) |
177178
(&ty::TyEnum(def_a, _), &ty::TyEnum(def_b, _)) =>
178179
def_a == def_b,
179180
_ => cat_a == cat_b

src/librustc/ty/item_path.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
263263
// anything other than a simple path.
264264
match self_ty.sty {
265265
ty::TyStruct(adt_def, substs) |
266+
ty::TyUnion(adt_def, substs) |
266267
ty::TyEnum(adt_def, substs) => {
267268
if substs.types().next().is_none() { // ignore regions
268269
self.push_item_path(buffer, adt_def.did);

src/librustc/ty/layout.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,9 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
12561256
}
12571257
}
12581258

1259+
ty::TyUnion(..) => {
1260+
unimplemented_unions!();
1261+
}
12591262
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
12601263
// Only newtypes and enums w/ nullable pointer optimization.
12611264
if def.variants.is_empty() || def.variants.len() > 2 {

0 commit comments

Comments
 (0)