diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 830417eea1a..691e3d0f8f9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn opt_item_name(self, item_index: DefIndex) -> Option { - self.def_key(item_index).disambiguated_data.data.get_opt_name() + let def_key = self.def_key(item_index); + def_key.disambiguated_data.data.get_opt_name().or_else(|| { + if def_key.disambiguated_data.data == DefPathData::Ctor { + let parent_index = def_key.parent.expect("no parent for a constructor"); + self.def_key(parent_index).disambiguated_data.data.get_opt_name() + } else { + None + } + }) } fn item_name(self, item_index: DefIndex) -> Symbol { @@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or_else(LazyArray::empty) .decode(self) - .map(|index| self.get_variant(&self.def_kind(index), index, did)) + .filter_map(|index| { + let kind = self.def_kind(index); + match kind { + DefKind::Ctor(..) => None, + _ => Some(self.get_variant(&kind, index, did)), + } + }) .collect() } else { std::iter::once(self.get_variant(&kind, item_id, did)).collect() @@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { callback(ModChild { ident, res, vis, span, macro_rules }); - // For non-re-export structs and variants add their constructors to children. - // Re-export lists automatically contain constructors when necessary. - match kind { - DefKind::Struct => { - if let Some((ctor_def_id, ctor_kind)) = - self.get_ctor_def_id_and_kind(child_index) - { - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); - let vis = self.get_visibility(ctor_def_id.index); - callback(ModChild { - ident, - res: ctor_res, - vis, - span, - macro_rules: false, - }); + // For non-reexport variants add their fictive constructors to children. + // Braced variants, unlike structs, generate unusable names in value namespace, + // they are reserved for possible future use. It's ok to use the variant's id as + // a ctor id since an error will be reported on any use of such resolution anyway. + // Reexport lists automatically contain such constructors when necessary. + if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none() + { + let ctor_res = + Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id); + let mut vis = vis; + if vis.is_public() { + // For non-exhaustive variants lower the constructor visibility to + // within the crate. We only need this for fictive constructors, + // for other constructors correct visibilities + // were already encoded in metadata. + let mut attrs = self.get_item_attrs(def_id.index, sess); + if attrs.any(|item| item.has_name(sym::non_exhaustive)) { + vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX)); } } - DefKind::Variant => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let (ctor_def_id, ctor_kind) = self - .get_ctor_def_id_and_kind(child_index) - .unwrap_or((def_id, CtorKind::Fictive)); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis.is_public() { - // For non-exhaustive variants lower the constructor visibility to - // within the crate. We only need this for fictive constructors, - // for other constructors correct visibilities - // were already encoded in metadata. - let mut attrs = self.get_item_attrs(def_id.index, sess); - if attrs.any(|item| item.has_name(sym::non_exhaustive)) { - let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); - vis = ty::Visibility::Restricted(crate_def_id); - } - } - callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); - } - _ => {} + callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c019211a948..61e84a5a01d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1335,6 +1335,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, + hir::ItemKind::Struct(ref vdata, _) => { + yield item_id.def_id.def_id.local_def_index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_hir_id) = vdata.ctor_hir_id() { + yield tcx.hir().local_def_id(ctor_hir_id).local_def_index; + } + } _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { yield item_id.def_id.def_id.local_def_index; } @@ -1646,12 +1653,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <- - self.tcx.adt_def(def_id).variants().iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - }) - ), + hir::ItemKind::Enum(..) => { + record_array!(self.tables.children[def_id] <- iter::from_generator(|| + for variant in tcx.adt_def(def_id).variants() { + yield variant.def_id.index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_def_id) = variant.ctor_def_id { + yield ctor_def_id.index; + } + } + )) + } hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { record_array!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {