@@ -29,6 +29,8 @@ use rustc_hir::def_id::DefId;
2929use rustc_hir:: lang_items:: LangItem ;
3030use rustc_infer:: infer:: resolve:: OpportunisticRegionResolver ;
3131use rustc_middle:: traits:: select:: OverflowError ;
32+ use rustc_middle:: ty:: error:: ExpectedFound ;
33+ use rustc_middle:: ty:: error:: TypeError ;
3234use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
3335use rustc_middle:: ty:: visit:: { MaxUniverse , TypeVisitable } ;
3436use rustc_middle:: ty:: DefIdTree ;
@@ -255,6 +257,7 @@ fn project_and_unify_type<'cx, 'tcx>(
255257 } ;
256258 debug ! ( ?normalized, ?obligations, "project_and_unify_type result" ) ;
257259 let actual = obligation. predicate . term ;
260+
258261 // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
259262 // This allows users to omit re-mentioning all bounds on an associated type and just use an
260263 // `impl Trait` for the assoc type to add more bounds.
@@ -267,16 +270,94 @@ fn project_and_unify_type<'cx, 'tcx>(
267270 ) ;
268271 obligations. extend ( new) ;
269272
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) {
280361 Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
281362 obligations. extend ( inferred_obligations) ;
282363 ProjectAndUnifyResult :: Holds ( obligations)
0 commit comments