@@ -21,7 +21,7 @@ use rustc_hir::{
2121 TraitItemKind , TyKind , UnOp ,
2222} ;
2323use rustc_index:: bit_set:: BitSet ;
24- use rustc_infer:: infer:: TyCtxtInferExt ;
24+ use rustc_infer:: infer:: { InferOk , TyCtxtInferExt } ;
2525use rustc_lint:: { LateContext , LateLintPass } ;
2626use rustc_middle:: mir:: { Rvalue , StatementKind } ;
2727use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
@@ -31,8 +31,9 @@ use rustc_middle::ty::{
3131} ;
3232use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
3333use rustc_span:: { symbol:: sym, Span , Symbol } ;
34- use rustc_trait_selection:: infer:: InferCtxtExt as _;
35- use rustc_trait_selection:: traits:: { query:: evaluate_obligation:: InferCtxtExt as _, Obligation , ObligationCause } ;
34+ use rustc_trait_selection:: infer:: { canonical:: OriginalQueryValues , InferCtxtExt as _} ;
35+ use rustc_trait_selection:: traits:: query:: { evaluate_obligation:: InferCtxtExt as _, NormalizationResult } ;
36+ use rustc_trait_selection:: traits:: { Obligation , ObligationCause } ;
3637use std:: collections:: VecDeque ;
3738
3839declare_clippy_lint ! {
@@ -1359,13 +1360,30 @@ fn replace_types<'tcx>(
13591360 {
13601361 let item_def_id = projection_predicate. projection_ty . def_id ;
13611362 let assoc_item = cx. tcx . associated_item ( item_def_id) ;
1362- let projection = cx. tcx
1363- . mk_projection ( assoc_item. def_id , cx. tcx . mk_substs_trait ( new_ty, [ ] ) ) ;
1364-
1365- if let Ok ( projected_ty) = cx. tcx . try_normalize_erasing_regions ( cx. param_env , projection)
1366- && substs[ term_param_ty. index as usize ] != ty:: GenericArg :: from ( projected_ty)
1363+ let alias_ty = cx
1364+ . tcx
1365+ . mk_alias_ty ( assoc_item. def_id , cx. tcx . mk_substs_trait ( new_ty, [ ] ) ) ;
1366+
1367+ // The following normalization method is based on:
1368+ // https://github.com/rust-lang/rust/blob/695072daa6cc04045f2aa79d751d884ad5263080/compiler/rustc_trait_selection/src/traits/query/normalize.rs#L258-L285
1369+ // It is meant to address: https://github.com/rust-lang/rust/issues/107877
1370+ let infcx = cx. tcx . infer_ctxt ( ) . build ( ) ;
1371+ let mut orig_values = OriginalQueryValues :: default ( ) ;
1372+ let canonical_ty =
1373+ infcx. canonicalize_query_keep_static ( cx. param_env . and ( alias_ty) , & mut orig_values) ;
1374+
1375+ if let Ok ( result) = cx. tcx . normalize_projection_ty ( canonical_ty)
1376+ && !result. is_ambiguous ( )
1377+ && let Ok ( InferOk { value : NormalizationResult { normalized_ty, .. } , .. } ) =
1378+ infcx. instantiate_query_response_and_region_obligations (
1379+ & ObligationCause :: dummy ( ) ,
1380+ cx. param_env ,
1381+ & orig_values,
1382+ result,
1383+ )
1384+ && substs[ term_param_ty. index as usize ] != ty:: GenericArg :: from ( normalized_ty)
13671385 {
1368- deque. push_back ( ( * term_param_ty, projected_ty ) ) ;
1386+ deque. push_back ( ( * term_param_ty, normalized_ty ) ) ;
13691387 }
13701388 }
13711389 }
0 commit comments