@@ -16,9 +16,10 @@ use rustc_hir::def::{DefKind, Res};
16
16
use rustc_hir:: def_id:: { DefId , LocalDefId , LOCAL_CRATE } ;
17
17
use rustc_metadata:: rendered_const;
18
18
use rustc_middle:: mir;
19
+ use rustc_middle:: ty:: TypeVisitableExt ;
19
20
use rustc_middle:: ty:: { self , GenericArgKind , GenericArgsRef , TyCtxt } ;
20
- use rustc_middle:: ty:: { TypeVisitable , TypeVisitableExt } ;
21
21
use rustc_span:: symbol:: { kw, sym, Symbol } ;
22
+ use std:: assert_matches:: debug_assert_matches;
22
23
use std:: fmt:: Write as _;
23
24
use std:: mem;
24
25
use std:: sync:: LazyLock as Lazy ;
@@ -108,57 +109,46 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
108
109
std:: borrow:: Cow :: from ( args)
109
110
} ;
110
111
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 ;
114
122
}
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
- }
126
123
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 ;
128
131
}
132
+ elision_has_failed_once_before = true ;
133
+ }
129
134
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) ,
132
141
cx,
133
142
None ,
134
143
Some ( crate :: clean:: ContainerTy :: Regular {
135
144
ty : owner,
136
- args : ty . rebind ( args. as_ref ( ) ) ,
145
+ args : arg . rebind ( args. as_ref ( ) ) ,
137
146
arg : index,
138
147
} ) ,
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) ) ) )
146
151
}
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) ) ) )
162
152
}
163
153
} ;
164
154
@@ -172,13 +162,17 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
172
162
/// This uses a very conservative approach for performance and correctness reasons, meaning for
173
163
/// several classes of terms it claims that they cannot be elided even if they theoretically could.
174
164
/// 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
+
182
176
// In practice, we shouldn't have any inference variables at this point.
183
177
// However to be safe, we bail out if we do happen to stumble upon them.
184
178
if actual. has_infer ( ) || default. has_infer ( ) {
0 commit comments