use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
use crate::ty::util::{Discr, IntTypeExt};
use crate::ty::walk::TypeWalker;
+use rustc_ast::ast::{self, Ident, Name};
+use rustc_ast::node_id::{NodeId, NodeMap, NodeSet};
+use rustc_attr as attr;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::{GlobMap, Node, TraitMap};
+use rustc_hir::{Constness, GlobMap, Node, TraitMap};
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_serialize::{self, Encodable, Encoder};
-use rustc_session::node_id::{NodeMap, NodeSet};
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use rustc_target::abi::Align;
-use smallvec;
+
use std::cell::RefCell;
use std::cmp::{self, Ordering};
use std::fmt;
use std::ops::Range;
use std::slice;
use std::{mem, ptr};
-use syntax::ast::{self, Constness, Ident, Name, NodeId};
-use syntax::attr;
pub use self::sty::BoundRegion::*;
pub use self::sty::InferTy::*;
CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckTables,
};
+pub use self::instance::RESOLVE_INSTANCE;
pub use self::instance::{Instance, InstanceDef};
pub use self::trait_def::TraitDef;
pub definitions: hir_map::Definitions,
pub cstore: Box<CrateStoreDyn>,
pub extern_crate_map: NodeMap<CrateNum>,
- pub trait_map: TraitMap,
+ pub trait_map: TraitMap<NodeId>,
pub maybe_unused_trait_imports: NodeSet,
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
pub export_map: ExportMap<NodeId>,
ty::AssocKind::Const => "associated constant",
}
}
+
+ pub fn namespace(&self) -> Namespace {
+ match *self {
+ ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::TypeNS,
+ ty::AssocKind::Const | ty::AssocKind::Method => Namespace::ValueNS,
+ }
+ }
}
impl AssocItem {
}
}
+/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
+///
+/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
+/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
+/// done only on items with the same name.
+#[derive(Debug, Clone, PartialEq, HashStable)]
+pub struct AssociatedItems {
+ items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
+}
+
+impl AssociatedItems {
+ /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
+ pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
+ let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect();
+ AssociatedItems { items }
+ }
+
+ /// Returns a slice of associated items in the order they were defined.
+ ///
+ /// New code should avoid relying on definition order. If you need a particular associated item
+ /// for a known trait, make that trait a lang item instead of indexing this array.
+ pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
+ self.items.iter().map(|(_, v)| v)
+ }
+
+ /// Returns an iterator over all associated items with the given name, ignoring hygiene.
+ pub fn filter_by_name_unhygienic(
+ &self,
+ name: Symbol,
+ ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
+ self.items.get_by_key(&name)
+ }
+
+ /// Returns an iterator over all associated items with the given name.
+ ///
+ /// Multiple items may have the same name if they are in different `Namespace`s. For example,
+ /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*`
+ /// methods below if you know which item you are looking for.
+ pub fn filter_by_name(
+ &'a self,
+ tcx: TyCtxt<'a>,
+ ident: Ident,
+ parent_def_id: DefId,
+ ) -> impl 'a + Iterator<Item = &'a ty::AssocItem> {
+ self.filter_by_name_unhygienic(ident.name)
+ .filter(move |item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+ }
+
+ /// Returns the associated item with the given name and `AssocKind`, if one exists.
+ pub fn find_by_name_and_kind(
+ &self,
+ tcx: TyCtxt<'_>,
+ ident: Ident,
+ kind: AssocKind,
+ parent_def_id: DefId,
+ ) -> Option<&ty::AssocItem> {
+ self.filter_by_name_unhygienic(ident.name)
+ .filter(|item| item.kind == kind)
+ .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+ }
+
+ /// Returns the associated item with the given name in the given `Namespace`, if one exists.
+ pub fn find_by_name_and_namespace(
+ &self,
+ tcx: TyCtxt<'_>,
+ ident: Ident,
+ ns: Namespace,
+ parent_def_id: DefId,
+ ) -> Option<&ty::AssocItem> {
+ self.filter_by_name_unhygienic(ident.name)
+ .filter(|item| item.kind.namespace() == ns)
+ .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+ }
+}
+
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
pub enum Visibility {
/// Visible everywhere (including in other crates).
impl<'tcx> DefIdTree for TyCtxt<'tcx> {
fn parent(self, id: DefId) -> Option<DefId> {
- self.def_key(id).parent.map(|index| DefId { index: index, ..id })
+ self.def_key(id).parent.map(|index| DefId { index, ..id })
}
}
Res::Err => Visibility::Public,
def => Visibility::Restricted(def.def_id()),
},
- hir::VisibilityKind::Inherited => {
- Visibility::Restricted(tcx.hir().get_module_parent(id))
- }
+ hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)),
}
}
pub pos: usize,
}
-// Flags that we track on types. These flags are propagated upwards
-// through the type during type construction, so that we can quickly
-// check whether the type has various kinds of types in it without
-// recursing over the type itself.
bitflags! {
+ /// Flags that we track on types. These flags are propagated upwards
+ /// through the type during type construction, so that we can quickly check
+ /// whether the type has various kinds of types in it without recursing
+ /// over the type itself.
pub struct TypeFlags: u32 {
- const HAS_PARAMS = 1 << 0;
- const HAS_TY_INFER = 1 << 1;
- const HAS_RE_INFER = 1 << 2;
- const HAS_RE_PLACEHOLDER = 1 << 3;
-
- /// Does this have any `ReEarlyBound` regions? Used to
- /// determine whether substitition is required, since those
- /// represent regions that are bound in a `ty::Generics` and
- /// hence may be substituted.
- const HAS_RE_EARLY_BOUND = 1 << 4;
-
- /// Does this have any region that "appears free" in the type?
- /// Basically anything but `ReLateBound` and `ReErased`.
- const HAS_FREE_REGIONS = 1 << 5;
-
- /// Is an error type reachable?
- const HAS_TY_ERR = 1 << 6;
- const HAS_PROJECTION = 1 << 7;
-
- // FIXME: Rename this to the actual property since it's used for generators too
- const HAS_TY_CLOSURE = 1 << 8;
+ // Does this have parameters? Used to determine whether substitution is
+ // required.
+ /// Does this have [Param]?
+ const HAS_TY_PARAM = 1 << 0;
+ /// Does this have [ReEarlyBound]?
+ const HAS_RE_PARAM = 1 << 1;
+ /// Does this have [ConstKind::Param]?
+ const HAS_CT_PARAM = 1 << 2;
+
+ const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits
+ | TypeFlags::HAS_RE_PARAM.bits
+ | TypeFlags::HAS_CT_PARAM.bits;
+
+ /// Does this have [Infer]?
+ const HAS_TY_INFER = 1 << 3;
+ /// Does this have [ReVar]?
+ const HAS_RE_INFER = 1 << 4;
+ /// Does this have [ConstKind::Infer]?
+ const HAS_CT_INFER = 1 << 5;
+
+ /// Does this have inference variables? Used to determine whether
+ /// inference is required.
+ const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
+ | TypeFlags::HAS_RE_INFER.bits
+ | TypeFlags::HAS_CT_INFER.bits;
+
+ /// Does this have [Placeholder]?
+ const HAS_TY_PLACEHOLDER = 1 << 6;
+ /// Does this have [RePlaceholder]?
+ const HAS_RE_PLACEHOLDER = 1 << 7;
+ /// Does this have [ConstKind::Placeholder]?
+ const HAS_CT_PLACEHOLDER = 1 << 8;
+
+ /// `true` if there are "names" of regions and so forth
+ /// that are local to a particular fn/inferctxt
+ const HAS_FREE_LOCAL_REGIONS = 1 << 9;
/// `true` if there are "names" of types and regions and so forth
/// that are local to a particular fn
- const HAS_FREE_LOCAL_NAMES = 1 << 9;
+ const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits
+ | TypeFlags::HAS_CT_PARAM.bits
+ | TypeFlags::HAS_TY_INFER.bits
+ | TypeFlags::HAS_CT_INFER.bits
+ | TypeFlags::HAS_TY_PLACEHOLDER.bits
+ | TypeFlags::HAS_CT_PLACEHOLDER.bits
+ | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+
+ /// Does this have [Projection] or [UnnormalizedProjection]?
+ const HAS_TY_PROJECTION = 1 << 10;
+ /// Does this have [Opaque]?
+ const HAS_TY_OPAQUE = 1 << 11;
+ /// Does this have [ConstKind::Unevaluated]?
+ const HAS_CT_PROJECTION = 1 << 12;
+
+ /// Could this type be normalized further?
+ const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits
+ | TypeFlags::HAS_TY_OPAQUE.bits
+ | TypeFlags::HAS_CT_PROJECTION.bits;
/// Present if the type belongs in a local type context.
- /// Only set for Infer other than Fresh.
- const KEEP_IN_LOCAL_TCX = 1 << 10;
+ /// Set for placeholders and inference variables that are not "Fresh".
+ const KEEP_IN_LOCAL_TCX = 1 << 13;
- /// Does this have any `ReLateBound` regions? Used to check
- /// if a global bound is safe to evaluate.
- const HAS_RE_LATE_BOUND = 1 << 11;
+ /// Is an error type reachable?
+ const HAS_TY_ERR = 1 << 14;
- const HAS_TY_PLACEHOLDER = 1 << 12;
+ /// Does this have any region that "appears free" in the type?
+ /// Basically anything but [ReLateBound] and [ReErased].
+ const HAS_FREE_REGIONS = 1 << 15;
- const HAS_CT_INFER = 1 << 13;
- const HAS_CT_PLACEHOLDER = 1 << 14;
+ /// Does this have any [ReLateBound] regions? Used to check
+ /// if a global bound is safe to evaluate.
+ const HAS_RE_LATE_BOUND = 1 << 16;
- const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
- TypeFlags::HAS_RE_EARLY_BOUND.bits;
+ /// Does this have any [ReErased] regions?
+ const HAS_RE_ERASED = 1 << 17;
/// Flags representing the nominal content of a type,
/// computed by FlagsComputation. If you add a new nominal
/// flag, it should be added here too.
- const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits |
- TypeFlags::HAS_TY_INFER.bits |
- TypeFlags::HAS_RE_INFER.bits |
- TypeFlags::HAS_RE_PLACEHOLDER.bits |
- TypeFlags::HAS_RE_EARLY_BOUND.bits |
- TypeFlags::HAS_FREE_REGIONS.bits |
- TypeFlags::HAS_TY_ERR.bits |
- TypeFlags::HAS_PROJECTION.bits |
- TypeFlags::HAS_TY_CLOSURE.bits |
- TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
- TypeFlags::KEEP_IN_LOCAL_TCX.bits |
- TypeFlags::HAS_RE_LATE_BOUND.bits |
- TypeFlags::HAS_TY_PLACEHOLDER.bits |
- TypeFlags::HAS_CT_INFER.bits |
- TypeFlags::HAS_CT_PLACEHOLDER.bits;
+ const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits
+ | TypeFlags::HAS_RE_PARAM.bits
+ | TypeFlags::HAS_CT_PARAM.bits
+ | TypeFlags::HAS_TY_INFER.bits
+ | TypeFlags::HAS_RE_INFER.bits
+ | TypeFlags::HAS_CT_INFER.bits
+ | TypeFlags::HAS_TY_PLACEHOLDER.bits
+ | TypeFlags::HAS_RE_PLACEHOLDER.bits
+ | TypeFlags::HAS_CT_PLACEHOLDER.bits
+ | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
+ | TypeFlags::HAS_TY_PROJECTION.bits
+ | TypeFlags::HAS_TY_OPAQUE.bits
+ | TypeFlags::HAS_CT_PROJECTION.bits
+ | TypeFlags::KEEP_IN_LOCAL_TCX.bits
+ | TypeFlags::HAS_TY_ERR.bits
+ | TypeFlags::HAS_FREE_REGIONS.bits
+ | TypeFlags::HAS_RE_LATE_BOUND.bits
+ | TypeFlags::HAS_RE_ERASED.bits;
}
}
fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
- assert!(slice.len() != 0);
+ assert!(!slice.is_empty());
// Align up the size of the len (usize) field
let align = mem::align_of::<T>();
Const,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+impl GenericParamDefKind {
+ pub fn descr(&self) -> &'static str {
+ match self {
+ GenericParamDefKind::Lifetime => "lifetime",
+ GenericParamDefKind::Type { .. } => "type",
+ GenericParamDefKind::Const => "constant",
+ }
+ }
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct GenericParamDef {
pub name: Symbol,
pub def_id: DefId,
) -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(),
+ spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
}
}
tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
}
instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)));
+ instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
}
pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> {
if let Some(def_id) = self.parent {
tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
}
- instantiated.predicates.extend(self.predicates.iter().map(|&(p, _)| p))
+ instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p));
+ instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
}
pub fn instantiate_supertrait(
.iter()
.map(|(pred, _)| pred.subst_supertrait(tcx, poly_trait_ref))
.collect(),
+ spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
}
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(
- ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+ ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value }),
self.constness,
)
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(
- ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+ ty::Binder::dummy(ty::TraitPredicate { trait_ref: *self.value }),
self.constness,
)
}
#[derive(Clone, Debug, TypeFoldable)]
pub struct InstantiatedPredicates<'tcx> {
pub predicates: Vec<Predicate<'tcx>>,
+ pub spans: Vec<Span>,
}
impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn empty() -> InstantiatedPredicates<'tcx> {
- InstantiatedPredicates { predicates: vec![] }
+ InstantiatedPredicates { predicates: vec![], spans: vec![] }
}
pub fn is_empty(&self) -> bool {
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
Reveal::All => {
- if value.has_placeholders() || value.needs_infer() || value.has_param_types() {
- ParamEnvAnd { param_env: self, value }
- } else {
+ if value.is_global() {
ParamEnvAnd { param_env: self.without_caller_bounds(), value }
+ } else {
+ ParamEnvAnd { param_env: self, value }
}
}
}
const IS_STRUCT = 1 << 2;
/// Indicates whether the ADT is a struct and has a constructor.
const HAS_CTOR = 1 << 3;
- /// Indicates whether the type is a `PhantomData`.
+ /// Indicates whether the type is `PhantomData`.
const IS_PHANTOM_DATA = 1 << 4;
/// Indicates whether the type has a `#[fundamental]` attribute.
const IS_FUNDAMENTAL = 1 << 5;
- /// Indicates whether the type is a `Box`.
+ /// Indicates whether the type is `Box`.
const IS_BOX = 1 << 6;
+ /// Indicates whether the type is `ManuallyDrop`.
+ const IS_MANUALLY_DROP = 1 << 7;
+ // FIXME(matthewjasper) replace these with diagnostic items
/// Indicates whether the type is an `Arc`.
- const IS_ARC = 1 << 7;
+ const IS_ARC = 1 << 8;
/// Indicates whether the type is an `Rc`.
- const IS_RC = 1 << 8;
+ const IS_RC = 1 << 9;
/// 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 << 9;
+ const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 10;
}
}
const IS_TRANSPARENT = 1 << 2;
// Internal only for now. If true, don't reorder fields.
const IS_LINEAR = 1 << 3;
-
+ // If true, don't expose any niche to type's context.
+ const HIDE_NICHE = 1 << 4;
// Any of these flags being set prevent field reordering optimisation.
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits |
ReprFlags::IS_SIMD.bits |
ReprFlags::empty()
}
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
+ attr::ReprNoNiche => ReprFlags::HIDE_NICHE,
attr::ReprSimd => ReprFlags::IS_SIMD,
attr::ReprInt(i) => {
size = Some(i);
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
}
- ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags }
+ ReprOptions { int: size, align: max_align, pack: min_pack, flags }
}
#[inline]
pub fn linear(&self) -> bool {
self.flags.contains(ReprFlags::IS_LINEAR)
}
+ #[inline]
+ pub fn hide_niche(&self) -> bool {
+ self.flags.contains(ReprFlags::HIDE_NICHE)
+ }
pub fn discr_type(&self) -> attr::IntType {
self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
if Some(did) == tcx.lang_items().owned_box() {
flags |= AdtFlags::IS_BOX;
}
+ if Some(did) == tcx.lang_items().manually_drop() {
+ flags |= AdtFlags::IS_MANUALLY_DROP;
+ }
if Some(did) == tcx.lang_items().arc() {
flags |= AdtFlags::IS_ARC;
}
self.flags.contains(AdtFlags::IS_BOX)
}
+ /// Returns `true` if this is `ManuallyDrop<T>`.
+ #[inline]
+ pub fn is_manually_drop(&self) -> bool {
+ self.flags.contains(AdtFlags::IS_MANUALLY_DROP)
+ }
+
/// Returns `true` if this type has a destructor.
pub fn has_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
self.destructor(tcx).is_some()
let repr_type = self.repr.discr_type();
match tcx.const_eval_poly(expr_did) {
Ok(val) => {
- // FIXME: Find the right type and use it instead of `val.ty` here
- if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
+ let ty = repr_type.to_ty(tcx);
+ if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
trace!("discriminants: {} ({:?})", b, repr_type);
- Some(Discr { val: b, ty: val.ty })
+ Some(Discr { val: b, ty })
} else {
info!("invalid enum discriminant: {:#?}", val);
crate::mir::interpret::struct_error(
pub enum ImplOverlapKind {
/// These impls are always allowed to overlap.
Permitted {
- /// Whether or not the impl is permitted due to the trait being
- /// a marker trait (a trait with #[marker], or a trait with
- /// no associated items and #![feature(overlapping_marker_traits)] enabled)
+ /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
marker: bool,
},
/// These impls are allowed to overlap, but that raises
.for_each(|&body_id| f(self.hir().body_owner_def_id(body_id)));
}
- pub fn provided_trait_methods(self, id: DefId) -> Vec<AssocItem> {
+ pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
self.associated_items(id)
+ .in_definition_order()
.filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value())
- .collect()
}
pub fn trait_relevant_for_never(self, did: DefId) -> bool {
- self.associated_items(did).any(|item| item.relevant_for_never())
+ self.associated_items(did).in_definition_order().any(|item| item.relevant_for_never())
}
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
variant.fields.iter().position(|field| self.hygienic_eq(ident, field.ident, variant.def_id))
}
- pub fn associated_items(self, def_id: DefId) -> AssocItemsIterator<'tcx> {
- // Ideally, we would use `-> impl Iterator` here, but it falls
- // afoul of the conservative "capture [restrictions]" we put
- // in place, so we use a hand-written iterator.
- //
- // [restrictions]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
- AssocItemsIterator {
- tcx: self,
- def_ids: self.associated_item_def_ids(def_id),
- next_index: 0,
- }
- }
-
/// Returns `true` if the impls are the same polarity and the trait either
/// has no items or is annotated #[marker] and prevents item overrides.
pub fn impls_are_allowed_to_overlap(
| (ImplPolarity::Negative, ImplPolarity::Negative) => {}
};
- let is_marker_overlap = if self.features().overlapping_marker_traits {
- let trait1_is_empty = self.impl_trait_ref(def_id1).map_or(false, |trait_ref| {
- self.associated_item_def_ids(trait_ref.def_id).is_empty()
- });
- let trait2_is_empty = self.impl_trait_ref(def_id2).map_or(false, |trait_ref| {
- self.associated_item_def_ids(trait_ref.def_id).is_empty()
- });
- trait1_is_empty && trait2_is_empty
- } else {
+ let is_marker_overlap = {
let is_marker_impl = |def_id: DefId| -> bool {
let trait_ref = self.impl_trait_ref(def_id);
trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
Some(actual_expansion) => {
self.hir().definitions().parent_module_of_macro_def(actual_expansion)
}
- None => self.hir().get_module_parent(block),
+ None => self.parent_module(block),
};
(ident, scope)
}
-}
-
-#[derive(Clone)]
-pub struct AssocItemsIterator<'tcx> {
- tcx: TyCtxt<'tcx>,
- def_ids: &'tcx [DefId],
- next_index: usize,
-}
-
-impl Iterator for AssocItemsIterator<'_> {
- type Item = AssocItem;
- fn next(&mut self) -> Option<AssocItem> {
- let def_id = self.def_ids.get(self.next_index)?;
- self.next_index += 1;
- Some(self.tcx.associated_item(*def_id))
+ pub fn is_object_safe(self, key: DefId) -> bool {
+ self.object_safety_violations(key).is_empty()
}
}