提交 641d8e9e 编写于 作者: V Vadim Petrochenkov

Some better support for unions through the compiler

上级 a014323e
......@@ -18,6 +18,7 @@
enum Target {
Fn,
Struct,
Union,
Enum,
Other,
}
......@@ -27,6 +28,7 @@ fn from_item(item: &ast::Item) -> 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 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
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 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
"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
}
......
......@@ -331,7 +331,8 @@ fn visit_item(&mut self, i: &'ast hir::Item) {
});
}
}
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(),
......
......@@ -105,6 +105,7 @@ fn item_scope_tag(item: &hir::Item) -> &'static str {
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 @@ fn rebuild_arg_ty_or_output(&self,
}
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 =
......
......@@ -86,7 +86,7 @@ fn insert_def_id(&mut self, def_id: DefId) {
}
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 @@ fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
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 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId) {
}
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 @@ fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
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 @@ fn visit_node(&mut self, node: &ast_map::Node) {
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 @@ fn should_warn_about_item(&mut self, item: &hir::Item) -> bool {
| hir::ItemConst(..)
| hir::ItemFn(..)
| hir::ItemEnum(..)
| hir::ItemStruct(..) => true,
| hir::ItemStruct(..)
| hir::ItemUnion(..) => true,
_ => false
};
let ctor_id = get_struct_ctor_id(item);
......
......@@ -672,30 +672,36 @@ fn walk_struct_expr(&mut self,
// 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 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
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);
}
......
......@@ -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 {
......
......@@ -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"),
......
......@@ -174,6 +174,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
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
......
......@@ -263,6 +263,7 @@ fn push_impl_path<T>(self,
// 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);
......
......@@ -1256,6 +1256,9 @@ pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
}
}
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 {
......
......@@ -948,6 +948,7 @@ fn dep_node(&self) -> DepNode<DefId> {
.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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
}
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTy(..) |
hir::ItemImpl(..) |
hir::ItemConst(..) |
......@@ -1615,7 +1617,8 @@ pub fn has_dtor(&self) -> bool {
/// 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 @@ pub fn variant_index_with_id(&self, vid: DefId) -> usize {
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 @@ pub fn expect_variant_def(self, def: Def) -> VariantDef<'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)
......
......@@ -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 =>
......
......@@ -922,7 +922,7 @@ pub fn is_uninhabited(&self, _cx: TyCtxt) -> bool {
// 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 @@ pub fn is_slice(&self) -> bool {
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 @@ pub fn ty_to_def_id(&self) -> Option<DefId> {
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 @@ pub fn ty_to_def_id(&self) -> Option<DefId> {
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
}
}
......
......@@ -138,7 +138,7 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, '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 @@ pub fn arm_contains_ref_binding(self, arm: &hir::Arm) -> Option<hir::Mutability>
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 @@ pub fn positional_element_ty(self,
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 @@ pub fn named_element_ty(self,
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 @@ fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span,
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 @@ fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span,
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 @@ fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
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 @@ fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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();
......
......@@ -796,7 +796,9 @@ fn check_if_assigned_path_is_moved(&self,
}
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
......
......@@ -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 {
......
......@@ -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 `{}`, \
......
......@@ -709,7 +709,7 @@ fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, '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 @@ fn must_complete_drop<'a>(&self, c: &DropCtxt<'a, 'tcx>) -> bool {
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,
......
......@@ -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
......
......@@ -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,
......
......@@ -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,
......
......@@ -220,6 +220,7 @@ fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<as
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) |
hir::ItemImpl(..) |
hir::ItemDefaultImpl(..) => {
......
......@@ -419,6 +419,7 @@ fn hash_def(&mut self, def: Def) {
Def::AssociatedTy(..) |
Def::TyParam(..) |
Def::Struct(..) |
Def::Union(..) |
Def::Trait(..) |
Def::Method(..) |
Def::Const(..) |
......
......@@ -111,7 +111,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
}
match it.node {
hir::ItemTy(..) | hir::ItemStruct(..) => {
hir::ItemTy(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => {
self.check_case(cx, "type", it.name, it.span)
}
hir::ItemTrait(..) => {
......
......@@ -116,7 +116,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
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 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
// 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 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
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 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
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 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
}
match item.node {
hir::ItemStruct(..) | hir::ItemEnum(..) => {},
hir::ItemStruct(..) | hir::ItemUnion(..) | hir::ItemEnum(..) => {},
_ => return,
}
......
......@@ -137,6 +137,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
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)
......
......@@ -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!(
......
......@@ -217,7 +217,9 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'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 @@ fn variant_or_leaf(&mut self,
}
}
Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
Def::Struct(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => {
PatternKind::Leaf { subpatterns: subpatterns }
}
......
......@@ -281,7 +281,9 @@ fn field_ty(&mut self,
(&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)
}
......
......@@ -440,6 +440,7 @@ fn visit_expr(&mut self, ex: &hir::Expr) {
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);
}
......
......@@ -174,7 +174,7 @@ fn visit_item(&mut self, item: &hir::Item) {
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 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
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 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
// 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);
......
......@@ -2187,6 +2187,7 @@ fn resolve_type(&mut self, ty: &Ty) {
Def::Trait(_) |
Def::Enum(_) |
Def::Struct(_) |
Def::Union(_) |
Def::TyAlias(_) => true,
_ => false,
},
......@@ -2389,7 +2390,7 @@ fn resolve_pattern(&mut self,
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 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
// 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) {
......
......@@ -404,7 +404,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
};
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 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
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 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
}))
}
Def::Struct(def_id) |
Def::Union(def_id) |
Def::Enum(def_id) |
Def::TyAlias(def_id) |
Def::Trait(def_id) |
......
......@@ -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))
}
......
......@@ -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
};
......
......@@ -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 @@ pub fn from_ty(tcx: TyCtxt<'a, 'tcx, '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)
......
......@@ -184,6 +184,10 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, '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,
......
......@@ -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
......
......@@ -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);
......
......@@ -1476,7 +1476,7 @@ fn base_def_to_ty(&self,
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,
......
......@@ -510,7 +510,7 @@ fn check_pat_struct(&self,
// 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);
......
......@@ -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(..) => {
......
......@@ -293,7 +293,8 @@ fn assemble_probe(&mut self, self_ty: Ty<'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(_) => {
......
......@@ -164,30 +164,33 @@ pub fn report_method_error(&self,
// 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 @@ fn type_derefs_to_local(&self,
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(),
......
......@@ -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 @@ fn check_field(&self,
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 @@ fn check_field(&self,
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 @@ fn check_expr_struct_fields(&self,
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 @@ pub fn check_struct_path(&self,
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) => {
......
......@@ -142,6 +142,9 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
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)
......
......@@ -242,7 +242,8 @@ fn populate_destructors(&self) {
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());
}
_ => {
......
......@@ -76,7 +76,8 @@ fn check_item(&self, item: &hir::Item) {
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 @@ fn check_item(&self, item: &hir::Item) {
{
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(),
......
......@@ -97,7 +97,7 @@ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
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);
}
......
......@@ -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);
......
......@@ -185,6 +185,7 @@ fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
hir::ItemTy(..) |
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) => is_inferred = true,
hir::ItemFn(..) => is_inferred = false,
_ => cannot_happen!(),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册