@@ -16,9 +16,10 @@ use rustc_hir::def::{DefKind, Res};
1616use rustc_hir:: def_id:: { DefId , LocalDefId , LOCAL_CRATE } ;
1717use rustc_metadata:: rendered_const;
1818use rustc_middle:: mir;
19+ use rustc_middle:: ty:: TypeVisitableExt ;
1920use rustc_middle:: ty:: { self , GenericArgKind , GenericArgsRef , TyCtxt } ;
20- use rustc_middle:: ty:: { TypeVisitable , TypeVisitableExt } ;
2121use rustc_span:: symbol:: { kw, sym, Symbol } ;
22+ use std:: assert_matches:: debug_assert_matches;
2223use std:: fmt:: Write as _;
2324use std:: mem;
2425use std:: sync:: LazyLock as Lazy ;
@@ -108,57 +109,46 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
108109 std:: borrow:: Cow :: from ( args)
109110 } ;
110111
111- let clean_arg = |( index, arg) : ( usize , & ty:: GenericArg < ' tcx > ) | match arg. unpack ( ) {
112- GenericArgKind :: Lifetime ( lt) => {
113- Some ( GenericArg :: Lifetime ( clean_middle_region ( lt) . unwrap_or ( Lifetime :: elided ( ) ) ) )
112+ let clean_arg = |( index, & arg) : ( usize , & ty:: GenericArg < ' tcx > ) | {
113+ // Elide the self type.
114+ if has_self && index == 0 {
115+ return None ;
116+ }
117+
118+ // Elide internal host effect args.
119+ let param = generics. param_at ( index, cx. tcx ) ;
120+ if param. is_host_effect ( ) {
121+ return None ;
114122 }
115- GenericArgKind :: Type ( _) if has_self && index == 0 => None ,
116- GenericArgKind :: Type ( ty) => {
117- let ty = ty:: Binder :: bind_with_vars ( ty, bound_vars) ;
118-
119- if !elision_has_failed_once_before
120- && let Some ( default) = generics. param_at ( index, cx. tcx ) . default_value ( cx. tcx )
121- {
122- let default = default. instantiate ( cx. tcx , args. as_ref ( ) ) . expect_ty ( ) ;
123- if can_elide_generic_arg ( ty, ty. rebind ( default) ) {
124- return None ;
125- }
126123
127- elision_has_failed_once_before = true ;
124+ let arg = ty:: Binder :: bind_with_vars ( arg, bound_vars) ;
125+
126+ // Elide arguments that coincide with their default.
127+ if !elision_has_failed_once_before && let Some ( default) = param. default_value ( cx. tcx ) {
128+ let default = default. instantiate ( cx. tcx , args. as_ref ( ) ) ;
129+ if can_elide_generic_arg ( arg, arg. rebind ( default) ) {
130+ return None ;
128131 }
132+ elision_has_failed_once_before = true ;
133+ }
129134
130- Some ( GenericArg :: Type ( clean_middle_ty (
131- ty,
135+ match arg. skip_binder ( ) . unpack ( ) {
136+ GenericArgKind :: Lifetime ( lt) => {
137+ Some ( GenericArg :: Lifetime ( clean_middle_region ( lt) . unwrap_or ( Lifetime :: elided ( ) ) ) )
138+ }
139+ GenericArgKind :: Type ( ty) => Some ( GenericArg :: Type ( clean_middle_ty (
140+ arg. rebind ( ty) ,
132141 cx,
133142 None ,
134143 Some ( crate :: clean:: ContainerTy :: Regular {
135144 ty : owner,
136- args : ty . rebind ( args. as_ref ( ) ) ,
145+ args : arg . rebind ( args. as_ref ( ) ) ,
137146 arg : index,
138147 } ) ,
139- ) ) )
140- }
141- GenericArgKind :: Const ( ct) => {
142- if let ty:: GenericParamDefKind :: Const { is_host_effect : true , .. } =
143- generics. param_at ( index, cx. tcx ) . kind
144- {
145- return None ;
148+ ) ) ) ,
149+ GenericArgKind :: Const ( ct) => {
150+ Some ( GenericArg :: Const ( Box :: new ( clean_middle_const ( arg. rebind ( ct) , cx) ) ) )
146151 }
147-
148- let ct = ty:: Binder :: bind_with_vars ( ct, bound_vars) ;
149-
150- if !elision_has_failed_once_before
151- && let Some ( default) = generics. param_at ( index, cx. tcx ) . default_value ( cx. tcx )
152- {
153- let default = default. instantiate ( cx. tcx , args. as_ref ( ) ) . expect_const ( ) ;
154- if can_elide_generic_arg ( ct, ct. rebind ( default) ) {
155- return None ;
156- }
157-
158- elision_has_failed_once_before = true ;
159- }
160-
161- Some ( GenericArg :: Const ( Box :: new ( clean_middle_const ( ct, cx) ) ) )
162152 }
163153 } ;
164154
@@ -172,13 +162,17 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
172162/// This uses a very conservative approach for performance and correctness reasons, meaning for
173163/// several classes of terms it claims that they cannot be elided even if they theoretically could.
174164/// This is absolutely fine since it mostly concerns edge cases.
175- fn can_elide_generic_arg < ' tcx , Term > (
176- actual : ty:: Binder < ' tcx , Term > ,
177- default : ty:: Binder < ' tcx , Term > ,
178- ) -> bool
179- where
180- Term : Eq + TypeVisitable < TyCtxt < ' tcx > > ,
181- {
165+ fn can_elide_generic_arg < ' tcx > (
166+ actual : ty:: Binder < ' tcx , ty:: GenericArg < ' tcx > > ,
167+ default : ty:: Binder < ' tcx , ty:: GenericArg < ' tcx > > ,
168+ ) -> bool {
169+ debug_assert_matches ! (
170+ ( actual. skip_binder( ) . unpack( ) , default . skip_binder( ) . unpack( ) ) ,
171+ ( ty:: GenericArgKind :: Lifetime ( _) , ty:: GenericArgKind :: Lifetime ( _) )
172+ | ( ty:: GenericArgKind :: Type ( _) , ty:: GenericArgKind :: Type ( _) )
173+ | ( ty:: GenericArgKind :: Const ( _) , ty:: GenericArgKind :: Const ( _) )
174+ ) ;
175+
182176 // In practice, we shouldn't have any inference variables at this point.
183177 // However to be safe, we bail out if we do happen to stumble upon them.
184178 if actual. has_infer ( ) || default. has_infer ( ) {
0 commit comments