11use std:: iter;
2+ use std:: ops:: ControlFlow ;
23
34use rustc_data_structures:: fx:: FxIndexMap ;
45use rustc_errors:: ErrorGuaranteed ;
@@ -13,7 +14,7 @@ use crate::query::LocalCrate;
1314use crate :: traits:: specialization_graph;
1415use crate :: ty:: fast_reject:: { self , SimplifiedType , TreatParams } ;
1516use crate :: ty:: print:: { with_crate_prefix, with_no_trimmed_paths} ;
16- use crate :: ty:: { Ident , Ty , TyCtxt } ;
17+ use crate :: ty:: { self , Ident , Interner , Ty , TyCtxt , VisitorResult } ;
1718
1819/// A trait's definition with type information.
1920#[ derive( StableHash , Encodable , Decodable ) ]
@@ -182,40 +183,141 @@ impl<'tcx> TyCtxt<'tcx> {
182183 /// Iterate over every impl that could possibly match the self type `self_ty`.
183184 ///
184185 /// `trait_def_id` MUST BE the `DefId` of a trait.
185- pub fn for_each_relevant_impl (
186+ pub fn for_each_relevant_impl < R : VisitorResult > (
186187 self ,
187188 trait_def_id : DefId ,
188189 self_ty : Ty < ' tcx > ,
189- mut f : impl FnMut ( DefId ) ,
190- ) {
191- // FIXME: This depends on the set of all impls for the trait. That is
192- // unfortunate wrt. incremental compilation.
193- //
194- // If we want to be faster, we could have separate queries for
195- // blanket and non-blanket impls, and compare them separately.
196- let impls = self . trait_impls_of ( trait_def_id) ;
197-
198- for & impl_def_id in impls. blanket_impls . iter ( ) {
199- f ( impl_def_id) ;
190+ mut f : impl FnMut ( DefId ) -> R ,
191+ ) -> R {
192+ macro_rules! ret {
193+ ( $e: expr) => {
194+ match $e. branch( ) {
195+ ControlFlow :: Break ( b) => return R :: from_residual( b) ,
196+ ControlFlow :: Continue ( ( ) ) => { }
197+ }
198+ } ;
200199 }
201200
202- // This way, when searching for some impl for `T: Trait`, we do not look at any impls
203- // whose outer level is not a parameter or projection. Especially for things like
204- // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
205- // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
206- // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using
207- // `TreatParams::InstantiateWithInfer` while actually adding them.
208- if let Some ( simp) = fast_reject:: simplify_type ( self , self_ty, TreatParams :: AsRigid ) {
209- if let Some ( impls) = impls. non_blanket_impls . get ( & simp) {
210- for & impl_def_id in impls {
211- f ( impl_def_id) ;
201+ let tcx = self ;
202+ let trait_impls = tcx. trait_impls_of ( trait_def_id) ;
203+ let mut consider_impls_for_simplified_type = |simp| {
204+ if let Some ( impls_for_type) = trait_impls. non_blanket_impls ( ) . get ( & simp) {
205+ for & impl_def_id in impls_for_type {
206+ ret ! ( f( impl_def_id) )
212207 }
213208 }
214- } else {
215- for & impl_def_id in impls. non_blanket_impls . values ( ) . flatten ( ) {
216- f ( impl_def_id) ;
209+
210+ R :: output ( )
211+ } ;
212+
213+ match self_ty. kind ( ) {
214+ ty:: Bool
215+ | ty:: Char
216+ | ty:: Int ( _)
217+ | ty:: Uint ( _)
218+ | ty:: Float ( _)
219+ | ty:: Adt ( _, _)
220+ | ty:: Foreign ( _)
221+ | ty:: Str
222+ | ty:: Array ( _, _)
223+ | ty:: Pat ( _, _)
224+ | ty:: Slice ( _)
225+ | ty:: RawPtr ( _, _)
226+ | ty:: Ref ( _, _, _)
227+ | ty:: FnDef ( _, _)
228+ | ty:: FnPtr ( ..)
229+ | ty:: Dynamic ( _, _)
230+ | ty:: Closure ( ..)
231+ | ty:: CoroutineClosure ( ..)
232+ | ty:: Coroutine ( _, _)
233+ | ty:: Never
234+ | ty:: Tuple ( _)
235+ | ty:: UnsafeBinder ( _) => {
236+ let simp = ty:: fast_reject:: simplify_type (
237+ tcx,
238+ self_ty,
239+ ty:: fast_reject:: TreatParams :: AsRigid ,
240+ )
241+ . unwrap ( ) ;
242+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
243+ }
244+
245+ // HACK: For integer and float variables we have to manually look at all impls
246+ // which have some integer or float as a self type.
247+ ty:: Infer ( ty:: IntVar ( _) ) => {
248+ use ty:: IntTy :: * ;
249+ use ty:: UintTy :: * ;
250+ // This causes a compiler error if any new integer kinds are added.
251+ let ( I8 | I16 | I32 | I64 | I128 | Isize ) : ty:: IntTy ;
252+ let ( U8 | U16 | U32 | U64 | U128 | Usize ) : ty:: UintTy ;
253+ let possible_integers = [
254+ // signed integers
255+ ty:: SimplifiedType :: Int ( I8 ) ,
256+ ty:: SimplifiedType :: Int ( I16 ) ,
257+ ty:: SimplifiedType :: Int ( I32 ) ,
258+ ty:: SimplifiedType :: Int ( I64 ) ,
259+ ty:: SimplifiedType :: Int ( I128 ) ,
260+ ty:: SimplifiedType :: Int ( Isize ) ,
261+ // unsigned integers
262+ ty:: SimplifiedType :: Uint ( U8 ) ,
263+ ty:: SimplifiedType :: Uint ( U16 ) ,
264+ ty:: SimplifiedType :: Uint ( U32 ) ,
265+ ty:: SimplifiedType :: Uint ( U64 ) ,
266+ ty:: SimplifiedType :: Uint ( U128 ) ,
267+ ty:: SimplifiedType :: Uint ( Usize ) ,
268+ ] ;
269+ for simp in possible_integers {
270+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
271+ }
272+ }
273+
274+ ty:: Infer ( ty:: FloatVar ( _) ) => {
275+ // This causes a compiler error if any new float kinds are added.
276+ let ( ty:: FloatTy :: F16 | ty:: FloatTy :: F32 | ty:: FloatTy :: F64 | ty:: FloatTy :: F128 ) ;
277+ let possible_floats = [
278+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F16 ) ,
279+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F32 ) ,
280+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F64 ) ,
281+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F128 ) ,
282+ ] ;
283+
284+ for simp in possible_floats {
285+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
286+ }
287+ }
288+
289+ // This is only for diagnostics and normally ty vars should be handled by the callers.
290+ ty:: Infer ( ty:: TyVar ( _) ) => {
291+ for & impl_def_id in trait_impls. non_blanket_impls ( ) . values ( ) . flatten ( ) {
292+ ret ! ( f( impl_def_id) ) ;
293+ }
294+ }
295+
296+ // The only traits applying to aliases and placeholders are blanket impls.
297+ //
298+ // Impls which apply to an alias after normalization are handled by
299+ // `assemble_candidates_after_normalizing_self_ty`.
300+ ty:: Alias ( ty:: IsRigid :: Yes , _) | ty:: Placeholder ( ..) | ty:: Error ( _) => ( ) ,
301+ // FIXME(-Znext-solver=no): Need to support aliases not marked as
302+ // rigid for the old solver.
303+ ty:: Alias ( ty:: IsRigid :: No , _) => ( ) ,
304+
305+ // FIXME: These should ideally not exist as a self type. It would be nice for
306+ // the builtin auto trait impls of coroutines to instead directly recurse
307+ // into the witness.
308+ ty:: CoroutineWitness ( ..) => ( ) ,
309+
310+ // These are used in diagnostics or in the old solver.
311+ ty:: Param ( _) | ty:: Bound ( _, _) => ( ) ,
312+
313+ // These variants should not exist as a self type.
314+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => {
315+ bug ! ( "unexpected self type: {self_ty:?}" ) ;
217316 }
218317 }
318+
319+ #[ allow( rustc:: usage_of_type_ir_traits) ]
320+ self . for_each_blanket_impl ( trait_def_id, f)
219321 }
220322
221323 /// `trait_def_id` MUST BE the `DefId` of a trait.
0 commit comments