Lower anonymous structs or unions to HIR
This commit is contained in:
parent
084ce5bdb5
commit
879a1e5713
@ -2107,9 +2107,9 @@ pub enum TyKind {
|
||||
/// A tuple (`(A, B, C, D,...)`).
|
||||
Tup(ThinVec<P<Ty>>),
|
||||
/// An anonymous struct type i.e. `struct { foo: Type }`
|
||||
AnonStruct(ThinVec<FieldDef>),
|
||||
AnonStruct(NodeId, ThinVec<FieldDef>),
|
||||
/// An anonymous union type i.e. `union { bar: Type }`
|
||||
AnonUnion(ThinVec<FieldDef>),
|
||||
AnonUnion(NodeId, ThinVec<FieldDef>),
|
||||
/// A path (`module::module::...::Type`), optionally
|
||||
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
|
||||
///
|
||||
|
@ -514,7 +514,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
||||
}
|
||||
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||
TyKind::AnonStruct(fields) | TyKind::AnonUnion(fields) => {
|
||||
TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
|
||||
vis.visit_id(id);
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
|
||||
TyKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
TyKind::Never | TyKind::CVarArgs => {}
|
||||
TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => {
|
||||
TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
|
||||
walk_list!(visitor, visit_field_def, fields)
|
||||
}
|
||||
}
|
||||
|
@ -720,7 +720,10 @@ fn lower_variant_data(
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
|
||||
pub(super) fn lower_field_def(
|
||||
&mut self,
|
||||
(index, f): (usize, &FieldDef),
|
||||
) -> hir::FieldDef<'hir> {
|
||||
let ty = if let TyKind::Path(qself, path) = &f.ty.kind {
|
||||
let t = self.lower_path_ty(
|
||||
&f.ty,
|
||||
|
@ -1288,17 +1288,49 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
|
||||
TyKind::Err => {
|
||||
hir::TyKind::Err(self.dcx().span_delayed_bug(t.span, "TyKind::Err lowered"))
|
||||
}
|
||||
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
TyKind::AnonStruct(ref _fields) => {
|
||||
hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous structs are unimplemented"))
|
||||
}
|
||||
// FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
TyKind::AnonUnion(ref _fields) => {
|
||||
hir::TyKind::Err(self.dcx().span_err(t.span, "anonymous unions are unimplemented"))
|
||||
// Lower the anonymous structs or unions in a nested lowering context.
|
||||
//
|
||||
// ```
|
||||
// struct Foo {
|
||||
// _: union {
|
||||
// // ^__________________ <-- within the nested lowering context,
|
||||
// /* fields */ // | we lower all fields defined into an
|
||||
// } // | owner node of struct or union item
|
||||
// // ^_____________________|
|
||||
// }
|
||||
// ```
|
||||
TyKind::AnonStruct(def_node_id, fields) | TyKind::AnonUnion(def_node_id, fields) => {
|
||||
let (def_kind, item_kind): (DefKind, fn(_, _) -> _) = match t.kind {
|
||||
TyKind::AnonStruct(..) => (DefKind::Struct, hir::ItemKind::Struct),
|
||||
TyKind::AnonUnion(..) => (DefKind::Union, hir::ItemKind::Union),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
*def_node_id,
|
||||
kw::Empty,
|
||||
def_kind,
|
||||
t.span,
|
||||
);
|
||||
debug!(?def_id);
|
||||
let owner_id = hir::OwnerId { def_id };
|
||||
self.with_hir_id_owner(*def_node_id, |this| {
|
||||
let fields = this.arena.alloc_from_iter(
|
||||
fields.iter().enumerate().map(|f| this.lower_field_def(f)),
|
||||
);
|
||||
let span = t.span;
|
||||
let variant_data = hir::VariantData::Struct(fields, false);
|
||||
// FIXME: capture the generics from the outer adt.
|
||||
let generics = hir::Generics::empty();
|
||||
hir::OwnerNode::Item(this.arena.alloc(hir::Item {
|
||||
ident: Ident::new(kw::Empty, span),
|
||||
owner_id,
|
||||
kind: item_kind(variant_data, generics),
|
||||
span: this.lower_span(span),
|
||||
vis_span: this.lower_span(span.shrink_to_lo()),
|
||||
}))
|
||||
});
|
||||
hir::TyKind::AnonAdt(hir::ItemId { owner_id })
|
||||
}
|
||||
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
|
||||
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
|
||||
|
@ -219,7 +219,7 @@ fn walk_ty(&mut self, t: &'a Ty) {
|
||||
}
|
||||
}
|
||||
}
|
||||
TyKind::AnonStruct(ref fields, ..) | TyKind::AnonUnion(ref fields, ..) => {
|
||||
TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
|
||||
walk_list!(self, visit_field_def, fields)
|
||||
}
|
||||
_ => visit::walk_ty(self, t),
|
||||
|
@ -1003,11 +1003,11 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
|
||||
}
|
||||
self.pclose();
|
||||
}
|
||||
ast::TyKind::AnonStruct(fields) => {
|
||||
ast::TyKind::AnonStruct(_, fields) => {
|
||||
self.head("struct");
|
||||
self.print_record_struct_body(fields, ty.span);
|
||||
}
|
||||
ast::TyKind::AnonUnion(fields) => {
|
||||
ast::TyKind::AnonUnion(_, fields) => {
|
||||
self.head("union");
|
||||
self.print_record_struct_body(fields, ty.span);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use std::array::IntoIter;
|
||||
@ -225,6 +226,7 @@ pub fn ns(&self) -> Option<Namespace> {
|
||||
|
||||
pub fn def_path_data(self, name: Symbol) -> DefPathData {
|
||||
match self {
|
||||
DefKind::Struct | DefKind::Union if name == kw::Empty => DefPathData::AnonAdt,
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
|
@ -287,6 +287,8 @@ pub enum DefPathData {
|
||||
/// An existential `impl Trait` type node.
|
||||
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
||||
OpaqueTy,
|
||||
/// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { bar: Type }`
|
||||
AnonAdt,
|
||||
}
|
||||
|
||||
impl Definitions {
|
||||
@ -409,8 +411,9 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||
match *self {
|
||||
TypeNs(name) if name == kw::Empty => None,
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
||||
|
||||
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
|
||||
| OpaqueTy => None,
|
||||
| OpaqueTy | AnonAdt => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,6 +434,7 @@ pub fn name(&self) -> DefPathDataName {
|
||||
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
|
||||
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
|
||||
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
|
||||
AnonAdt => DefPathDataName::Anon { namespace: sym::anon_adt },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2587,6 +2587,8 @@ pub enum TyKind<'hir> {
|
||||
Never,
|
||||
/// A tuple (`(A, B, C, D, ...)`).
|
||||
Tup(&'hir [Ty<'hir>]),
|
||||
/// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { foo: Type }`
|
||||
AnonAdt(ItemId),
|
||||
/// A path to a type definition (`module::module::...::Type`), or an
|
||||
/// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`).
|
||||
///
|
||||
|
@ -852,6 +852,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
||||
}
|
||||
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
|
||||
TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {}
|
||||
TyKind::AnonAdt(item_id) => {
|
||||
visitor.visit_nested_item(item_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2457,6 +2457,19 @@ fn ast_ty_to_ty_inner(
|
||||
hir::TyKind::Tup(fields) => {
|
||||
Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t)))
|
||||
}
|
||||
hir::TyKind::AnonAdt(item_id) => {
|
||||
let did = item_id.owner_id.def_id;
|
||||
let adt_def = tcx.adt_def(did);
|
||||
let generics = tcx.generics_of(did);
|
||||
|
||||
debug!("ast_ty_to_ty_inner(AnonAdt): generics={:?}", generics);
|
||||
let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| {
|
||||
tcx.mk_param_from_def(param)
|
||||
});
|
||||
debug!("ast_ty_to_ty_inner(AnonAdt): args={:?}", args);
|
||||
|
||||
Ty::new_adt(tcx, adt_def, tcx.mk_args(args))
|
||||
}
|
||||
hir::TyKind::BareFn(bf) => {
|
||||
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);
|
||||
|
||||
|
@ -789,6 +789,65 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// In a type definition, we check that unnamed field names are distinct.
|
||||
fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) {
|
||||
let mut seen_fields: FxHashMap<Ident, Option<Span>> = Default::default();
|
||||
fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap<Ident, Option<Span>>) {
|
||||
let fields = match &item.kind {
|
||||
hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields,
|
||||
_ => return,
|
||||
};
|
||||
for field in fields.fields() {
|
||||
if field.ident.name == kw::Underscore {
|
||||
if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() {
|
||||
let item = tcx.hir().item(item_id);
|
||||
check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
|
||||
} else {
|
||||
let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() {
|
||||
Some(adt_ty) => adt_ty,
|
||||
None => {
|
||||
tcx.sess.emit_err(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Some(def_id) = field_ty.did().as_local() {
|
||||
let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }});
|
||||
check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
|
||||
}
|
||||
}
|
||||
field_ty.flags()
|
||||
let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt");
|
||||
check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields);
|
||||
} else {
|
||||
let span = field.did.as_local().map(|did| {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(did);
|
||||
tcx.hir().span(hir_id)
|
||||
});
|
||||
match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() {
|
||||
Some(Some(prev_span)) => {
|
||||
tcx.sess.emit_err(errors::FieldAlreadyDeclared {
|
||||
field_name: ident,
|
||||
span: f.span,
|
||||
prev_span,
|
||||
});
|
||||
}
|
||||
Some(None) => {
|
||||
tcx.sess.emit_err(errors::FieldAlreadyDeclared {
|
||||
field_name: f.ident,
|
||||
span: f.span,
|
||||
prev_span,
|
||||
});
|
||||
}
|
||||
None =>
|
||||
seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fn convert_variant(
|
||||
tcx: TyCtxt<'_>,
|
||||
variant_did: Option<LocalDefId>,
|
||||
@ -798,11 +857,17 @@ fn convert_variant(
|
||||
adt_kind: ty::AdtKind,
|
||||
parent_did: LocalDefId,
|
||||
) -> ty::VariantDef {
|
||||
let mut has_unnamed_fields = false;
|
||||
let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
|
||||
let fields = def
|
||||
.fields()
|
||||
.iter()
|
||||
.map(|f| {
|
||||
.inspect(|f| {
|
||||
// Skip the unnamed field here, we will check it later.
|
||||
if f.ident.name == kw::Underscore {
|
||||
has_unnamed_fields = true;
|
||||
return;
|
||||
}
|
||||
let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
|
||||
if let Some(prev_span) = dup_span {
|
||||
tcx.dcx().emit_err(errors::FieldAlreadyDeclared {
|
||||
@ -813,12 +878,11 @@ fn convert_variant(
|
||||
} else {
|
||||
seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
|
||||
}
|
||||
|
||||
ty::FieldDef {
|
||||
did: f.def_id.to_def_id(),
|
||||
name: f.ident.name,
|
||||
vis: tcx.visibility(f.def_id),
|
||||
}
|
||||
})
|
||||
.map(|f| ty::FieldDef {
|
||||
did: f.def_id.to_def_id(),
|
||||
name: f.ident.name,
|
||||
vis: tcx.visibility(f.def_id),
|
||||
})
|
||||
.collect();
|
||||
let recovered = match def {
|
||||
@ -837,6 +901,7 @@ fn convert_variant(
|
||||
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|
||||
|| variant_did
|
||||
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
|
||||
has_unnamed_fields,
|
||||
)
|
||||
}
|
||||
|
||||
@ -847,6 +912,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
||||
bug!("expected ADT to be an item");
|
||||
};
|
||||
|
||||
let is_anonymous = item.ident.name == kw::Empty;
|
||||
let repr = tcx.repr_options_of_def(def_id.to_def_id());
|
||||
let (kind, variants) = match &item.kind {
|
||||
ItemKind::Enum(def, _) => {
|
||||
@ -897,7 +963,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
|
||||
}
|
||||
_ => bug!("{:?} is not an ADT", item.owner_id.def_id),
|
||||
};
|
||||
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
|
||||
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous)
|
||||
}
|
||||
|
||||
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
||||
|
@ -328,6 +328,7 @@ fn print_type(&mut self, ty: &hir::Ty<'_>) {
|
||||
hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => {
|
||||
self.word("_");
|
||||
}
|
||||
hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"),
|
||||
}
|
||||
self.end()
|
||||
}
|
||||
@ -728,26 +729,30 @@ fn print_struct(
|
||||
}
|
||||
hir::VariantData::Struct { .. } => {
|
||||
self.print_where_clause(generics);
|
||||
self.nbsp();
|
||||
self.bopen();
|
||||
self.hardbreak_if_not_bol();
|
||||
|
||||
for field in struct_def.fields() {
|
||||
self.hardbreak_if_not_bol();
|
||||
self.maybe_print_comment(field.span.lo());
|
||||
self.print_outer_attributes(self.attrs(field.hir_id));
|
||||
self.print_ident(field.ident);
|
||||
self.word_nbsp(":");
|
||||
self.print_type(field.ty);
|
||||
self.word(",");
|
||||
}
|
||||
|
||||
self.bclose(span)
|
||||
self.print_variant_struct(span, struct_def.fields())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_variant(&mut self, v: &hir::Variant<'_>) {
|
||||
fn print_variant_struct(&mut self, span: rustc_span::Span, fields: &[hir::FieldDef<'_>]) {
|
||||
self.nbsp();
|
||||
self.bopen();
|
||||
self.hardbreak_if_not_bol();
|
||||
|
||||
for field in fields {
|
||||
self.hardbreak_if_not_bol();
|
||||
self.maybe_print_comment(field.span.lo());
|
||||
self.print_outer_attributes(self.attrs(field.hir_id));
|
||||
self.print_ident(field.ident);
|
||||
self.word_nbsp(":");
|
||||
self.print_type(field.ty);
|
||||
self.word(",");
|
||||
}
|
||||
|
||||
self.bclose(span)
|
||||
}
|
||||
|
||||
pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
|
||||
self.head("");
|
||||
let generics = hir::Generics::empty();
|
||||
self.print_struct(&v.data, generics, v.ident.name, v.span, false);
|
||||
|
@ -1084,6 +1084,8 @@ fn get_variant(
|
||||
parent_did,
|
||||
false,
|
||||
data.is_non_exhaustive,
|
||||
// FIXME: unnamed fields in crate metadata is unimplemented yet.
|
||||
false,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -1126,6 +1128,7 @@ fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
|
||||
adt_kind,
|
||||
variants.into_iter().map(|(_, variant)| variant).collect(),
|
||||
repr,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -756,6 +756,13 @@ pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
|
||||
match self.tcx.hir_node(id) {
|
||||
Node::Field(field) => field,
|
||||
_ => bug!("expected field, found {}", self.node_to_string(id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
|
||||
match self.tcx.hir_owner_node(id) {
|
||||
OwnerNode::ForeignItem(item) => item,
|
||||
|
@ -50,6 +50,8 @@ impl AdtFlags: u16 {
|
||||
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
|
||||
/// Indicates whether the type is `UnsafeCell`.
|
||||
const IS_UNSAFE_CELL = 1 << 9;
|
||||
/// Indicates whether the type is anonymous.
|
||||
const IS_ANONYMOUS = 1 << 10;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { AdtFlags }
|
||||
@ -233,8 +235,12 @@ pub(super) fn new(
|
||||
kind: AdtKind,
|
||||
variants: IndexVec<VariantIdx, VariantDef>,
|
||||
repr: ReprOptions,
|
||||
is_anonymous: bool,
|
||||
) -> Self {
|
||||
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
|
||||
debug!(
|
||||
"AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})",
|
||||
did, kind, variants, repr, is_anonymous
|
||||
);
|
||||
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
||||
|
||||
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
|
||||
@ -267,6 +273,9 @@ pub(super) fn new(
|
||||
if Some(did) == tcx.lang_items().unsafe_cell_type() {
|
||||
flags |= AdtFlags::IS_UNSAFE_CELL;
|
||||
}
|
||||
if is_anonymous {
|
||||
flags |= AdtFlags::IS_ANONYMOUS;
|
||||
}
|
||||
|
||||
AdtDefData { did, variants, flags, repr }
|
||||
}
|
||||
@ -365,6 +374,12 @@ pub fn is_manually_drop(self) -> bool {
|
||||
self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an anonymous adt
|
||||
#[inline]
|
||||
pub fn is_anonymous(self) -> bool {
|
||||
self.flags().contains(AdtFlags::IS_ANONYMOUS)
|
||||
}
|
||||
|
||||
/// Returns `true` if this type has a destructor.
|
||||
pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.destructor(tcx).is_some()
|
||||
|
@ -715,8 +715,16 @@ pub fn mk_adt_def(
|
||||
kind: AdtKind,
|
||||
variants: IndexVec<VariantIdx, ty::VariantDef>,
|
||||
repr: ReprOptions,
|
||||
is_anonymous: bool,
|
||||
) -> ty::AdtDef<'tcx> {
|
||||
self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
|
||||
self.mk_adt_def_from_data(ty::AdtDefData::new(
|
||||
self,
|
||||
did,
|
||||
kind,
|
||||
variants,
|
||||
repr,
|
||||
is_anonymous,
|
||||
))
|
||||
}
|
||||
|
||||
/// Allocates a read-only byte or string literal for `mir::interpret`.
|
||||
|
@ -1130,6 +1130,8 @@ impl VariantFlags: u8 {
|
||||
/// Indicates whether this variant was obtained as part of recovering from
|
||||
/// a syntactic error. May be incomplete or bogus.
|
||||
const IS_RECOVERED = 1 << 1;
|
||||
/// Indicates whether this variant has unnamed fields.
|
||||
const HAS_UNNAMED_FIELDS = 1 << 2;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { VariantFlags }
|
||||
@ -1143,7 +1145,7 @@ pub struct VariantDef {
|
||||
/// `DefId` that identifies the variant's constructor.
|
||||
/// If this variant is a struct variant, then this is `None`.
|
||||
pub ctor: Option<(CtorKind, DefId)>,
|
||||
/// Variant or struct name.
|
||||
/// Variant or struct name, maybe empty for anonymous adt (struct or union).
|
||||
pub name: Symbol,
|
||||
/// Discriminant of this variant.
|
||||
pub discr: VariantDiscr,
|
||||
@ -1180,11 +1182,12 @@ pub fn new(
|
||||
parent_did: DefId,
|
||||
recovered: bool,
|
||||
is_field_list_non_exhaustive: bool,
|
||||
has_unnamed_fields: bool,
|
||||
) -> Self {
|
||||
debug!(
|
||||
"VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
|
||||
fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
|
||||
name, variant_did, ctor, discr, fields, adt_kind, parent_did,
|
||||
fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})",
|
||||
name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields,
|
||||
);
|
||||
|
||||
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
|
||||
@ -1196,6 +1199,10 @@ pub fn new(
|
||||
flags |= VariantFlags::IS_RECOVERED;
|
||||
}
|
||||
|
||||
if has_unnamed_fields {
|
||||
flags |= VariantFlags::HAS_UNNAMED_FIELDS;
|
||||
}
|
||||
|
||||
VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
|
||||
}
|
||||
|
||||
@ -1211,6 +1218,12 @@ pub fn is_recovered(&self) -> bool {
|
||||
self.flags.intersects(VariantFlags::IS_RECOVERED)
|
||||
}
|
||||
|
||||
/// Does this variant contains unnamed fields
|
||||
#[inline]
|
||||
pub fn has_unnamed_fields(&self) -> bool {
|
||||
self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS)
|
||||
}
|
||||
|
||||
/// Computes the `Ident` of this variant by looking up the `Span`
|
||||
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
|
||||
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
|
||||
|
@ -396,8 +396,9 @@ fn parse_anon_struct_or_union(&mut self) -> PResult<'a, P<Ty>> {
|
||||
self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?;
|
||||
let span = lo.to(self.prev_token.span);
|
||||
self.sess.gated_spans.gate(sym::unnamed_fields, span);
|
||||
// These can be rejected during AST validation in `deny_anon_struct_or_union`.
|
||||
let kind = if is_union { TyKind::AnonUnion(fields) } else { TyKind::AnonStruct(fields) };
|
||||
let id = ast::DUMMY_NODE_ID;
|
||||
let kind =
|
||||
if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) };
|
||||
Ok(self.mk_ty(span, kind))
|
||||
}
|
||||
|
||||
|
@ -345,6 +345,7 @@ fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
|
||||
BareFn,
|
||||
Never,
|
||||
Tup,
|
||||
AnonAdt,
|
||||
Path,
|
||||
OpaqueDef,
|
||||
TraitObject,
|
||||
|
@ -382,6 +382,7 @@
|
||||
and,
|
||||
and_then,
|
||||
anon,
|
||||
anon_adt,
|
||||
anonymous_lifetime_in_impl_trait,
|
||||
any,
|
||||
append_const_msg,
|
||||
|
@ -387,7 +387,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
|
||||
| hir::definitions::DefPathData::Use
|
||||
| hir::definitions::DefPathData::GlobalAsm
|
||||
| hir::definitions::DefPathData::MacroNs(..)
|
||||
| hir::definitions::DefPathData::LifetimeNs(..) => {
|
||||
| hir::definitions::DefPathData::LifetimeNs(..)
|
||||
| hir::definitions::DefPathData::AnonAdt => {
|
||||
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
|
||||
}
|
||||
});
|
||||
|
@ -748,7 +748,8 @@ fn path_append(
|
||||
| DefPathData::GlobalAsm
|
||||
| DefPathData::Impl
|
||||
| DefPathData::MacroNs(_)
|
||||
| DefPathData::LifetimeNs(_) => {
|
||||
| DefPathData::LifetimeNs(_)
|
||||
| DefPathData::AnonAdt => {
|
||||
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
|
||||
}
|
||||
};
|
||||
|
@ -181,6 +181,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
||||
| ty::Ref(_, _, Mutability::Not)
|
||||
| ty::Array(..) => Err(NoSolution),
|
||||
|
||||
// Check for anonymous adts.
|
||||
ty::Adt(adt, generics) if adt.is_anonymous() => {
|
||||
Ok(adt.all_fields().map(|f| f.ty(ecx.tcx(), generics)).collect())
|
||||
}
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
|
@ -2212,6 +2212,16 @@ fn copy_clone_conditions(
|
||||
|
||||
// FIXME(async_closures): These are never clone, for now.
|
||||
ty::CoroutineClosure(_, _) => None,
|
||||
// `Copy` and `Clone` are automatically impelemented for an anonymous adt
|
||||
// if all of its fields are `Copy` and `Clone`
|
||||
ty::Adt(adt, args) if adt.is_anonymous() => {
|
||||
// (*) binder moved here
|
||||
Where(
|
||||
obligation
|
||||
.predicate
|
||||
.rebind(adt.all_fields().map(|f| f.ty(self.tcx(), args)).collect()),
|
||||
)
|
||||
}
|
||||
|
||||
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {
|
||||
// Fallback to whatever user-defined impls exist in this case.
|
||||
|
@ -21,8 +21,7 @@ macro_rules! rtry {
|
||||
fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
||||
let adt_def = tcx.adt_def(def_id);
|
||||
for variant in adt_def.variants() {
|
||||
for variant in tcx.adt_def(def_id).variants() {
|
||||
for field in variant.fields.iter() {
|
||||
rtry!(tcx.representability(field.did.expect_local()));
|
||||
}
|
||||
|
@ -1892,6 +1892,16 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
|
||||
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
|
||||
TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer,
|
||||
TyKind::AnonAdt(item_id) => {
|
||||
let path = external_path(
|
||||
cx,
|
||||
item_id.owner_id.def_id.to_def_id(),
|
||||
false,
|
||||
ThinVec::new(),
|
||||
ty::Binder::dummy(ty::GenericArgs::empty()),
|
||||
);
|
||||
Type::Path { path }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1511,6 +1511,10 @@ pub(crate) enum Type {
|
||||
|
||||
/// An `impl Trait`: `impl TraitA + TraitB + ...`
|
||||
ImplTrait(Vec<GenericBound>),
|
||||
// /// An anonymous struct type i.e. `struct { foo: Type }`
|
||||
// AnonStruct(VariantStruct),
|
||||
// /// An anonymous union type i.e. `union { bar: Type }`
|
||||
// AnonUnion(VariantStruct),
|
||||
}
|
||||
|
||||
impl Type {
|
||||
|
@ -831,6 +831,7 @@ fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self {
|
||||
| TyKind::Typeof(..)
|
||||
| TyKind::TraitObject(..)
|
||||
| TyKind::InferDelegation(..)
|
||||
| TyKind::AnonAdt(..)
|
||||
| TyKind::Err(_) => Self::Reborrow,
|
||||
};
|
||||
}
|
||||
|
@ -515,6 +515,7 @@ pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
|
||||
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
|
||||
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
||||
(&TyKind::Infer, &TyKind::Infer) => true,
|
||||
(TyKind::AnonAdt(l_item_id), TyKind::AnonAdt(r_item_id)) => l_item_id == r_item_id,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -1108,7 +1109,7 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||
TyKind::Typeof(anon_const) => {
|
||||
self.hash_body(anon_const.body);
|
||||
},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) => {},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -806,8 +806,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
|
||||
ast::TyKind::Tup(ref items) => {
|
||||
rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
|
||||
}
|
||||
ast::TyKind::AnonStruct(_) => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::AnonUnion(_) => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::AnonStruct(..) => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::AnonUnion(..) => Some(context.snippet(self.span).to_owned()),
|
||||
ast::TyKind::Path(ref q_self, ref path) => {
|
||||
rewrite_path(context, PathContext::Type, q_self, path, shape)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ struct Foo {
|
||||
foo: u8,
|
||||
_: union { //~ ERROR unnamed fields are not yet fully implemented [E0658]
|
||||
//~^ ERROR unnamed fields are not yet fully implemented [E0658]
|
||||
//~| ERROR anonymous unions are unimplemented
|
||||
bar: u8,
|
||||
baz: u16
|
||||
}
|
||||
@ -12,7 +11,6 @@ union Bar {
|
||||
foobar: u8,
|
||||
_: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658]
|
||||
//~^ ERROR unnamed fields are not yet fully implemented [E0658]
|
||||
//~| ERROR anonymous structs are unimplemented
|
||||
foobaz: u8,
|
||||
barbaz: u16
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ error[E0658]: unnamed fields are not yet fully implemented
|
||||
LL | _: union {
|
||||
| ________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | bar: u8,
|
||||
LL | | baz: u16
|
||||
LL | | }
|
||||
@ -25,7 +24,7 @@ LL | | }
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unnamed fields are not yet fully implemented
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:13:5
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:12:5
|
||||
|
|
||||
LL | _: struct {
|
||||
| ^
|
||||
@ -35,12 +34,11 @@ LL | _: struct {
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unnamed fields are not yet fully implemented
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:13:8
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:12:8
|
||||
|
|
||||
LL | _: struct {
|
||||
| ________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | foobaz: u8,
|
||||
LL | | barbaz: u16
|
||||
LL | | }
|
||||
@ -51,7 +49,7 @@ LL | | }
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unnamed fields are not yet fully implemented
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:23:5
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:21:5
|
||||
|
|
||||
LL | _: S
|
||||
| ^
|
||||
@ -60,30 +58,6 @@ LL | _: S
|
||||
= help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:3:8
|
||||
|
|
||||
LL | _: union {
|
||||
| ________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | bar: u8,
|
||||
LL | | baz: u16
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/feature-gate-unnamed_fields.rs:13:8
|
||||
|
|
||||
LL | _: struct {
|
||||
| ________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | foobaz: u8,
|
||||
LL | | barbaz: u16
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -3,9 +3,7 @@
|
||||
|
||||
struct F {
|
||||
field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR anonymous structs are unimplemented
|
||||
_: struct { field: u8 },
|
||||
//~^ ERROR anonymous structs are unimplemented
|
||||
}
|
||||
|
||||
struct G {
|
||||
@ -14,9 +12,7 @@ struct G {
|
||||
|
||||
union H {
|
||||
field: struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR anonymous structs are unimplemented
|
||||
_: struct { field: u8 },
|
||||
//~^ ERROR anonymous structs are unimplemented
|
||||
}
|
||||
|
||||
union I {
|
||||
@ -27,7 +23,6 @@ enum K {
|
||||
M {
|
||||
_ : struct { field: u8 }, //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR unnamed fields are not allowed outside of structs or unions
|
||||
//~| ERROR anonymous structs are unimplemented
|
||||
},
|
||||
N {
|
||||
_ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions
|
||||
|
@ -5,25 +5,25 @@ LL | field: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
|
||||
|
||||
error: unnamed fields can only have struct or union types
|
||||
--> $DIR/restrict_anonymous_structs.rs:12:5
|
||||
--> $DIR/restrict_anonymous_structs.rs:10:5
|
||||
|
|
||||
LL | _: (u8, u8),
|
||||
| ^ -------- not a struct or union
|
||||
|
||||
error: anonymous structs are not allowed outside of unnamed struct or union fields
|
||||
--> $DIR/restrict_anonymous_structs.rs:16:12
|
||||
--> $DIR/restrict_anonymous_structs.rs:14:12
|
||||
|
|
||||
LL | field: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
|
||||
|
||||
error: unnamed fields can only have struct or union types
|
||||
--> $DIR/restrict_anonymous_structs.rs:23:5
|
||||
--> $DIR/restrict_anonymous_structs.rs:19:5
|
||||
|
|
||||
LL | _: (u8, u8),
|
||||
| ^ -------- not a struct or union
|
||||
|
||||
error: unnamed fields are not allowed outside of structs or unions
|
||||
--> $DIR/restrict_anonymous_structs.rs:28:9
|
||||
--> $DIR/restrict_anonymous_structs.rs:24:9
|
||||
|
|
||||
LL | _ : struct { field: u8 },
|
||||
| -^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,48 +31,18 @@ LL | _ : struct { field: u8 },
|
||||
| unnamed field declared here
|
||||
|
||||
error: anonymous structs are not allowed outside of unnamed struct or union fields
|
||||
--> $DIR/restrict_anonymous_structs.rs:28:13
|
||||
--> $DIR/restrict_anonymous_structs.rs:24:13
|
||||
|
|
||||
LL | _ : struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
|
||||
|
||||
error: unnamed fields are not allowed outside of structs or unions
|
||||
--> $DIR/restrict_anonymous_structs.rs:33:9
|
||||
--> $DIR/restrict_anonymous_structs.rs:28:9
|
||||
|
|
||||
LL | _ : u8,
|
||||
| -^^^^^
|
||||
| |
|
||||
| unnamed field declared here
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/restrict_anonymous_structs.rs:5:12
|
||||
|
|
||||
LL | field: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/restrict_anonymous_structs.rs:7:8
|
||||
|
|
||||
LL | _: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/restrict_anonymous_structs.rs:16:12
|
||||
|
|
||||
LL | field: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/restrict_anonymous_structs.rs:18:8
|
||||
|
|
||||
LL | _: struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous structs are unimplemented
|
||||
--> $DIR/restrict_anonymous_structs.rs:28:13
|
||||
|
|
||||
LL | _ : struct { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
|
||||
struct F {
|
||||
field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR anonymous unions are unimplemented
|
||||
_: union { field: u8 },
|
||||
//~^ ERROR anonymous unions are unimplemented
|
||||
}
|
||||
|
||||
struct G {
|
||||
@ -14,9 +12,7 @@ struct G {
|
||||
|
||||
union H {
|
||||
field: union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR anonymous unions are unimplemented
|
||||
_: union { field: u8 },
|
||||
//~^ ERROR anonymous unions are unimplemented
|
||||
}
|
||||
|
||||
union I {
|
||||
@ -27,7 +23,6 @@ enum K {
|
||||
M {
|
||||
_ : union { field: u8 }, //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
|
||||
//~^ ERROR unnamed fields are not allowed outside of structs or unions
|
||||
//~| ERROR anonymous unions are unimplemented
|
||||
},
|
||||
N {
|
||||
_ : u8, //~ ERROR unnamed fields are not allowed outside of structs or unions
|
||||
|
@ -5,25 +5,25 @@ LL | field: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
|
||||
|
||||
error: unnamed fields can only have struct or union types
|
||||
--> $DIR/restrict_anonymous_unions.rs:12:5
|
||||
--> $DIR/restrict_anonymous_unions.rs:10:5
|
||||
|
|
||||
LL | _: (u8, u8),
|
||||
| ^ -------- not a struct or union
|
||||
|
||||
error: anonymous unions are not allowed outside of unnamed struct or union fields
|
||||
--> $DIR/restrict_anonymous_unions.rs:16:12
|
||||
--> $DIR/restrict_anonymous_unions.rs:14:12
|
||||
|
|
||||
LL | field: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
|
||||
|
||||
error: unnamed fields can only have struct or union types
|
||||
--> $DIR/restrict_anonymous_unions.rs:23:5
|
||||
--> $DIR/restrict_anonymous_unions.rs:19:5
|
||||
|
|
||||
LL | _: (u8, u8),
|
||||
| ^ -------- not a struct or union
|
||||
|
||||
error: unnamed fields are not allowed outside of structs or unions
|
||||
--> $DIR/restrict_anonymous_unions.rs:28:9
|
||||
--> $DIR/restrict_anonymous_unions.rs:24:9
|
||||
|
|
||||
LL | _ : union { field: u8 },
|
||||
| -^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,48 +31,18 @@ LL | _ : union { field: u8 },
|
||||
| unnamed field declared here
|
||||
|
||||
error: anonymous unions are not allowed outside of unnamed struct or union fields
|
||||
--> $DIR/restrict_anonymous_unions.rs:28:13
|
||||
--> $DIR/restrict_anonymous_unions.rs:24:13
|
||||
|
|
||||
LL | _ : union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
|
||||
|
||||
error: unnamed fields are not allowed outside of structs or unions
|
||||
--> $DIR/restrict_anonymous_unions.rs:33:9
|
||||
--> $DIR/restrict_anonymous_unions.rs:28:9
|
||||
|
|
||||
LL | _ : u8,
|
||||
| -^^^^^
|
||||
| |
|
||||
| unnamed field declared here
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/restrict_anonymous_unions.rs:5:12
|
||||
|
|
||||
LL | field: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/restrict_anonymous_unions.rs:7:8
|
||||
|
|
||||
LL | _: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/restrict_anonymous_unions.rs:16:12
|
||||
|
|
||||
LL | field: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/restrict_anonymous_unions.rs:18:8
|
||||
|
|
||||
LL | _: union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: anonymous unions are unimplemented
|
||||
--> $DIR/restrict_anonymous_unions.rs:28:13
|
||||
|
|
||||
LL | _ : union { field: u8 },
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user