提交 a014323e 编写于 作者: V Vadim Petrochenkov

Lower unions from AST to HIR and from HIR to types

Parse union items and add a feature for them
上级 cbd912ba
......@@ -638,7 +638,10 @@ fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ {
let struct_def = self.lower_variant_data(struct_def);
hir::ItemStruct(struct_def, self.lower_generics(generics))
}
ItemKind::Union(..) => panic!("`union` is not yet implemented"),
ItemKind::Union(ref vdata, ref generics) => {
let vdata = self.lower_variant_data(vdata);
hir::ItemUnion(vdata, self.lower_generics(generics))
}
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
self.lower_trait_ref(trait_ref))
......
......@@ -1321,6 +1321,11 @@ pub fn mk_struct(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx
self.mk_ty(TyStruct(def, substs))
}
pub fn mk_union(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
// take a copy of substs so that we own the vectors inside
self.mk_ty(TyUnion(def, substs))
}
pub fn mk_closure(self,
closure_id: DefId,
substs: &'tcx Substs<'tcx>,
......
......@@ -1514,7 +1514,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Enum }
pub enum AdtKind { Struct, Union, Enum }
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum VariantKind { Struct, Tuple, Unit }
......@@ -1545,8 +1545,10 @@ fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
if Some(did) == tcx.lang_items.phantom_data() {
flags = flags | AdtFlags::IS_PHANTOM_DATA;
}
if let AdtKind::Enum = kind {
flags = flags | AdtFlags::IS_ENUM;
match kind {
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
AdtKind::Struct => {}
}
AdtDefData {
did: did,
......@@ -1569,6 +1571,8 @@ fn calculate_dtorck(&'gcx self, tcx: TyCtxt) {
pub fn adt_kind(&self) -> AdtKind {
if self.flags.get().intersects(AdtFlags::IS_ENUM) {
AdtKind::Enum
} else if self.flags.get().intersects(AdtFlags::IS_UNION) {
AdtKind::Union
} else {
AdtKind::Struct
}
......
......@@ -383,7 +383,7 @@ fn item_is_accessible(&self, did: DefId) -> bool {
// Checks that a field is in scope.
fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
if def.adt_kind() == ty::AdtKind::Struct &&
if def.adt_kind() != ty::AdtKind::Enum &&
!field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private",
field.name, self.tcx.item_path_str(def.did))
......
......@@ -304,7 +304,8 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
tcx.item_path_str(def_id),
variant),
ty::AdtKind::Struct => format!("struct {}",
tcx.item_path_str(def_id))
tcx.item_path_str(def_id)),
ty::AdtKind::Union => unimplemented_unions!(),
};
span_note!(
&mut err,
......
......@@ -1069,6 +1069,16 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
adt
}
fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
it: &hir::Item,
def: &hir::VariantData)
-> ty::AdtDefMaster<'tcx>
{
let did = ccx.tcx.map.local_def_id(it.id);
let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
ccx.tcx.intern_adt_def(did, ty::AdtKind::Union, variants)
}
fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
-> Option<ty::Disr> {
debug!("disr expr, checking {}", pprust::expr_to_string(e));
......
......@@ -292,6 +292,9 @@ pub fn new() -> Features {
// Macros 1.1
(active, rustc_macro, "1.13.0", Some(35900)),
// Allows untagged unions `union U { ... }`
(active, untagged_unions, "1.13.0", Some(32836)),
);
declare_features! (
......@@ -953,6 +956,12 @@ fn visit_item(&mut self, i: &ast::Item) {
}
}
ast::ItemKind::Union(..) => {
gate_feature_post!(&self, untagged_unions,
i.span,
"unions are unstable and not fully implemented");
}
ast::ItemKind::DefaultImpl(..) => {
gate_feature_post!(&self, optin_builtin_traits,
i.span,
......
......@@ -5102,6 +5102,25 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
Ok((class_name, ItemKind::Struct(vdata, generics), None))
}
/// Parse union Foo { ... }
fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
let class_name = self.parse_ident()?;
let mut generics = self.parse_generics()?;
let vdata = if self.token.is_keyword(keywords::Where) {
generics.where_clause = self.parse_where_clause()?;
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
} else if self.token == token::OpenDelim(token::Brace) {
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
} else {
let token_str = self.this_token_to_string();
return Err(self.fatal(&format!("expected `where` or `{{` after union \
name, found `{}`", token_str)))
};
Ok((class_name, ItemKind::Union(vdata, generics), None))
}
pub fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
let mut fields = Vec::new();
if self.eat(&token::OpenDelim(token::Brace)) {
......@@ -5938,6 +5957,18 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
if self.eat_keyword(keywords::Union) {
// UNION ITEM
let (ident, item_, extra_attrs) = self.parse_item_union()?;
let last_span = self.last_span;
let item = self.mk_item(lo,
last_span.hi,
ident,
item_,
visibility,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册