};
let variant_def = match self.cat {
Categorization::Downcast(_, variant_did) => {
- adt_def.variant_with_variant_id(variant_did)
+ adt_def.variant_with_id(variant_did)
}
_ => {
assert_eq!(adt_def.variants.len(), 1);
AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
let variant_def = &adt_def.variants[variant];
- let did = variant_def.variant_did_or_parent_struct_did();
let f = &mut *fmt;
ty::tls::with(|tcx| {
let substs = tcx.lift(&substs).expect("could not lift for printing");
FmtPrinter::new(tcx, f, Namespace::ValueNS)
- .print_def_path(did, substs)?;
+ .print_def_path(variant_def.def_id, substs)?;
Ok(())
})?;
fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
ty.uninhabited_from(self)
}
-
- pub fn is_enum_variant_uninhabited_from(self,
- module: DefId,
- variant: &'tcx VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- self.variant_inhabitedness_forest(variant, substs).contains(self, module)
- }
-
- pub fn is_variant_uninhabited_from_all_modules(self,
- variant: &'tcx VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- !self.variant_inhabitedness_forest(variant, substs).is_empty()
- }
-
- fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>)
- -> DefIdForest {
- // Determine the ADT kind:
- let adt_def_id = self.adt_def_id_of_variant(variant);
- let adt_kind = self.adt_def(adt_def_id).adt_kind();
-
- // Compute inhabitedness forest:
- variant.uninhabited_from(self, substs, adt_kind)
- }
}
impl<'a, 'gcx, 'tcx> AdtDef {
impl<'a, 'gcx, 'tcx> VariantDef {
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
- fn uninhabited_from(
+ pub fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: SubstsRef<'tcx>,
/// Definition of a variant -- a struct's fields or a enum variant.
#[derive(Debug)]
pub struct VariantDef {
- /// `DefId` that identifies this enum variant. If this `VariantDef` is part of a struct or
- /// union then this is `None`.
- variant_did: Option<DefId>,
- /// `DefId` that identifies this enum variant or struct's constructor. If this is a
- /// `Struct`-variant then this is `None`.
- ctor_did: Option<DefId>,
+ /// `DefId` that identifies the variant itself.
+ /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
+ pub def_id: DefId,
+ /// `DefId` that identifies the variant's constructor.
+ /// If this variant is a struct variant, then this is `None`.
+ pub ctor_def_id: Option<DefId>,
/// Variant or struct name.
pub ident: Ident,
/// Discriminant of this variant.
pub fields: Vec<FieldDef>,
/// Type of constructor of variant.
pub ctor_kind: CtorKind,
- /// `DefId` of the parent `AdtDef` representing the struct or enum. This is required as there
- /// is a valid scenario where this type represents a `Struct`-struct and both `ctor_did` and
- /// `variant_did` would be `None` and we would still want a way to get back to the original
- /// `AdtDef`.
- parent_did: DefId,
/// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
/// Recovered?
tcx: TyCtxt<'a, 'gcx, 'tcx>,
ident: Ident,
variant_did: Option<DefId>,
- ctor_did: Option<DefId>,
+ ctor_def_id: Option<DefId>,
discr: VariantDiscr,
fields: Vec<FieldDef>,
ctor_kind: CtorKind,
recovered: bool,
) -> Self {
debug!(
- "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_did = {:?}, discr = {:?},
+ "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
- ident, variant_did, ctor_did, discr, fields, ctor_kind, adt_kind, parent_did,
+ ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
}
VariantDef {
- variant_did,
- ctor_did,
+ def_id: variant_did.unwrap_or(parent_did),
+ ctor_def_id,
ident,
discr,
fields,
ctor_kind,
flags,
- parent_did,
recovered,
}
}
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}
-
- /// Returns `true` if this `VariantDef` represents a enum's variant.
- #[inline]
- pub fn is_enum_variant(&self) -> bool {
- self.variant_did.is_some()
- }
-
- /// Returns `true` if this `VariantDef` represents a struct.
- #[inline]
- pub fn is_struct(&self) -> bool {
- !self.is_enum_variant()
- }
-
- /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant, or
- /// returns the `DefId` of the parent struct.
- #[inline]
- pub fn variant_did_or_parent_struct_did(&self) -> DefId {
- self.variant_did.unwrap_or(self.parent_did)
- }
-
- /// Returns `true` if the variant is defined in the local crate.
- #[inline]
- pub fn is_local(&self) -> bool {
- self.variant_did_or_parent_struct_did().krate == LOCAL_CRATE
- }
-
- /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant or
- /// panics.
- #[inline]
- pub fn variant_did(&self) -> DefId {
- self.variant_did.expect("enum variant without a variant id")
- }
-
- /// Returns the `DefId` of this variant's constructor if this is a unit or
- /// tuple-variant/struct.
- #[inline]
- pub fn ctor_did(&self) -> Option<DefId> {
- self.ctor_did
- }
-
- /// Returns the `AdtDef` representing the struct or enum associated with this `VariantDef`.
- #[inline]
- pub fn adt_def(&self, tcx: TyCtxt<'a, 'tcx, 'gcx>) -> &'tcx AdtDef {
- tcx.adt_def(self.parent_did)
- }
}
impl_stable_hash_for!(struct VariantDef {
- variant_did,
- ctor_did,
+ def_id,
+ ctor_def_id,
ident -> (ident.name),
discr,
fields,
ctor_kind,
flags,
- parent_did,
recovered
});
AdtKind::Struct => AdtFlags::IS_STRUCT,
};
- if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_did.is_some() {
+ if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() {
flags |= AdtFlags::HAS_CTOR;
}
self.variants.iter().all(|v| v.fields.is_empty())
}
- pub fn variant_with_variant_id(&self, vid: DefId) -> &VariantDef {
- self.variants
- .iter()
- .find(|v| v.variant_did.map(|did| did == vid).unwrap_or(false))
- .expect("variant_with_variant_id: unknown variant")
+ pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
+ self.variants.iter().find(|v| v.def_id == vid)
+ .expect("variant_with_id: unknown variant")
}
pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
- self.variants
- .iter()
- .find(|v| v.ctor_did.map(|did| did == cid).unwrap_or(false))
+ self.variants.iter().find(|v| v.ctor_def_id == Some(cid))
.expect("variant_with_ctor_id: unknown variant")
}
- pub fn variant_index_with_variant_id(&self, vid: DefId) -> VariantIdx {
- self.variants
- .iter_enumerated()
- .find(|(_, v)| v.variant_did.map(|did| did == vid).unwrap_or(false))
- .expect("variant_index_with_variant_id: unknown variant")
- .0
+ pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
+ self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid)
+ .expect("variant_index_with_id: unknown variant").0
}
pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
- self.variants
- .iter_enumerated()
- .find(|(_, v)| v.ctor_did.map(|did| did == cid).unwrap_or(false))
- .expect("variant_index_with_ctor_id: unknown variant")
- .0
- }
-
- pub fn variant_index_with_ctor_or_variant_id(&self, id: DefId) -> VariantIdx {
- self.variants
- .iter_enumerated()
- .find(|(_, v)| {
- let ctor = v.ctor_did.map(|did| did == id);
- let variant = v.variant_did.map(|did| did == id);
- ctor.or(variant).unwrap_or(false)
- })
- .expect("variant_index_with_ctor_or_variant_id: unknown variant")
- .0
+ self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid))
+ .expect("variant_index_with_ctor_id: unknown variant").0
}
pub fn variant_of_def(&self, def: Def) -> &VariantDef {
match def {
- Def::Variant(vid) => self.variant_with_variant_id(vid),
+ Def::Variant(vid) => self.variant_with_id(vid),
Def::Ctor(hir::CtorOf::Variant, cid, ..) => self.variant_with_ctor_id(cid),
Def::Struct(..) | Def::Ctor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
variant.fields.iter().position(|field| {
- let did = variant.variant_did.unwrap_or(variant.parent_did);
- self.adjust_ident(ident, did, hir::DUMMY_HIR_ID).0 == field.ident.modern()
+ self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern()
})
}
match def {
Def::Variant(did) => {
let enum_did = self.parent(did).unwrap();
- self.adt_def(enum_did).variant_with_variant_id(did)
+ self.adt_def(enum_did).variant_with_id(did)
}
Def::Struct(did) | Def::Union(did) => {
self.adt_def(did).non_enum_variant()
}
}
- /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part.
- pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId {
- variant_def.parent_did
- }
-
pub fn item_name(self, id: DefId) -> InternedString {
if id.index == CRATE_DEF_INDEX {
self.original_crate_name(id.krate).as_interned_str()
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
let variant = &def.variants[index];
- let def_id = variant.variant_did();
+ let def_id = variant.def_id;
debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
let data = VariantData {
ctor_kind: variant.ctor_kind,
discr: variant.discr,
- ctor: variant.ctor_did().map(|did| did.index),
+ ctor: variant.ctor_def_id.map(|did| did.index),
ctor_sig: None,
};
let tcx = self.tcx;
let def = tcx.adt_def(enum_did);
let variant = &def.variants[index];
- let def_id = variant.ctor_did().unwrap();
+ let def_id = variant.ctor_def_id.unwrap();
debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
let data = VariantData {
let def_id = field.did;
debug!("IsolatedEncoder::encode_field({:?})", def_id);
- let variant_id = tcx.hir()
- .as_local_hir_id(variant.variant_did_or_parent_struct_did())
- .unwrap();
+ let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
let variant_data = tcx.hir().expect_variant_data(variant_id);
Entry {
hir::ItemKind::Enum(..) => {
let def = self.tcx.adt_def(def_id);
self.lazy_seq(def.variants.iter().map(|v| {
- let did = v.variant_did();
- assert!(did.is_local());
- did.index
+ assert!(v.def_id.is_local());
+ v.def_id.index
}))
}
hir::ItemKind::Struct(..) |
let def = self.tcx.adt_def(def_id);
for (i, variant) in def.variants.iter_enumerated() {
- self.record(variant.variant_did(),
+ self.record(variant.def_id,
IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i)));
- if let Some(ctor_hir_did) = variant.ctor_did() {
- self.record(ctor_hir_did,
+ if let Some(ctor_def_id) = variant.ctor_def_id {
+ self.record(ctor_def_id,
IsolatedEncoder::encode_enum_variant_ctor,
(def_id, Untracked(i)));
}
i == variant_index || {
self.hir.tcx().features().never_type &&
self.hir.tcx().features().exhaustive_patterns &&
- self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
+ !v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
});
if irrefutable {
Def::Variant(variant_id) => {
assert!(base.is_none());
- let index = adt.variant_index_with_variant_id(variant_id);
+ let index = adt.variant_index_with_id(variant_id);
let user_provided_types = cx.tables().user_provided_types();
let user_ty = user_provided_types.get(expr.hir_id)
.map(|u_ty| *u_ty);
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
-use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
use rustc::mir::Field;
_ => false,
}
}
-
- fn is_variant_uninhabited(&self,
- variant: &'tcx ty::VariantDef,
- substs: SubstsRef<'tcx>)
- -> bool
- {
- if self.tcx.features().exhaustive_patterns {
- self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
- } else {
- false
- }
- }
}
#[derive(Clone, Debug, PartialEq)]
-pub enum Constructor<'tcx> {
+enum Constructor<'tcx> {
/// The constructor of all patterns that don't vary by constructor,
/// e.g., struct patterns and fixed-length arrays.
Single,
adt: &'tcx ty::AdtDef,
) -> VariantIdx {
match self {
- &Variant(id) => adt.variant_index_with_ctor_or_variant_id(id),
+ &Variant(id) => adt.variant_index_with_id(id),
&Single => {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
ty::Adt(def, substs) if def.is_enum() => {
def.variants.iter()
- .filter(|v| !cx.is_variant_uninhabited(v, substs))
- .map(|v| v.ctor_did().map_or_else(|| Variant(v.variant_did()), |did| Variant(did)))
+ .filter(|v| {
+ !cx.tcx.features().exhaustive_patterns ||
+ !v.uninhabited_from(cx.tcx, substs, def.adt_kind()).contains(cx.tcx, cx.module)
+ })
+ .map(|v| Variant(v.def_id))
.collect()
}
ty::Char => {
PatternKind::Binding { .. } | PatternKind::Wild => None,
PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
PatternKind::Variant { adt_def, variant_index, .. } => {
- let variant = &adt_def.variants[variant_index];
- Some(variant.ctor_did()
- .map_or_else(|| vec![Variant(variant.variant_did())], |did| vec![Variant(did)]))
+ Some(vec![Variant(adt_def.variants[variant_index].def_id)])
}
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
- variant.ctor_did()
- .map(|did| Variant(did))
- .or_else(|| Some(Variant(variant.variant_did())))
+ Some(Variant(variant.def_id))
.filter(|variant_constructor| variant_constructor == constructor)
.map(|_| patterns_for_variant(subpatterns, wild_patterns))
}
PatternKind::Variant {
adt_def,
substs,
- variant_index: adt_def.variant_index_with_variant_id(variant_id),
+ variant_index: adt_def.variant_index_with_id(variant_id),
subpatterns,
}
} else {
tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
});
if let Some(variant_def) = variant_def {
- let did = variant_def.variant_did();
- let def = Def::Variant(did);
+ let def = Def::Variant(variant_def.def_id);
if permit_variants {
check_type_alias_enum_variants_enabled(tcx, span);
- tcx.check_stability(did, Some(hir_ref_id), span);
+ tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
return (qself_ty, def);
} else {
variant_resolution = Some(def);
let mut inexistent_fields = vec![];
// Typecheck each field.
for &Spanned { node: ref field, span } in fields {
- let ident = tcx.adjust_ident(
- field.ident, variant.variant_did_or_parent_struct_did(), self.body_id).0;
+ let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
struct_span_err!(tcx.sess, span, E0025,
.join(", ")), "these", "s")
};
let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
- let did = variant.variant_did_or_parent_struct_did();
let mut err = struct_span_err!(tcx.sess,
spans,
E0026,
"{} `{}` does not have {}",
kind_name,
- tcx.def_path_str(did),
+ tcx.def_path_str(variant.def_id),
field_names);
if let Some((span, ident)) = inexistent_fields.last() {
err.span_label(*span,
format!("{} `{}` does not have {} field{}",
kind_name,
- tcx.def_path_str(did),
+ tcx.def_path_str(variant.def_id),
t,
plural));
if plural == "" {
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) {
- let variant_path = self.tcx.def_path_str(variant.variant_did());
+ let variant_path = self.tcx.def_path_str(variant.def_id);
// FIXME #56861: DRYer prelude filtering
Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
} else {
if let Some(variant_def) = variant_def {
check_type_alias_enum_variants_enabled(tcx, span);
- let def = if let Some(ctor_did) = variant_def.ctor_did() {
- Def::Ctor(hir::CtorOf::Variant, ctor_did, variant_def.ctor_kind)
+ let def = if let Some(ctor_def_id) = variant_def.ctor_def_id {
+ Def::Ctor(hir::CtorOf::Variant, ctor_def_id, variant_def.ctor_kind)
} else {
// Normally, there do not exist any `Def::Ctor` for `Struct`-variants but
// in this case, we can get better error messages as diagnostics will
// specialize the message around a `CtorKind::Fictive`.
- Def::Ctor(hir::CtorOf::Variant, variant_def.variant_did(),
+ Def::Ctor(hir::CtorOf::Variant, variant_def.def_id,
hir::def::CtorKind::Fictive)
};
for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
// Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
- let variant_did = def.variants[VariantIdx::new(i)].variant_did();
+ let variant_did = def.variants[VariantIdx::new(i)].def_id;
let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap();
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
let i_span = match variant_i.node.disr_expr {
let names = variant.fields.iter().filter_map(|field| {
// ignore already set fields and private fields from non-local crates
if skip.iter().any(|x| *x == field.ident.as_str()) ||
- (!variant.is_local() && field.vis != Visibility::Public)
+ (!variant.def_id.is_local() && field.vis != Visibility::Public)
{
None
} else {
fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
variant.fields.iter().filter(|field| {
- let did = variant.variant_did_or_parent_struct_did();
- let def_scope = self.tcx.adjust_ident(field.ident, did, self.body_id).1;
+ let def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1;
field.vis.is_accessible_from(def_scope, self.tcx)
})
.map(|field| field.ident.name)
// Type-check each field.
for field in ast_fields {
- let ident = tcx.adjust_ident(
- field.ident, variant.variant_did_or_parent_struct_did(), self.body_id).0;
+ let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
self.write_field_index(field.hir_id, i);
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
- let ctor_did = variant.ctor_did().unwrap();
- let def = Def::Ctor(hir::CtorOf::Struct, ctor_did, variant.ctor_kind);
- (def, ctor_did, tcx.type_of(ctor_did))
+ let ctor_def_id = variant.ctor_def_id.unwrap();
+ let def = Def::Ctor(hir::CtorOf::Struct, ctor_def_id, variant.ctor_kind);
+ (def, ctor_def_id, tcx.type_of(ctor_def_id))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
})
}
};
- let did = self.variant_did_or_parent_struct_did();
Item {
name: Some(self.ident.clean(cx)),
- attrs: inline::load_attrs(cx, did),
- source: cx.tcx.def_span(did).clean(cx),
+ attrs: inline::load_attrs(cx, self.def_id),
+ source: cx.tcx.def_span(self.def_id).clean(cx),
visibility: Some(Inherited),
- def_id: did,
+ def_id: self.def_id,
inner: VariantItem(Variant { kind }),
- stability: get_stability(cx, did),
- deprecation: get_deprecation(cx, did),
+ stability: get_stability(cx, self.def_id),
+ deprecation: get_deprecation(cx, self.def_id),
}
}
}