• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::traits::specialization_graph;
2 use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
3 use crate::ty::visit::TypeVisitableExt;
4 use crate::ty::{Ident, Ty, TyCtxt};
5 use hir::def_id::LOCAL_CRATE;
6 use rustc_hir as hir;
7 use rustc_hir::def_id::DefId;
8 use std::iter;
9 
10 use rustc_data_structures::fx::FxIndexMap;
11 use rustc_errors::ErrorGuaranteed;
12 use rustc_macros::HashStable;
13 
14 /// A trait's definition with type information.
15 #[derive(HashStable, Encodable, Decodable)]
16 pub struct TraitDef {
17     pub def_id: DefId,
18 
19     pub unsafety: hir::Unsafety,
20 
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,
26 
27     pub has_auto_impl: bool,
28 
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.
32     pub is_marker: bool,
33 
34     /// If `true`, then this trait has to `#[rustc_coinductive]` attribute or
35     /// is an auto trait. This indicates that trait solver cycles involving an
36     /// `X: ThisTrait` goal are accepted.
37     ///
38     /// In the future all traits should be coinductive, but we need a better
39     /// formal understanding of what exactly that means and should probably
40     /// also have already switched to the new trait solver.
41     pub is_coinductive: bool,
42 
43     /// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
44     /// attribute, indicating that editions before 2021 should not consider this trait
45     /// during method dispatch if the receiver is an array.
46     pub skip_array_during_method_dispatch: bool,
47 
48     /// Used to determine whether the standard library is allowed to specialize
49     /// on this trait.
50     pub specialization_kind: TraitSpecializationKind,
51 
52     /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
53     /// must be implemented.
54     pub must_implement_one_of: Option<Box<[Ident]>>,
55 
56     /// Whether to add a builtin `dyn Trait: Trait` implementation.
57     /// This is enabled for all traits except ones marked with
58     /// `#[rustc_deny_explicit_impl(implement_via_object = false)]`.
59     pub implement_via_object: bool,
60 
61     /// Whether a trait is fully built-in, and any implementation is disallowed.
62     /// This only applies to built-in traits, and is marked via
63     /// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`.
64     pub deny_explicit_impl: bool,
65 }
66 
67 /// Whether this trait is treated specially by the standard library
68 /// specialization lint.
69 #[derive(HashStable, PartialEq, Clone, Copy, Encodable, Decodable)]
70 pub enum TraitSpecializationKind {
71     /// The default. Specializing on this trait is not allowed.
72     None,
73     /// Specializing on this trait is allowed because it doesn't have any
74     /// methods. For example `Sized` or `FusedIterator`.
75     /// Applies to traits with the `rustc_unsafe_specialization_marker`
76     /// attribute.
77     Marker,
78     /// Specializing on this trait is allowed because all of the impls of this
79     /// trait are "always applicable". Always applicable means that if
80     /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`.
81     /// Applies to traits with the `rustc_specialization_trait` attribute.
82     AlwaysApplicable,
83 }
84 
85 #[derive(Default, Debug, HashStable)]
86 pub struct TraitImpls {
87     blanket_impls: Vec<DefId>,
88     /// Impls indexed by their simplified self type, for fast lookup.
89     non_blanket_impls: FxIndexMap<SimplifiedType, Vec<DefId>>,
90 }
91 
92 impl TraitImpls {
blanket_impls(&self) -> &[DefId]93     pub fn blanket_impls(&self) -> &[DefId] {
94         self.blanket_impls.as_slice()
95     }
96 
non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>>97     pub fn non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>> {
98         &self.non_blanket_impls
99     }
100 }
101 
102 impl<'tcx> TraitDef {
ancestors( &self, tcx: TyCtxt<'tcx>, of_impl: DefId, ) -> Result<specialization_graph::Ancestors<'tcx>, ErrorGuaranteed>103     pub fn ancestors(
104         &self,
105         tcx: TyCtxt<'tcx>,
106         of_impl: DefId,
107     ) -> Result<specialization_graph::Ancestors<'tcx>, ErrorGuaranteed> {
108         specialization_graph::ancestors(tcx, self.def_id, of_impl)
109     }
110 }
111 
112 impl<'tcx> TyCtxt<'tcx> {
113     /// `trait_def_id` MUST BE the `DefId` of a trait.
for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F)114     pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
115         let impls = self.trait_impls_of(trait_def_id);
116 
117         for &impl_def_id in impls.blanket_impls.iter() {
118             f(impl_def_id);
119         }
120 
121         for v in impls.non_blanket_impls.values() {
122             for &impl_def_id in v {
123                 f(impl_def_id);
124             }
125         }
126     }
127 
128     /// Iterate over every impl that could possibly match the self type `self_ty`.
129     ///
130     /// `trait_def_id` MUST BE the `DefId` of a trait.
for_each_relevant_impl( self, trait_def_id: DefId, self_ty: Ty<'tcx>, f: impl FnMut(DefId), )131     pub fn for_each_relevant_impl(
132         self,
133         trait_def_id: DefId,
134         self_ty: Ty<'tcx>,
135         f: impl FnMut(DefId),
136     ) {
137         self.for_each_relevant_impl_treating_projections(
138             trait_def_id,
139             self_ty,
140             TreatProjections::ForLookup,
141             f,
142         )
143     }
144 
for_each_relevant_impl_treating_projections( self, trait_def_id: DefId, self_ty: Ty<'tcx>, treat_projections: TreatProjections, mut f: impl FnMut(DefId), )145     pub fn for_each_relevant_impl_treating_projections(
146         self,
147         trait_def_id: DefId,
148         self_ty: Ty<'tcx>,
149         treat_projections: TreatProjections,
150         mut f: impl FnMut(DefId),
151     ) {
152         // FIXME: This depends on the set of all impls for the trait. That is
153         // unfortunate wrt. incremental compilation.
154         //
155         // If we want to be faster, we could have separate queries for
156         // blanket and non-blanket impls, and compare them separately.
157         let impls = self.trait_impls_of(trait_def_id);
158 
159         for &impl_def_id in impls.blanket_impls.iter() {
160             f(impl_def_id);
161         }
162 
163         // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
164         // `TreatParams::AsCandidateKey` while actually adding them.
165         let treat_params = match treat_projections {
166             TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
167             TreatProjections::ForLookup => TreatParams::ForLookup,
168         };
169         // This way, when searching for some impl for `T: Trait`, we do not look at any impls
170         // whose outer level is not a parameter or projection. Especially for things like
171         // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
172         // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
173         if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
174             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
175                 for &impl_def_id in impls {
176                     f(impl_def_id);
177                 }
178             }
179         } else {
180             for &impl_def_id in impls.non_blanket_impls.values().flatten() {
181                 f(impl_def_id);
182             }
183         }
184     }
185 
186     /// `trait_def_id` MUST BE the `DefId` of a trait.
non_blanket_impls_for_ty( self, trait_def_id: DefId, self_ty: Ty<'tcx>, ) -> impl Iterator<Item = DefId> + 'tcx187     pub fn non_blanket_impls_for_ty(
188         self,
189         trait_def_id: DefId,
190         self_ty: Ty<'tcx>,
191     ) -> impl Iterator<Item = DefId> + 'tcx {
192         let impls = self.trait_impls_of(trait_def_id);
193         if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
194             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
195                 return impls.iter().copied();
196             }
197         }
198 
199         [].iter().copied()
200     }
201 
202     /// Returns an iterator containing all impls for `trait_def_id`.
203     ///
204     /// `trait_def_id` MUST BE the `DefId` of a trait.
all_impls(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx205     pub fn all_impls(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
206         let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(trait_def_id);
207 
208         blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned()
209     }
210 }
211 
212 /// Query provider for `trait_impls_of`.
trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls213 pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls {
214     let mut impls = TraitImpls::default();
215 
216     // Traits defined in the current crate can't have impls in upstream
217     // crates, so we don't bother querying the cstore.
218     if !trait_id.is_local() {
219         for &cnum in tcx.crates(()).iter() {
220             for &(impl_def_id, simplified_self_ty) in
221                 tcx.implementations_of_trait((cnum, trait_id)).iter()
222             {
223                 if let Some(simplified_self_ty) = simplified_self_ty {
224                     impls
225                         .non_blanket_impls
226                         .entry(simplified_self_ty)
227                         .or_default()
228                         .push(impl_def_id);
229                 } else {
230                     impls.blanket_impls.push(impl_def_id);
231                 }
232             }
233         }
234     }
235 
236     for &impl_def_id in tcx.hir().trait_impls(trait_id) {
237         let impl_def_id = impl_def_id.to_def_id();
238 
239         let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
240         if impl_self_ty.references_error() {
241             continue;
242         }
243 
244         if let Some(simplified_self_ty) =
245             fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey)
246         {
247             impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
248         } else {
249             impls.blanket_impls.push(impl_def_id);
250         }
251     }
252 
253     impls
254 }
255 
256 /// Query provider for `incoherent_impls`.
incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId]257 pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
258     let mut impls = Vec::new();
259 
260     for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
261         for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
262             impls.push(impl_def_id)
263         }
264     }
265 
266     debug!(?impls);
267 
268     tcx.arena.alloc_slice(&impls)
269 }
270