1 use crate::traits
::specialization_graph
;
2 use crate::ty
::fast_reject
::{self, SimplifiedType, TreatParams}
;
3 use crate::ty
::fold
::TypeFoldable
;
4 use crate::ty
::{Ident, Ty, TyCtxt}
;
5 use hir
::def_id
::LOCAL_CRATE
;
7 use rustc_hir
::def_id
::DefId
;
10 use rustc_data_structures
::fx
::FxIndexMap
;
11 use rustc_errors
::ErrorGuaranteed
;
12 use rustc_macros
::HashStable
;
14 /// A trait's definition with type information.
15 #[derive(HashStable, Encodable, Decodable)]
19 pub unsafety
: hir
::Unsafety
,
21 /// If `true`, then this trait had the `#[rustc_paren_sugar]`
22 /// attribute, indicating that it should be used with `Foo()`
23 /// sugar. This is a temporary thing -- eventually any trait will
24 /// be usable with the sugar (or without it).
25 pub paren_sugar
: bool
,
27 pub has_auto_impl
: bool
,
29 /// If `true`, then this trait has the `#[marker]` attribute, indicating
30 /// that all its associated items have defaults that cannot be overridden,
31 /// and thus `impl`s of it are allowed to overlap.
34 /// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
35 /// attribute, indicating that editions before 2021 should not consider this trait
36 /// during method dispatch if the receiver is an array.
37 pub skip_array_during_method_dispatch
: bool
,
39 /// Used to determine whether the standard library is allowed to specialize
41 pub specialization_kind
: TraitSpecializationKind
,
43 /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
44 /// must be implemented.
45 pub must_implement_one_of
: Option
<Box
<[Ident
]>>,
48 /// Whether this trait is treated specially by the standard library
49 /// specialization lint.
50 #[derive(HashStable, PartialEq, Clone, Copy, Encodable, Decodable)]
51 pub enum TraitSpecializationKind
{
52 /// The default. Specializing on this trait is not allowed.
54 /// Specializing on this trait is allowed because it doesn't have any
55 /// methods. For example `Sized` or `FusedIterator`.
56 /// Applies to traits with the `rustc_unsafe_specialization_marker`
59 /// Specializing on this trait is allowed because all of the impls of this
60 /// trait are "always applicable". Always applicable means that if
61 /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`.
62 /// Applies to traits with the `rustc_specialization_trait` attribute.
66 #[derive(Default, Debug, HashStable)]
67 pub struct TraitImpls
{
68 blanket_impls
: Vec
<DefId
>,
69 /// Impls indexed by their simplified self type, for fast lookup.
70 non_blanket_impls
: FxIndexMap
<SimplifiedType
, Vec
<DefId
>>,
74 pub fn blanket_impls(&self) -> &[DefId
] {
75 self.blanket_impls
.as_slice()
82 unsafety
: hir
::Unsafety
,
86 skip_array_during_method_dispatch
: bool
,
87 specialization_kind
: TraitSpecializationKind
,
88 must_implement_one_of
: Option
<Box
<[Ident
]>>,
96 skip_array_during_method_dispatch
,
98 must_implement_one_of
,
106 ) -> Result
<specialization_graph
::Ancestors
<'tcx
>, ErrorGuaranteed
> {
107 specialization_graph
::ancestors(tcx
, self.def_id
, of_impl
)
111 impl<'tcx
> TyCtxt
<'tcx
> {
112 pub fn for_each_impl
<F
: FnMut(DefId
)>(self, def_id
: DefId
, mut f
: F
) {
113 let impls
= self.trait_impls_of(def_id
);
115 for &impl_def_id
in impls
.blanket_impls
.iter() {
119 for v
in impls
.non_blanket_impls
.values() {
120 for &impl_def_id
in v
{
126 /// Iterate over every impl that could possibly match the
127 /// self type `self_ty`.
128 pub fn for_each_relevant_impl
<F
: FnMut(DefId
)>(
134 let _
: Option
<()> = self.find_map_relevant_impl(def_id
, self_ty
, |did
| {
140 pub fn non_blanket_impls_for_ty(
144 ) -> impl Iterator
<Item
= DefId
> + 'tcx
{
145 let impls
= self.trait_impls_of(def_id
);
146 if let Some(simp
) = fast_reject
::simplify_type(self, self_ty
, TreatParams
::AsInfer
) {
147 if let Some(impls
) = impls
.non_blanket_impls
.get(&simp
) {
148 return impls
.iter().copied();
155 /// Applies function to every impl that could possibly match the self type `self_ty` and returns
156 /// the first non-none value.
157 pub fn find_map_relevant_impl
<T
, F
: FnMut(DefId
) -> Option
<T
>>(
163 // FIXME: This depends on the set of all impls for the trait. That is
164 // unfortunate wrt. incremental compilation.
166 // If we want to be faster, we could have separate queries for
167 // blanket and non-blanket impls, and compare them separately.
168 let impls
= self.trait_impls_of(def_id
);
170 for &impl_def_id
in impls
.blanket_impls
.iter() {
171 if let result @
Some(_
) = f(impl_def_id
) {
176 // Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using
177 // `TreatParams::AsInfer` while actually adding them.
179 // This way, when searching for some impl for `T: Trait`, we do not look at any impls
180 // whose outer level is not a parameter or projection. Especially for things like
181 // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
182 // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
183 if let Some(simp
) = fast_reject
::simplify_type(self, self_ty
, TreatParams
::AsPlaceholder
) {
184 if let Some(impls
) = impls
.non_blanket_impls
.get(&simp
) {
185 for &impl_def_id
in impls
{
186 if let result @
Some(_
) = f(impl_def_id
) {
192 for &impl_def_id
in impls
.non_blanket_impls
.values().flatten() {
193 if let result @
Some(_
) = f(impl_def_id
) {
202 /// Returns an iterator containing all impls
203 pub fn all_impls(self, def_id
: DefId
) -> impl Iterator
<Item
= DefId
> + 'tcx
{
204 let TraitImpls { blanket_impls, non_blanket_impls }
= self.trait_impls_of(def_id
);
206 blanket_impls
.iter().chain(non_blanket_impls
.iter().flat_map(|(_
, v
)| v
)).cloned()
210 // Query provider for `trait_impls_of`.
211 pub(super) fn trait_impls_of_provider(tcx
: TyCtxt
<'_
>, trait_id
: DefId
) -> TraitImpls
{
212 let mut impls
= TraitImpls
::default();
214 // Traits defined in the current crate can't have impls in upstream
215 // crates, so we don't bother querying the cstore.
216 if !trait_id
.is_local() {
217 for &cnum
in tcx
.crates(()).iter() {
218 for &(impl_def_id
, simplified_self_ty
) in
219 tcx
.implementations_of_trait((cnum
, trait_id
)).iter()
221 if let Some(simplified_self_ty
) = simplified_self_ty
{
224 .entry(simplified_self_ty
)
228 impls
.blanket_impls
.push(impl_def_id
);
234 for &impl_def_id
in tcx
.hir().trait_impls(trait_id
) {
235 let impl_def_id
= impl_def_id
.to_def_id();
237 let impl_self_ty
= tcx
.type_of(impl_def_id
);
238 if impl_self_ty
.references_error() {
242 if let Some(simplified_self_ty
) =
243 fast_reject
::simplify_type(tcx
, impl_self_ty
, TreatParams
::AsInfer
)
245 impls
.non_blanket_impls
.entry(simplified_self_ty
).or_default().push(impl_def_id
);
247 impls
.blanket_impls
.push(impl_def_id
);
254 // Query provider for `incoherent_impls`.
255 #[instrument(level = "debug", skip(tcx))]
256 pub(super) fn incoherent_impls_provider(tcx
: TyCtxt
<'_
>, simp
: SimplifiedType
) -> &[DefId
] {
257 let mut impls
= Vec
::new();
259 for cnum
in iter
::once(LOCAL_CRATE
).chain(tcx
.crates(()).iter().copied()) {
260 for &impl_def_id
in tcx
.crate_incoherent_impls((cnum
, simp
)) {
261 impls
.push(impl_def_id
)
267 tcx
.arena
.alloc_slice(&impls
)