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,151 @@ 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:: Slice ( _)
224+ | ty:: RawPtr ( _, _)
225+ | ty:: Ref ( _, _, _)
226+ | ty:: FnDef ( _, _)
227+ | ty:: FnPtr ( ..)
228+ | ty:: Dynamic ( _, _)
229+ | ty:: Closure ( ..)
230+ | ty:: CoroutineClosure ( ..)
231+ | ty:: Coroutine ( _, _)
232+ | ty:: Never
233+ | ty:: Tuple ( _)
234+ | ty:: UnsafeBinder ( _) => {
235+ let simp = ty:: fast_reject:: simplify_type (
236+ tcx,
237+ self_ty,
238+ ty:: fast_reject:: TreatParams :: AsRigid ,
239+ )
240+ . unwrap ( ) ;
241+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
242+ }
243+
244+ // HACK: For integer and float variables we have to manually look at all impls
245+ // which have some integer or float as a self type.
246+ ty:: Infer ( ty:: IntVar ( _) ) => {
247+ use ty:: IntTy :: * ;
248+ use ty:: UintTy :: * ;
249+ // This causes a compiler error if any new integer kinds are added.
250+ let ( I8 | I16 | I32 | I64 | I128 | Isize ) : ty:: IntTy ;
251+ let ( U8 | U16 | U32 | U64 | U128 | Usize ) : ty:: UintTy ;
252+ let possible_integers = [
253+ // signed integers
254+ ty:: SimplifiedType :: Int ( I8 ) ,
255+ ty:: SimplifiedType :: Int ( I16 ) ,
256+ ty:: SimplifiedType :: Int ( I32 ) ,
257+ ty:: SimplifiedType :: Int ( I64 ) ,
258+ ty:: SimplifiedType :: Int ( I128 ) ,
259+ ty:: SimplifiedType :: Int ( Isize ) ,
260+ // unsigned integers
261+ ty:: SimplifiedType :: Uint ( U8 ) ,
262+ ty:: SimplifiedType :: Uint ( U16 ) ,
263+ ty:: SimplifiedType :: Uint ( U32 ) ,
264+ ty:: SimplifiedType :: Uint ( U64 ) ,
265+ ty:: SimplifiedType :: Uint ( U128 ) ,
266+ ty:: SimplifiedType :: Uint ( Usize ) ,
267+ ] ;
268+ for simp in possible_integers {
269+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
270+ }
271+ }
272+
273+ ty:: Infer ( ty:: FloatVar ( _) ) => {
274+ // This causes a compiler error if any new float kinds are added.
275+ let ( ty:: FloatTy :: F16 | ty:: FloatTy :: F32 | ty:: FloatTy :: F64 | ty:: FloatTy :: F128 ) ;
276+ let possible_floats = [
277+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F16 ) ,
278+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F32 ) ,
279+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F64 ) ,
280+ ty:: SimplifiedType :: Float ( ty:: FloatTy :: F128 ) ,
281+ ] ;
282+
283+ for simp in possible_floats {
284+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
285+ }
286+ }
287+
288+ // Pattern type might not have a simplified type.
289+ ty:: Pat ( _, _) => {
290+ if let Some ( simp) = ty:: fast_reject:: simplify_type (
291+ tcx,
292+ self_ty,
293+ ty:: fast_reject:: TreatParams :: AsRigid ,
294+ ) {
295+ ret ! ( consider_impls_for_simplified_type( simp) ) ;
296+ }
297+ }
298+
299+ // This is only for diagnostics and normally ty vars should be handled by the callers.
300+ ty:: Infer ( ty:: TyVar ( _) ) => {
301+ for & impl_def_id in trait_impls. non_blanket_impls ( ) . values ( ) . flatten ( ) {
302+ ret ! ( f( impl_def_id) ) ;
303+ }
304+ }
305+
306+ // The only traits applying to aliases and placeholders are blanket impls.
307+ //
308+ // Impls which apply to an alias after normalization are handled by
309+ // `assemble_candidates_after_normalizing_self_ty`.
310+ ty:: Alias ( ty:: IsRigid :: Yes , _) | ty:: Placeholder ( ..) | ty:: Error ( _) => ( ) ,
311+ // FIXME(-Znext-solver=no): Need to support aliases not marked as
312+ // rigid for the old solver.
313+ ty:: Alias ( ty:: IsRigid :: No , _) => ( ) ,
314+
315+ // FIXME: These should ideally not exist as a self type. It would be nice for
316+ // the builtin auto trait impls of coroutines to instead directly recurse
317+ // into the witness.
318+ ty:: CoroutineWitness ( ..) => ( ) ,
319+
320+ // These are used in diagnostics or in the old solver.
321+ ty:: Param ( _) | ty:: Bound ( _, _) => ( ) ,
322+
323+ // These variants should not exist as a self type.
324+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => {
325+ bug ! ( "unexpected self type: {self_ty:?}" ) ;
217326 }
218327 }
328+
329+ #[ allow( rustc:: usage_of_type_ir_traits) ]
330+ self . for_each_blanket_impl ( trait_def_id, f)
219331 }
220332
221333 /// `trait_def_id` MUST BE the `DefId` of a trait.
0 commit comments