@@ -12,7 +12,6 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
12
12
use rustc_middle:: { bug, span_bug} ;
13
13
use rustc_span:: symbol:: Ident ;
14
14
use rustc_span:: { DUMMY_SP , Span } ;
15
- use tracing:: debug;
16
15
17
16
use super :: { ItemCtxt , bad_placeholder} ;
18
17
use crate :: errors:: TypeofReservedKeywordUsed ;
@@ -138,252 +137,26 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
138
137
use hir:: * ;
139
138
use rustc_middle:: ty:: Ty ;
140
139
141
- let parent_node_id = tcx. parent_hir_id ( arg_hir_id) ;
142
- let parent_node = tcx. hir_node ( parent_node_id) ;
143
-
144
- let ( generics, arg_idx) = match parent_node {
145
- // Easy case: arrays repeat expressions.
140
+ match tcx. parent_hir_node ( arg_hir_id) {
141
+ // Array length const arguments do not have `type_of` fed as there is never a corresponding
142
+ // generic parameter definition.
146
143
Node :: Ty ( & hir:: Ty { kind : TyKind :: Array ( _, ref constant) , .. } )
147
144
| Node :: Expr ( & Expr { kind : ExprKind :: Repeat ( _, ref constant) , .. } )
148
145
if constant. hir_id == arg_hir_id =>
149
146
{
150
147
return tcx. types . usize ;
151
148
}
152
- Node :: GenericParam ( & GenericParam {
153
- def_id : param_def_id,
154
- kind : GenericParamKind :: Const { default : Some ( ct) , .. } ,
155
- ..
156
- } ) if ct. hir_id == arg_hir_id => {
157
- return tcx
158
- . type_of ( param_def_id)
159
- . no_bound_vars ( )
160
- . expect ( "const parameter types cannot be generic" ) ;
161
- }
162
-
163
- // This match arm is for when the def_id appears in a GAT whose
164
- // path can't be resolved without typechecking e.g.
165
- //
166
- // trait Foo {
167
- // type Assoc<const N: usize>;
168
- // fn foo() -> Self::Assoc<3>;
169
- // }
170
- //
171
- // In the above code we would call this query with the def_id of 3 and
172
- // the parent_node we match on would be the hir node for Self::Assoc<3>
173
- //
174
- // `Self::Assoc<3>` cant be resolved without typechecking here as we
175
- // didnt write <Self as Foo>::Assoc<3>. If we did then another match
176
- // arm would handle this.
177
- //
178
- // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
179
- Node :: Ty ( hir_ty @ hir:: Ty { kind : TyKind :: Path ( QPath :: TypeRelative ( ty, segment) ) , .. } ) => {
180
- // Find the Item containing the associated type so we can create an ItemCtxt.
181
- // Using the ItemCtxt lower the HIR for the unresolved assoc type into a
182
- // ty which is a fully resolved projection.
183
- // For the code example above, this would mean lowering `Self::Assoc<3>`
184
- // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
185
- let item_def_id = tcx. hir ( ) . get_parent_item ( ty. hir_id ) . def_id ;
186
- let ty = ItemCtxt :: new ( tcx, item_def_id) . lower_ty ( hir_ty) ;
187
-
188
- // Iterate through the generics of the projection to find the one that corresponds to
189
- // the def_id that this query was called with. We filter to only type and const args here
190
- // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
191
- // but it can't hurt to be safe ^^
192
- if let ty:: Alias ( ty:: Projection | ty:: Inherent , projection) = ty. kind ( ) {
193
- let generics = tcx. generics_of ( projection. def_id ) ;
194
-
195
- let arg_index = segment
196
- . args
197
- . and_then ( |args| {
198
- args. args
199
- . iter ( )
200
- . filter ( |arg| arg. is_ty_or_const ( ) )
201
- . position ( |arg| arg. hir_id ( ) == arg_hir_id)
202
- } )
203
- . unwrap_or_else ( || {
204
- bug ! ( "no arg matching AnonConst in segment" ) ;
205
- } ) ;
206
-
207
- ( generics, arg_index)
208
- } else {
209
- // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
210
- return Ty :: new_error_with_message (
211
- tcx,
212
- span,
213
- "unexpected non-GAT usage of an anon const" ,
214
- ) ;
215
- }
216
- }
217
- Node :: Expr ( & Expr {
218
- kind :
219
- ExprKind :: MethodCall ( segment, ..) | ExprKind :: Path ( QPath :: TypeRelative ( _, segment) ) ,
220
- ..
221
- } ) => {
222
- let body_owner = tcx. hir ( ) . enclosing_body_owner ( arg_hir_id) ;
223
- let tables = tcx. typeck ( body_owner) ;
224
- // This may fail in case the method/path does not actually exist.
225
- // As there is no relevant param for `def_id`, we simply return
226
- // `None` here.
227
- let Some ( type_dependent_def) = tables. type_dependent_def_id ( parent_node_id) else {
228
- return Ty :: new_error_with_message (
229
- tcx,
230
- span,
231
- format ! ( "unable to find type-dependent def for {parent_node_id:?}" ) ,
232
- ) ;
233
- } ;
234
- let idx = segment
235
- . args
236
- . and_then ( |args| {
237
- args. args
238
- . iter ( )
239
- . filter ( |arg| arg. is_ty_or_const ( ) )
240
- . position ( |arg| arg. hir_id ( ) == arg_hir_id)
241
- } )
242
- . unwrap_or_else ( || {
243
- bug ! ( "no arg matching ConstArg in segment" ) ;
244
- } ) ;
245
-
246
- ( tcx. generics_of ( type_dependent_def) , idx)
247
- }
248
-
249
- Node :: Ty ( & hir:: Ty { kind : TyKind :: Path ( _) , .. } )
250
- | Node :: Expr ( & Expr { kind : ExprKind :: Path ( _) | ExprKind :: Struct ( ..) , .. } )
251
- | Node :: TraitRef ( ..)
252
- | Node :: Pat ( _) => {
253
- let path = match parent_node {
254
- Node :: Ty ( & hir:: Ty { kind : TyKind :: Path ( QPath :: Resolved ( _, path) ) , .. } )
255
- | Node :: TraitRef ( & TraitRef { path, .. } ) => & * path,
256
- Node :: Expr ( & Expr {
257
- kind :
258
- ExprKind :: Path ( QPath :: Resolved ( _, path) )
259
- | ExprKind :: Struct ( & QPath :: Resolved ( _, path) , ..) ,
260
- ..
261
- } ) => {
262
- let body_owner = tcx. hir ( ) . enclosing_body_owner ( arg_hir_id) ;
263
- let _tables = tcx. typeck ( body_owner) ;
264
- & * path
265
- }
266
- Node :: Pat ( pat) => {
267
- if let Some ( path) = get_path_containing_arg_in_pat ( pat, arg_hir_id) {
268
- path
269
- } else {
270
- return Ty :: new_error_with_message (
271
- tcx,
272
- span,
273
- format ! ( "unable to find const parent for {arg_hir_id} in pat {pat:?}" ) ,
274
- ) ;
275
- }
276
- }
277
- _ => {
278
- return Ty :: new_error_with_message (
279
- tcx,
280
- span,
281
- format ! ( "unexpected const parent path {parent_node:?}" ) ,
282
- ) ;
283
- }
284
- } ;
285
-
286
- // We've encountered an `AnonConst` in some path, so we need to
287
- // figure out which generic parameter it corresponds to and return
288
- // the relevant type.
289
- let Some ( ( arg_index, segment) ) = path. segments . iter ( ) . find_map ( |seg| {
290
- let args = seg. args ?;
291
- args. args
292
- . iter ( )
293
- . filter ( |arg| arg. is_ty_or_const ( ) )
294
- . position ( |arg| arg. hir_id ( ) == arg_hir_id)
295
- . map ( |index| ( index, seg) )
296
- . or_else ( || {
297
- args. constraints
298
- . iter ( )
299
- . copied ( )
300
- . filter_map ( AssocItemConstraint :: ct)
301
- . position ( |ct| ct. hir_id == arg_hir_id)
302
- . map ( |idx| ( idx, seg) )
303
- } )
304
- } ) else {
305
- return Ty :: new_error_with_message ( tcx, span, "no arg matching AnonConst in path" ) ;
306
- } ;
307
-
308
- let generics = match tcx. res_generics_def_id ( segment. res ) {
309
- Some ( def_id) => tcx. generics_of ( def_id) ,
310
- None => {
311
- return Ty :: new_error_with_message (
312
- tcx,
313
- span,
314
- format ! ( "unexpected anon const res {:?} in path: {:?}" , segment. res, path) ,
315
- ) ;
316
- }
317
- } ;
318
-
319
- ( generics, arg_index)
320
- }
321
149
322
- _ => {
323
- return Ty :: new_error_with_message (
324
- tcx,
325
- span,
326
- format ! ( "unexpected const arg parent in type_of(): {parent_node:?}" ) ,
327
- ) ;
328
- }
329
- } ;
330
-
331
- debug ! ( ?parent_node) ;
332
- debug ! ( ?generics, ?arg_idx) ;
333
- if let Some ( param_def_id) = generics
334
- . own_params
335
- . iter ( )
336
- . filter ( |param| param. kind . is_ty_or_const ( ) )
337
- . nth ( match generics. has_self && generics. parent . is_none ( ) {
338
- true => arg_idx + 1 ,
339
- false => arg_idx,
340
- } )
341
- . and_then ( |param| match param. kind {
342
- ty:: GenericParamDefKind :: Const { .. } => {
343
- debug ! ( ?param) ;
344
- Some ( param. def_id )
345
- }
346
- _ => None ,
347
- } )
348
- {
349
- tcx. type_of ( param_def_id) . no_bound_vars ( ) . expect ( "const parameter types cannot be generic" )
350
- } else {
351
- return Ty :: new_error_with_message (
150
+ // This is not a `bug!` as const arguments in path segments that did not resolve to anything
151
+ // will result in `type_of` never being fed.
152
+ _ => Ty :: new_error_with_message (
352
153
tcx,
353
154
span,
354
- format ! ( " const generic parameter not found in {generics:?} at position {arg_idx:?}" ) ,
355
- ) ;
155
+ "`type_of` called on const argument's anon const before the const argument was lowered" ,
156
+ ) ,
356
157
}
357
158
}
358
159
359
- fn get_path_containing_arg_in_pat < ' hir > (
360
- pat : & ' hir hir:: Pat < ' hir > ,
361
- arg_id : HirId ,
362
- ) -> Option < & ' hir hir:: Path < ' hir > > {
363
- use hir:: * ;
364
-
365
- let is_arg_in_path = |p : & hir:: Path < ' _ > | {
366
- p. segments
367
- . iter ( )
368
- . filter_map ( |seg| seg. args )
369
- . flat_map ( |args| args. args )
370
- . any ( |arg| arg. hir_id ( ) == arg_id)
371
- } ;
372
- let mut arg_path = None ;
373
- pat. walk ( |pat| match pat. kind {
374
- PatKind :: Struct ( QPath :: Resolved ( _, path) , _, _)
375
- | PatKind :: TupleStruct ( QPath :: Resolved ( _, path) , _, _)
376
- | PatKind :: Path ( QPath :: Resolved ( _, path) )
377
- if is_arg_in_path ( path) =>
378
- {
379
- arg_path = Some ( path) ;
380
- false
381
- }
382
- _ => true ,
383
- } ) ;
384
- arg_path
385
- }
386
-
387
160
pub ( super ) fn type_of ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> ty:: EarlyBinder < ' _ , Ty < ' _ > > {
388
161
use rustc_hir:: * ;
389
162
use rustc_middle:: ty:: Ty ;
0 commit comments