@@ -83,85 +83,132 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
83
83
pub ( crate ) fn ty_args_to_args < ' tcx > (
84
84
cx : & mut DocContext < ' tcx > ,
85
85
ty_args : ty:: Binder < ' tcx , & ' tcx [ ty:: GenericArg < ' tcx > ] > ,
86
- skip_first : bool ,
86
+ has_self : bool ,
87
87
container : Option < DefId > ,
88
88
) -> Vec < GenericArg > {
89
+ let tcx = cx. tcx ;
90
+ let bound_vars = ty_args. bound_vars ( ) ;
91
+ let ty_args = ty_args. skip_binder ( ) ;
92
+
93
+ let offset = if has_self { 1 } else { 0 } ;
94
+ let mut args = Vec :: with_capacity ( ty_args. len ( ) . saturating_sub ( offset) ) ;
95
+
96
+ let params = container. map ( |container| & tcx. generics_of ( container) . params ) ;
97
+ let ( req_args, opt_args) = if let Some ( params) = params {
98
+ let partition_point = params
99
+ . iter ( )
100
+ . rposition ( |param| match param. kind {
101
+ ty:: GenericParamDefKind :: Lifetime => false ,
102
+ ty:: GenericParamDefKind :: Type { has_default, .. } => has_default,
103
+ ty:: GenericParamDefKind :: Const { has_default } => has_default,
104
+ } )
105
+ // FIXME: using `offset` here might not be entirely correct
106
+ . unwrap_or ( offset) ;
107
+ ty_args. split_at ( partition_point)
108
+ } else {
109
+ ( ty_args, & [ ] as _ )
110
+ } ;
111
+
112
+ args. extend ( req_args. iter ( ) . enumerate ( ) . filter_map ( |( index, arg) | {
113
+ ty_arg_to_arg ( cx, index, arg, has_self, container, ty_args, bound_vars)
114
+ } ) ) ;
115
+
116
+ let skipped_self = args. len ( ) != req_args. len ( ) ;
89
117
let param_env = ty:: ParamEnv :: empty ( ) ;
90
118
let cause = ObligationCause :: dummy ( ) ;
91
- let params = container. map ( |container| & cx. tcx . generics_of ( container) . params ) ;
92
119
let mut elision_has_failed_once_before = false ;
93
120
94
- let offset = if skip_first { 1 } else { 0 } ;
95
- let mut args = Vec :: with_capacity ( ty_args. skip_binder ( ) . len ( ) . saturating_sub ( offset) ) ;
96
-
97
- let ty_arg_to_arg = |( index, arg) : ( usize , & ty:: GenericArg < ' tcx > ) | match arg. unpack ( ) {
98
- GenericArgKind :: Lifetime ( lt) => {
99
- Some ( GenericArg :: Lifetime ( clean_middle_region ( lt) . unwrap_or ( Lifetime :: elided ( ) ) ) )
100
- }
101
- GenericArgKind :: Type ( _) if skip_first && index == 0 => None ,
102
- GenericArgKind :: Type ( ty) => {
103
- if !elision_has_failed_once_before
104
- && let Some ( params) = params
105
- && let Some ( default) = params[ index] . default_value ( cx. tcx )
106
- {
107
- let default =
108
- ty_args. map_bound ( |args| default. instantiate ( cx. tcx , args) . expect_ty ( ) ) ;
109
-
110
- if can_elide_generic_arg (
111
- cx. tcx ,
112
- & cause,
113
- param_env,
114
- ty_args. rebind ( ty) ,
115
- default,
116
- params[ index] . def_id ,
117
- ) {
118
- return None ;
121
+ args. extend (
122
+ ( req_args. len ( ) ..ty_args. len ( ) )
123
+ . zip ( opt_args)
124
+ . rev ( )
125
+ . filter ( |& ( index, arg) | match arg. unpack ( ) {
126
+ GenericArgKind :: Lifetime ( _) => true ,
127
+ GenericArgKind :: Type ( ty) => {
128
+ if !elision_has_failed_once_before
129
+ && let Some ( params) = params
130
+ && let Some ( default) = params[ index] . default_value ( tcx)
131
+ {
132
+ let default = default. instantiate ( tcx, ty_args) . expect_ty ( ) ;
133
+
134
+ if can_elide_generic_arg (
135
+ tcx,
136
+ & cause,
137
+ param_env,
138
+ ty:: Binder :: bind_with_vars ( ty, bound_vars) ,
139
+ ty:: Binder :: bind_with_vars ( default, bound_vars) ,
140
+ params[ index] . def_id ,
141
+ ) {
142
+ return false
143
+ }
144
+
145
+ elision_has_failed_once_before = true ;
146
+ }
147
+
148
+ true
119
149
}
120
-
121
- elision_has_failed_once_before = true ;
122
- }
123
-
124
- Some ( GenericArg :: Type ( clean_middle_ty (
125
- ty_args. rebind ( ty) ,
126
- cx,
127
- None ,
128
- container. map ( |container| crate :: clean:: ContainerTy :: Regular {
129
- ty : container,
130
- args : ty_args,
131
- arg : index,
132
- } ) ,
133
- ) ) )
134
- }
135
- GenericArgKind :: Const ( ct) => {
136
- if !elision_has_failed_once_before
137
- && let Some ( params) = params
138
- && let Some ( default) = params[ index] . default_value ( cx. tcx )
139
- {
140
- let default =
141
- ty_args. map_bound ( |args| default. instantiate ( cx. tcx , args) . expect_const ( ) ) ;
142
-
143
- if can_elide_generic_arg (
144
- cx. tcx ,
145
- & cause,
146
- param_env,
147
- ty_args. rebind ( ct) ,
148
- default,
149
- params[ index] . def_id ,
150
- ) {
151
- return None ;
150
+ GenericArgKind :: Const ( ct) => {
151
+ if !elision_has_failed_once_before
152
+ && let Some ( params) = params
153
+ && let Some ( default) = params[ index] . default_value ( tcx)
154
+ {
155
+ let default = default. instantiate ( tcx, ty_args) . expect_const ( ) ;
156
+
157
+ if can_elide_generic_arg (
158
+ tcx,
159
+ & cause,
160
+ param_env,
161
+ ty:: Binder :: bind_with_vars ( ct, bound_vars) ,
162
+ ty:: Binder :: bind_with_vars ( default, bound_vars) ,
163
+ params[ index] . def_id ,
164
+ ) {
165
+ return false ;
166
+ }
167
+
168
+ elision_has_failed_once_before = true ;
169
+ }
170
+
171
+ true
152
172
}
173
+ } )
174
+ . filter_map ( |( index, arg) | {
175
+ ty_arg_to_arg ( cx, index, arg, false , container, ty_args, bound_vars)
176
+ } ) ,
177
+ ) ;
178
+ args[ req_args. len ( ) . saturating_sub ( if skipped_self { 1 } else { 0 } ) ..] . reverse ( ) ;
153
179
154
- elision_has_failed_once_before = true ;
155
- }
180
+ args
181
+ }
156
182
157
- Some ( GenericArg :: Const ( Box :: new ( clean_middle_const ( ty_args. rebind ( ct) , cx) ) ) )
183
+ fn ty_arg_to_arg < ' tcx > (
184
+ cx : & mut DocContext < ' tcx > ,
185
+ index : usize ,
186
+ arg : & ty:: GenericArg < ' tcx > ,
187
+ has_self : bool ,
188
+ container : Option < DefId > ,
189
+ ty_args : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
190
+ bound_vars : & ' tcx ty:: List < ty:: BoundVariableKind > ,
191
+ ) -> Option < GenericArg > {
192
+ match arg. unpack ( ) {
193
+ GenericArgKind :: Lifetime ( lt) => {
194
+ Some ( GenericArg :: Lifetime ( clean_middle_region ( lt) . unwrap_or ( Lifetime :: elided ( ) ) ) )
158
195
}
159
- } ;
160
-
161
- // FIXME(fmease): This doesn't look performant to me!
162
- args. extend ( ty_args. skip_binder ( ) . iter ( ) . enumerate ( ) . rev ( ) . filter_map ( ty_arg_to_arg) ) ;
163
- args. reverse ( ) ;
164
- args
196
+ GenericArgKind :: Type ( _) if has_self && index == 0 => None ,
197
+ GenericArgKind :: Type ( ty) => Some ( GenericArg :: Type ( clean_middle_ty (
198
+ ty:: Binder :: bind_with_vars ( ty, bound_vars) ,
199
+ cx,
200
+ None ,
201
+ container. map ( |container| crate :: clean:: ContainerTy :: Regular {
202
+ ty : container,
203
+ args : ty:: Binder :: bind_with_vars ( ty_args, bound_vars) ,
204
+ arg : index,
205
+ } ) ,
206
+ ) ) ) ,
207
+ GenericArgKind :: Const ( ct) => Some ( GenericArg :: Const ( Box :: new ( clean_middle_const (
208
+ ty:: Binder :: bind_with_vars ( ct, bound_vars) ,
209
+ cx,
210
+ ) ) ) ) ,
211
+ }
165
212
}
166
213
167
214
fn can_elide_generic_arg < ' tcx , T : ToTrace < ' tcx > + TypeVisitable < TyCtxt < ' tcx > > > (
0 commit comments