@@ -33,7 +33,6 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
33
33
use rustc_middle:: dep_graph:: { DepKind , DepNodeIndex } ;
34
34
use rustc_middle:: mir:: interpret:: ErrorHandled ;
35
35
use rustc_middle:: thir:: abstract_const:: NotConstEvaluatable ;
36
- use rustc_middle:: ty:: fast_reject:: { self , TreatParams } ;
37
36
use rustc_middle:: ty:: fold:: BottomUpFolder ;
38
37
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
39
38
use rustc_middle:: ty:: relate:: TypeRelation ;
@@ -214,6 +213,122 @@ enum BuiltinImplConditions<'tcx> {
214
213
Ambiguous ,
215
214
}
216
215
216
+ fn tys_may_be_equivalent < ' tcx > ( oblig_ty : Ty < ' tcx > , impl_ty : Ty < ' tcx > ) -> bool {
217
+ let k = impl_ty. kind ( ) ;
218
+
219
+ // First, look for obvious equivalences, e.g. the types are equal. The most
220
+ // common case is to find such an equivalence trivially, e.g. `ty::Bool`
221
+ // and `ty::Bool`.
222
+ let mut maybe_equiv = match oblig_ty. kind ( ) {
223
+ ty:: Bool => matches ! ( k, ty:: Bool ) ,
224
+ ty:: Char => matches ! ( k, ty:: Char ) ,
225
+ ty:: Int ( ity) => matches ! ( k, ty:: Int ( ity2) if ity == ity2) ,
226
+ ty:: Uint ( uty) => matches ! ( k, ty:: Uint ( uty2) if uty == uty2) ,
227
+ ty:: Float ( fty) => matches ! ( k, ty:: Float ( fty2) if fty == fty2) ,
228
+ ty:: Adt ( def_id, substs1) => match k {
229
+ ty:: Adt ( def_id2, substs2) => {
230
+ def_id == def_id2 && {
231
+ // Check for cases like `Foo<3>` vs `Foo<4>`, which are hot
232
+ // in crates such as `bitmaps` and `nalgebra`.
233
+ let differ_by_single_const_arg = if
234
+ substs1. len ( ) == 1
235
+ && substs2. len ( ) == 1
236
+ && let ty:: subst:: GenericArgKind :: Const ( c1) = substs1[ 0 ] . unpack ( )
237
+ && let ty:: subst:: GenericArgKind :: Const ( c2) = substs2[ 0 ] . unpack ( )
238
+ && let Some ( s1) = c1. val ( ) . try_to_scalar_int ( )
239
+ && let Some ( s2) = c2. val ( ) . try_to_scalar_int ( )
240
+ && s1 != s2
241
+ {
242
+ true
243
+ } else {
244
+ false
245
+ } ;
246
+ !differ_by_single_const_arg
247
+ }
248
+ }
249
+ _ => false ,
250
+ } ,
251
+ ty:: Str => matches ! ( k, ty:: Str ) ,
252
+ ty:: Array ( ..) => matches ! ( k, ty:: Array ( ..) ) ,
253
+ ty:: Slice ( ..) => matches ! ( k, ty:: Slice ( ..) ) ,
254
+ ty:: RawPtr ( ptr) => matches ! ( k, ty:: RawPtr ( ptr2) if ptr. mutbl == ptr2. mutbl) ,
255
+ ty:: Dynamic ( trait_info, ..) => {
256
+ matches ! ( k, ty:: Dynamic ( trait_info2, ..) if
257
+ trait_info. principal_def_id( ) == trait_info2. principal_def_id( )
258
+ )
259
+ }
260
+ ty:: Ref ( _, _, mutbl) => matches ! ( k, ty:: Ref ( _, _, mutbl2) if mutbl == mutbl2) ,
261
+ ty:: FnDef ( def_id, _) => matches ! ( k, ty:: FnDef ( def_id2, _) if def_id == def_id2) ,
262
+ ty:: Closure ( def_id, _) => matches ! ( k, ty:: Closure ( def_id2, _) if def_id == def_id2) ,
263
+ ty:: Generator ( def_id, ..) => {
264
+ matches ! ( k, ty:: Generator ( def_id2, ..) if def_id == def_id2)
265
+ }
266
+ ty:: Never => matches ! ( k, ty:: Never ) ,
267
+ ty:: Tuple ( tys) => matches ! ( k, ty:: Tuple ( tys2) if tys. len( ) == tys2. len( ) ) ,
268
+ ty:: FnPtr ( tys) => {
269
+ matches ! (
270
+ k,
271
+ ty:: FnPtr ( tys2)
272
+ if tys. skip_binder( ) . inputs( ) . len( ) == tys2. skip_binder( ) . inputs( ) . len( )
273
+ )
274
+ }
275
+ ty:: Opaque ( def_id, _) => matches ! ( k, ty:: Opaque ( def_id2, _) if def_id == def_id2) ,
276
+ ty:: Foreign ( def_id) => matches ! ( k, ty:: Foreign ( def_id2) if def_id == def_id2) ,
277
+ ty:: Param ( _) => {
278
+ // Note, we simplify parameters for the obligation but not the impl
279
+ // so that we do not reject a blanket impl but do reject more
280
+ // concrete impls if we're searching for `T: Trait`.
281
+ matches ! ( k, ty:: Placeholder ( ..) )
282
+ }
283
+ ty:: Projection ( _) => {
284
+ // When treating `ty::Param` as a placeholder, projections also
285
+ // don't unify with anything else as long as they are fully normalized.
286
+ //
287
+ // We will have to be careful with lazy normalization here.
288
+ oblig_ty. has_infer_types_or_consts ( ) || matches ! ( k, ty:: Placeholder ( ..) )
289
+ }
290
+ ty:: Infer ( _) => true ,
291
+
292
+ ty:: GeneratorWitness ( ..) | ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Error ( _) => {
293
+ unreachable ! ( )
294
+ }
295
+ } ;
296
+
297
+ // Next, if necessary, look for less obvious sources of equivalence.
298
+ maybe_equiv = maybe_equiv
299
+ || match impl_ty. kind ( ) {
300
+ ty:: Bool
301
+ | ty:: Char
302
+ | ty:: Int ( _)
303
+ | ty:: Uint ( _)
304
+ | ty:: Float ( _)
305
+ | ty:: Adt ( ..)
306
+ | ty:: Str
307
+ | ty:: Array ( ..)
308
+ | ty:: Slice ( ..)
309
+ | ty:: RawPtr ( ..)
310
+ | ty:: Dynamic ( ..)
311
+ | ty:: Ref ( ..)
312
+ | ty:: Never
313
+ | ty:: Tuple ( ..)
314
+ | ty:: FnPtr ( ..)
315
+ | ty:: Foreign ( ..) => false ,
316
+
317
+ ty:: Param ( _) | ty:: Projection ( _) | ty:: Error ( _) => true ,
318
+
319
+ ty:: FnDef ( ..)
320
+ | ty:: Closure ( ..)
321
+ | ty:: Generator ( ..)
322
+ | ty:: GeneratorWitness ( ..)
323
+ | ty:: Placeholder ( ..)
324
+ | ty:: Opaque ( ..)
325
+ | ty:: Bound ( ..)
326
+ | ty:: Infer ( _) => unreachable ! ( ) ,
327
+ } ;
328
+
329
+ maybe_equiv
330
+ }
331
+
217
332
impl < ' cx , ' tcx > SelectionContext < ' cx , ' tcx > {
218
333
pub fn new ( infcx : & ' cx InferCtxt < ' cx , ' tcx > ) -> SelectionContext < ' cx , ' tcx > {
219
334
SelectionContext {
@@ -2142,20 +2257,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2142
2257
|( obligation_arg, impl_arg) | {
2143
2258
match ( obligation_arg. unpack ( ) , impl_arg. unpack ( ) ) {
2144
2259
( GenericArgKind :: Type ( obligation_ty) , GenericArgKind :: Type ( impl_ty) ) => {
2145
- // Note, we simplify parameters for the obligation but not the
2146
- // impl so that we do not reject a blanket impl but do reject
2147
- // more concrete impls if we're searching for `T: Trait`.
2148
- let simplified_obligation_ty = fast_reject:: simplify_type (
2149
- self . tcx ( ) ,
2150
- obligation_ty,
2151
- TreatParams :: AsPlaceholder ,
2152
- ) ;
2153
- let simplified_impl_ty =
2154
- fast_reject:: simplify_type ( self . tcx ( ) , impl_ty, TreatParams :: AsInfer ) ;
2155
-
2156
- simplified_obligation_ty. is_some ( )
2157
- && simplified_impl_ty. is_some ( )
2158
- && simplified_obligation_ty != simplified_impl_ty
2260
+ let tys_definitely_differ = !tys_may_be_equivalent ( obligation_ty, impl_ty) ;
2261
+ tys_definitely_differ
2159
2262
}
2160
2263
( GenericArgKind :: Lifetime ( _) , GenericArgKind :: Lifetime ( _) ) => {
2161
2264
// Lifetimes can never cause a rejection.
0 commit comments