@@ -29,6 +29,8 @@ use rustc_hir::def_id::DefId;
29
29
use rustc_hir:: lang_items:: LangItem ;
30
30
use rustc_infer:: infer:: resolve:: OpportunisticRegionResolver ;
31
31
use rustc_middle:: traits:: select:: OverflowError ;
32
+ use rustc_middle:: ty:: error:: ExpectedFound ;
33
+ use rustc_middle:: ty:: error:: TypeError ;
32
34
use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
33
35
use rustc_middle:: ty:: visit:: { MaxUniverse , TypeVisitable } ;
34
36
use rustc_middle:: ty:: DefIdTree ;
@@ -255,6 +257,7 @@ fn project_and_unify_type<'cx, 'tcx>(
255
257
} ;
256
258
debug ! ( ?normalized, ?obligations, "project_and_unify_type result" ) ;
257
259
let actual = obligation. predicate . term ;
260
+
258
261
// For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
259
262
// This allows users to omit re-mentioning all bounds on an associated type and just use an
260
263
// `impl Trait` for the assoc type to add more bounds.
@@ -267,16 +270,94 @@ fn project_and_unify_type<'cx, 'tcx>(
267
270
) ;
268
271
obligations. extend ( new) ;
269
272
270
- let defer_projection_equality =
271
- normalized. ty ( ) . map_or ( true , |normalized| match normalized. kind ( ) {
272
- ty:: Projection ( proj) => proj != & obligation. predicate . projection_ty ,
273
- _ => true ,
274
- } ) ;
275
- match infcx
276
- . at ( & obligation. cause , obligation. param_env )
277
- . defer_projection_equality ( defer_projection_equality)
278
- . eq ( normalized, actual)
279
- {
273
+ if let Some ( ty) = normalized. ty ( ) {
274
+ if let & ty:: Projection ( projection) = ty. kind ( ) {
275
+ match opt_normalize_projection_type (
276
+ selcx,
277
+ obligation. param_env ,
278
+ projection,
279
+ obligation. cause . clone ( ) ,
280
+ obligation. recursion_depth ,
281
+ & mut obligations,
282
+ ) {
283
+ Ok ( Some ( _) ) => ( ) ,
284
+ Ok ( None ) => {
285
+ debug ! ( "failed normalization of: {:?}" , projection) ;
286
+ return ProjectAndUnifyResult :: FailedNormalization ;
287
+ }
288
+ Err ( InProgress ) => unreachable ! ( ) ,
289
+ }
290
+
291
+ let actual = actual. ty ( ) . unwrap ( ) ;
292
+ let done = match actual. kind ( ) {
293
+ & ty:: Projection ( other) => {
294
+ let flipped_projection_eq = InferOk {
295
+ obligations : vec ! [ Obligation :: new(
296
+ obligation. cause. clone( ) ,
297
+ obligation. param_env,
298
+ ty:: Binder :: dummy( ty:: ProjectionPredicate {
299
+ projection_ty: other,
300
+ term: ty:: Term :: from( ty) ,
301
+ } )
302
+ . to_predicate( selcx. tcx( ) ) ,
303
+ ) ] ,
304
+ value : ( ) ,
305
+ } ;
306
+
307
+ match opt_normalize_projection_type (
308
+ selcx,
309
+ obligation. param_env ,
310
+ other,
311
+ obligation. cause . clone ( ) ,
312
+ obligation. recursion_depth ,
313
+ & mut obligations,
314
+ ) {
315
+ Ok ( Some ( normed_other) ) => match normed_other. ty ( ) . unwrap ( ) . kind ( ) {
316
+ & ty:: Projection ( normed_other) => {
317
+ match opt_normalize_projection_type (
318
+ selcx,
319
+ obligation. param_env ,
320
+ normed_other,
321
+ obligation. cause . clone ( ) ,
322
+ obligation. recursion_depth ,
323
+ & mut obligations,
324
+ ) {
325
+ Ok ( Some ( _) ) => infcx
326
+ . at ( & obligation. cause , obligation. param_env )
327
+ . trace ( ty, actual)
328
+ . eq ( projection, normed_other) ,
329
+ Ok ( None ) => Ok ( flipped_projection_eq) ,
330
+ Err ( InProgress ) => unreachable ! ( ) ,
331
+ }
332
+ }
333
+ ty:: Infer ( _) => {
334
+ infcx. at ( & obligation. cause , obligation. param_env ) . eq ( ty, actual)
335
+ }
336
+ _ => Err ( TypeError :: Sorts ( ExpectedFound :: new ( false , ty, actual) ) ) ,
337
+ } ,
338
+ Ok ( None ) => Ok ( flipped_projection_eq) ,
339
+ Err ( InProgress ) => return ProjectAndUnifyResult :: Recursive ,
340
+ }
341
+ }
342
+ ty:: Infer ( _) => infcx. at ( & obligation. cause , obligation. param_env ) . eq ( ty, actual) ,
343
+ _ => Err ( TypeError :: Sorts ( ExpectedFound :: new ( false , ty, actual) ) ) ,
344
+ } ;
345
+ return match done {
346
+ Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
347
+ obligations. extend ( inferred_obligations) ;
348
+ ProjectAndUnifyResult :: Holds ( obligations)
349
+ }
350
+ Err ( err) => {
351
+ debug ! ( "equating types encountered error {:?}" , err) ;
352
+ ProjectAndUnifyResult :: MismatchedProjectionTypes ( MismatchedProjectionTypes {
353
+ err,
354
+ } )
355
+ }
356
+ } ;
357
+ }
358
+ }
359
+
360
+ match infcx. at ( & obligation. cause , obligation. param_env ) . eq ( normalized, actual) {
280
361
Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
281
362
obligations. extend ( inferred_obligations) ;
282
363
ProjectAndUnifyResult :: Holds ( obligations)
0 commit comments