1use std::iter;
23use rustc_data_structures::fx::FxIndexMap;
4use rustc_errors::ErrorGuaranteed;
5use rustc_hiras hir;
6use rustc_hir::def::DefKind;
7use rustc_hir::def_id::{DefId, LOCAL_CRATE};
8use rustc_macros::{Decodable, Encodable, HashStable};
9use tracing::debug;
1011use crate::query::LocalCrate;
12use crate::traits::specialization_graph;
13use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
14use crate::ty::{Ident, Ty, TyCtxt};
1516/// A trait's definition with type information.
17#[derive(HashStable, Encodable, Decodable)]
18pub struct TraitDef {
19pub def_id: DefId,
2021pub safety: hir::Safety,
2223/// Whether this trait has been annotated with `#[const_trait]`.
24pub constness: hir::Constness,
2526/// If `true`, then this trait had the `#[rustc_paren_sugar]`
27 /// attribute, indicating that it should be used with `Foo()`
28 /// sugar. This is a temporary thing -- eventually any trait will
29 /// be usable with the sugar (or without it).
30pub paren_sugar: bool,
3132pub has_auto_impl: bool,
3334/// If `true`, then this trait has the `#[marker]` attribute, indicating
35 /// that all its associated items have defaults that cannot be overridden,
36 /// and thus `impl`s of it are allowed to overlap.
37pub is_marker: bool,
3839/// If `true`, then this trait has the `#[rustc_coinductive]` attribute or
40 /// is an auto trait. This indicates that trait solver cycles involving an
41 /// `X: ThisTrait` goal are accepted.
42 ///
43 /// In the future all traits should be coinductive, but we need a better
44 /// formal understanding of what exactly that means and should probably
45 /// also have already switched to the new trait solver.
46pub is_coinductive: bool,
4748/// If `true`, then this trait has the `#[fundamental]` attribute. This
49 /// affects how conherence computes whether a trait may have trait implementations
50 /// added in the future.
51pub is_fundamental: bool,
5253/// If `true`, then this trait has the `#[rustc_skip_during_method_dispatch(array)]`
54 /// attribute, indicating that editions before 2021 should not consider this trait
55 /// during method dispatch if the receiver is an array.
56pub skip_array_during_method_dispatch: bool,
5758/// If `true`, then this trait has the `#[rustc_skip_during_method_dispatch(boxed_slice)]`
59 /// attribute, indicating that editions before 2024 should not consider this trait
60 /// during method dispatch if the receiver is a boxed slice.
61pub skip_boxed_slice_during_method_dispatch: bool,
6263/// Used to determine whether the standard library is allowed to specialize
64 /// on this trait.
65pub specialization_kind: TraitSpecializationKind,
6667/// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
68 /// must be implemented.
69pub must_implement_one_of: Option<Box<[Ident]>>,
7071/// Whether to add a builtin `dyn Trait: Trait` implementation.
72 /// This is enabled for all traits except ones marked with
73 /// `#[rustc_do_not_implement_via_object]`.
74pub implement_via_object: bool,
7576/// Whether a trait is fully built-in, and any implementation is disallowed.
77 /// This only applies to built-in traits, and is marked via
78 /// `#[rustc_deny_explicit_impl]`.
79pub deny_explicit_impl: bool,
80}
8182/// Whether this trait is treated specially by the standard library
83/// specialization lint.
84#[derive(HashStable, PartialEq, Clone, Copy, Encodable, Decodable)]
85pub enum TraitSpecializationKind {
86/// The default. Specializing on this trait is not allowed.
87None,
88/// Specializing on this trait is allowed because it doesn't have any
89 /// methods. For example `Sized` or `FusedIterator`.
90 /// Applies to traits with the `rustc_unsafe_specialization_marker`
91 /// attribute.
92Marker,
93/// Specializing on this trait is allowed because all of the impls of this
94 /// trait are "always applicable". Always applicable means that if
95 /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`.
96 /// Applies to traits with the `rustc_specialization_trait` attribute.
97AlwaysApplicable,
98}
99100#[derive(Default, Debug, HashStable)]
101pub struct TraitImpls {
102 blanket_impls: Vec<DefId>,
103/// Impls indexed by their simplified self type, for fast lookup.
104non_blanket_impls: FxIndexMap<SimplifiedType, Vec<DefId>>,
105}
106107impl TraitImpls {
108pub fn is_empty(&self) -> bool {
109self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty()
110 }
111112pub fn blanket_impls(&self) -> &[DefId] {
113self.blanket_impls.as_slice()
114 }
115116pub fn non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>> {
117&self.non_blanket_impls
118 }
119}
120121impl<'tcx> TraitDef {
122pub fn ancestors(
123&self,
124 tcx: TyCtxt<'tcx>,
125 of_impl: DefId,
126 ) -> Result<specialization_graph::Ancestors<'tcx>, ErrorGuaranteed> {
127specialization_graph::ancestors(tcx, self.def_id, of_impl)
128 }
129}
130131impl<'tcx> TyCtxt<'tcx> {
132/// `trait_def_id` MUST BE the `DefId` of a trait.
133pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
134let impls = self.trait_impls_of(trait_def_id);
135136for &impl_def_id in impls.blanket_impls.iter() {
137 f(impl_def_id);
138 }
139140for v in impls.non_blanket_impls.values() {
141for &impl_def_id in v {
142 f(impl_def_id);
143 }
144 }
145 }
146147/// Iterate over every impl that could possibly match the self type `self_ty`.
148 ///
149 /// `trait_def_id` MUST BE the `DefId` of a trait.
150pub fn for_each_relevant_impl(
151self,
152 trait_def_id: DefId,
153 self_ty: Ty<'tcx>,
154mut f: impl FnMut(DefId),
155 ) {
156// FIXME: This depends on the set of all impls for the trait. That is
157 // unfortunate wrt. incremental compilation.
158 //
159 // If we want to be faster, we could have separate queries for
160 // blanket and non-blanket impls, and compare them separately.
161let impls = self.trait_impls_of(trait_def_id);
162163for &impl_def_id in impls.blanket_impls.iter() {
164 f(impl_def_id);
165 }
166167// This way, when searching for some impl for `T: Trait`, we do not look at any impls
168 // whose outer level is not a parameter or projection. Especially for things like
169 // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
170 // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
171 // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using
172 // `TreatParams::InstantiateWithInfer` while actually adding them.
173if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsRigid) {
174if let Some(impls) = impls.non_blanket_impls.get(&simp) {
175for &impl_def_id in impls {
176 f(impl_def_id);
177 }
178 }
179 } else {
180for &impl_def_id in impls.non_blanket_impls.values().flatten() {
181 f(impl_def_id);
182 }
183 }
184 }
185186/// `trait_def_id` MUST BE the `DefId` of a trait.
187pub fn non_blanket_impls_for_ty(
188self,
189 trait_def_id: DefId,
190 self_ty: Ty<'tcx>,
191 ) -> impl Iterator<Item = DefId> {
192let impls = self.trait_impls_of(trait_def_id);
193if let Some(simp) =
194fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer)
195 {
196if let Some(impls) = impls.non_blanket_impls.get(&simp) {
197return impls.iter().copied();
198 }
199 }
200201 [].iter().copied()
202 }
203204/// Returns an iterator containing all impls for `trait_def_id`.
205 ///
206 /// `trait_def_id` MUST BE the `DefId` of a trait.
207pub fn all_impls(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> {
208let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(trait_def_id);
209210blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned()
211 }
212}
213214/// Query provider for `trait_impls_of`.
215pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls {
216let mut impls = TraitImpls::default();
217218// Traits defined in the current crate can't have impls in upstream
219 // crates, so we don't bother querying the cstore.
220if !trait_id.is_local() {
221for &cnum in tcx.crates(()).iter() {
222for &(impl_def_id, simplified_self_ty) in
223tcx.implementations_of_trait((cnum, trait_id)).iter()
224 {
225if let Some(simplified_self_ty) = simplified_self_ty {
226 impls
227 .non_blanket_impls
228 .entry(simplified_self_ty)
229 .or_default()
230 .push(impl_def_id);
231 } else {
232 impls.blanket_impls.push(impl_def_id);
233 }
234 }
235 }
236 }
237238for &impl_def_id in tcx.hir_trait_impls(trait_id) {
239let impl_def_id = impl_def_id.to_def_id();
240241let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
242243if let Some(simplified_self_ty) =
244 fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer)
245 {
246 impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
247 } else {
248 impls.blanket_impls.push(impl_def_id);
249 }
250 }
251252impls253}
254255/// Query provider for `incoherent_impls`.
256pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
257let mut impls = Vec::new();
258for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
259for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
260 impls.push(impl_def_id)
261 }
262 }
263debug!(?impls);
264265tcx.arena.alloc_slice(&impls)
266}
267268pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
269let mut traits = Vec::new();
270for id in tcx.hir_free_items() {
271if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
272 traits.push(id.owner_id.to_def_id())
273 }
274 }
275276tcx.arena.alloc_slice(&traits)
277}
278279pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
280let mut trait_impls = Vec::new();
281for id in tcx.hir_free_items() {
282if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
283 && tcx.impl_trait_ref(id.owner_id).is_some()
284 {
285 trait_impls.push(id.owner_id.to_def_id())
286 }
287 }
288289tcx.arena.alloc_slice(&trait_impls)
290}