use syntax_pos::{DUMMY_SP, Span};
use smallvec;
+use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
impl GenericParamDef {
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
- match self.kind {
- GenericParamDefKind::Lifetime => {
- ty::EarlyBoundRegion {
- def_id: self.def_id,
- index: self.index,
- name: self.name,
- }
+ if let GenericParamDefKind::Lifetime = self.kind {
+ ty::EarlyBoundRegion {
+ def_id: self.def_id,
+ index: self.index,
+ name: self.name,
}
- _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
+ } else {
+ bug!("cannot convert a non-lifetime parameter def to an early bound region")
}
}
pub fn to_bound_region(&self) -> ty::BoundRegion {
- match self.kind {
- GenericParamDefKind::Lifetime => {
- self.to_early_bound_region_data().to_bound_region()
- }
- _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
+ if let GenericParamDefKind::Lifetime = self.kind {
+ self.to_early_bound_region_data().to_bound_region()
+ } else {
+ bug!("cannot convert a non-lifetime parameter def to an early bound region")
}
}
}
}
} else {
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
- .region_param(param, tcx)
+ .region_param(param, tcx)
}
}
}
} else {
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
- .type_param(param, tcx)
+ .type_param(param, tcx)
}
}
}
}
};
- // The only reason to collect into a vector here is that I was
+ // FIXME: The only reason to collect into a vector here is that I was
// too lazy to make the full (somewhat complicated) iterator
// type that would be needed here. But I wanted this fn to
// return an iterator conceptually, rather than a `Vec`, so as
/// "Universes" are used during type- and trait-checking in the
/// presence of `for<..>` binders to control what sets of names are
/// visible. Universes are arranged into a tree: the root universe
-/// contains names that are always visible. But when you enter into
-/// some subuniverse, then it may add names that are only visible
-/// within that subtree (but it can still name the names of its
-/// ancestor universes).
+/// contains names that are always visible. Each child then adds a new
+/// set of names that are visible, in addition to those of its parent.
+/// We say that the child universe "extends" the parent universe with
+/// new names.
///
/// To make this more concrete, consider this program:
///
/// ```
///
/// The struct name `Foo` is in the root universe U0. But the type
-/// parameter `T`, introduced on `bar`, is in a subuniverse U1 --
-/// i.e., within `bar`, we can name both `T` and `Foo`, but outside of
-/// `bar`, we cannot name `T`. Then, within the type of `y`, the
-/// region `'a` is in a subuniverse U2 of U1, because we can name it
-/// inside the fn type but not outside.
+/// parameter `T`, introduced on `bar`, is in an extended universe U1
+/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
+/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
+/// region `'a` is in a universe U2 that extends U1, because we can
+/// name it inside the fn type but not outside.
///
/// Universes are used to do type- and trait-checking around these
/// "forall" binders (also called **universal quantification**). The
/// declared, but a type name in a non-zero universe is a placeholder
/// type -- an idealized representative of "types in general" that we
/// use for checking generic functions.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct UniverseIndex(u32);
-
-impl UniverseIndex {
- /// The root universe, where things that the user defined are
- /// visible.
- pub const ROOT: Self = UniverseIndex(0);
+newtype_index! {
+ pub struct UniverseIndex {
+ DEBUG_FORMAT = "U{}",
+ }
+}
- /// The "max universe" -- this isn't really a valid universe, but
- /// it's useful sometimes as a "starting value" when you are
- /// taking the minimum of a (non-empty!) set of universes.
- pub const MAX: Self = UniverseIndex(::std::u32::MAX);
+impl_stable_hash_for!(struct UniverseIndex { private });
- /// Creates a universe index from the given integer. Not to be
- /// used lightly lest you pick a bad value. But sometimes we
- /// convert universe indices into integers and back for various
- /// reasons.
- pub fn from_u32(index: u32) -> Self {
- UniverseIndex(index)
- }
+impl UniverseIndex {
+ pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0);
- /// A "subuniverse" corresponds to being inside a `forall` quantifier.
- /// So, for example, suppose we have this type in universe `U`:
+ /// Returns the "next" universe index in order -- this new index
+ /// is considered to extend all previous universes. This
+ /// corresponds to entering a `forall` quantifier. So, for
+ /// example, suppose we have this type in universe `U`:
///
/// ```
/// for<'a> fn(&'a u32)
/// ```
///
/// Once we "enter" into this `for<'a>` quantifier, we are in a
- /// subuniverse of `U` -- in this new universe, we can name the
- /// region `'a`, but that region was not nameable from `U` because
- /// it was not in scope there.
- pub fn subuniverse(self) -> UniverseIndex {
- UniverseIndex(self.0.checked_add(1).unwrap())
- }
-
- /// True if the names in this universe are a subset of the names in `other`.
- pub fn is_subset_of(self, other: UniverseIndex) -> bool {
- self.0 <= other.0
- }
-
- pub fn as_u32(&self) -> u32 {
- self.0
+ /// new universe that extends `U` -- in this new universe, we can
+ /// name the region `'a`, but that region was not nameable from
+ /// `U` because it was not in scope there.
+ pub fn next_universe(self) -> UniverseIndex {
+ UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
}
- pub fn as_usize(&self) -> usize {
- self.0 as usize
- }
-}
-
-impl fmt::Debug for UniverseIndex {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(fmt, "U{}", self.as_u32())
- }
-}
-
-impl From<u32> for UniverseIndex {
- fn from(index: u32) -> Self {
- UniverseIndex(index)
+ /// True if `self` can name a name from `other` -- in other words,
+ /// if the set of names in `self` is a superset of those in
+ /// `other`.
+ pub fn can_name(self, other: UniverseIndex) -> bool {
+ self.private >= other.private
}
}
const IS_FUNDAMENTAL = 1 << 2;
const IS_UNION = 1 << 3;
const IS_BOX = 1 << 4;
+ /// Indicates whether the type is an `Arc`.
+ const IS_ARC = 1 << 5;
+ /// Indicates whether the type is an `Rc`.
+ const IS_RC = 1 << 6;
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
/// (i.e., this flag is never set unless this ADT is an enum).
- const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 5;
+ const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
}
}
if Some(did) == tcx.lang_items().owned_box() {
flags = flags | AdtFlags::IS_BOX;
}
+ if Some(did) == tcx.lang_items().arc() {
+ flags = flags | AdtFlags::IS_ARC;
+ }
+ if Some(did) == tcx.lang_items().rc() {
+ flags = flags | AdtFlags::IS_RC;
+ }
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
}
+ /// Returns `true` if this is `Arc<T>`.
+ pub fn is_arc(&self) -> bool {
+ self.flags.intersects(AdtFlags::IS_ARC)
+ }
+
+ /// Returns `true` if this is `Rc<T>`.
+ pub fn is_rc(&self) -> bool {
+ self.flags.intersects(AdtFlags::IS_RC)
+ }
+
/// Returns true if this is Box<T>.
#[inline]
pub fn is_box(&self) -> bool {
if !expr_did.is_local() {
span_bug!(tcx.def_span(expr_did),
"variant discriminant evaluation succeeded \
- in its crate but failed locally");
+ in its crate but failed locally");
}
None
}
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
ty, adt_tys);
adt_tys.iter()
- .map(|ty| ty.subst(tcx, substs))
- .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
- .collect()
+ .map(|ty| ty.subst(tcx, substs))
+ .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
+ .collect()
}
Projection(..) | Opaque(..) => {
}
}
-fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> AssociatedItem
-{
+fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> AssociatedItem {
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let parent_id = tcx.hir.get_parent(id);
let parent_def_id = tcx.hir.local_def_id(parent_id);
/// See `ParamEnv` struct def'n for details.
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
- -> ParamEnv<'tcx> {
-
+ -> ParamEnv<'tcx>
+{
// The param_env of an impl Trait type is its defining function's param_env
if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
return param_env(tcx, parent);