@@ -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,49 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
108
109
std:: borrow:: Cow :: from ( args)
109
110
} ;
110
111
111
- let clean_middle_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_middle_arg = |( index, arg) : ( usize , & ty:: GenericArg < ' tcx > ) | {
113
+ // Elide the self type.
114
+ if has_self && index == 0 {
115
+ return None ;
114
116
}
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. params [ index] . 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
117
127
- elision_has_failed_once_before = true ;
118
+ // Elide internal host effect args.
119
+ if let ty:: GenericParamDefKind :: Const { is_host_effect : true , .. } =
120
+ generics. params [ index] . kind
121
+ {
122
+ return None ;
123
+ }
124
+
125
+ let arg = ty:: Binder :: bind_with_vars ( * arg, bound_vars) ;
126
+
127
+ // Elide arguments that coincide with their default.
128
+ if !elision_has_failed_once_before
129
+ && let Some ( default) = generics. params [ index] . default_value ( cx. tcx )
130
+ {
131
+ let default = default. instantiate ( cx. tcx , args. as_ref ( ) ) ;
132
+ if can_elide_generic_arg ( arg, arg. rebind ( default) ) {
133
+ return None ;
128
134
}
135
+ elision_has_failed_once_before = true ;
136
+ }
129
137
130
- Some ( GenericArg :: Type ( clean_middle_ty (
131
- ty,
138
+ match arg. skip_binder ( ) . unpack ( ) {
139
+ GenericArgKind :: Lifetime ( lt) => {
140
+ Some ( GenericArg :: Lifetime ( clean_middle_region ( lt) . unwrap_or ( Lifetime :: elided ( ) ) ) )
141
+ }
142
+ GenericArgKind :: Type ( ty) => Some ( GenericArg :: Type ( clean_middle_ty (
143
+ arg. rebind ( ty) ,
132
144
cx,
133
145
None ,
134
146
Some ( crate :: clean:: ContainerTy :: Regular {
135
147
ty : owner,
136
- args : ty . rebind ( args. as_ref ( ) ) ,
148
+ args : arg . rebind ( args. as_ref ( ) ) ,
137
149
arg : index,
138
150
} ) ,
139
- ) ) )
140
- }
141
- GenericArgKind :: Const ( ct) => {
142
- if let ty:: GenericParamDefKind :: Const { is_host_effect : true , .. } =
143
- generics. params [ index] . kind
144
- {
145
- return None ;
151
+ ) ) ) ,
152
+ GenericArgKind :: Const ( ct) => {
153
+ Some ( GenericArg :: Const ( Box :: new ( clean_middle_const ( arg. rebind ( ct) , cx) ) ) )
146
154
}
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. params [ index] . 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
155
}
163
156
} ;
164
157
@@ -172,13 +165,17 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
172
165
/// This uses a very conservative approach for performance and correctness reasons, meaning for
173
166
/// several classes of terms it claims that they cannot be elided even if they theoretically could.
174
167
/// 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
- {
168
+ fn can_elide_generic_arg < ' tcx > (
169
+ actual : ty:: Binder < ' tcx , ty:: GenericArg < ' tcx > > ,
170
+ default : ty:: Binder < ' tcx , ty:: GenericArg < ' tcx > > ,
171
+ ) -> bool {
172
+ debug_assert_matches ! (
173
+ ( actual. skip_binder( ) . unpack( ) , default . skip_binder( ) . unpack( ) ) ,
174
+ ( ty:: GenericArgKind :: Lifetime ( _) , ty:: GenericArgKind :: Lifetime ( _) )
175
+ | ( ty:: GenericArgKind :: Type ( _) , ty:: GenericArgKind :: Type ( _) )
176
+ | ( ty:: GenericArgKind :: Const ( _) , ty:: GenericArgKind :: Const ( _) )
177
+ ) ;
178
+
182
179
// In practice, we shouldn't have any inference variables at this point.
183
180
// However to be safe, we bail out if we do happen to stumble upon them.
184
181
if actual. has_infer ( ) || default. has_infer ( ) {
0 commit comments