1
1
use rustc_errors:: { Applicability , StashKey } ;
2
2
use rustc_hir as hir;
3
- use rustc_hir:: def_id:: { DefId , LocalDefId } ;
3
+ use rustc_hir:: def_id:: LocalDefId ;
4
4
use rustc_hir:: intravisit;
5
5
use rustc_hir:: intravisit:: Visitor ;
6
6
use rustc_hir:: { HirId , Node } ;
@@ -16,22 +16,81 @@ use super::ItemCtxt;
16
16
use super :: { bad_placeholder, is_suggestable_infer_ty} ;
17
17
use crate :: errors:: UnconstrainedOpaqueType ;
18
18
19
- /// Computes the relevant generic parameter for a potential generic const argument.
20
- ///
21
- /// This should be called using the query `tcx.opt_const_param_of`.
22
- pub ( super ) fn opt_const_param_of ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < DefId > {
19
+ fn anon_const_type_of < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Ty < ' tcx > {
23
20
use hir:: * ;
24
21
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
25
22
26
- match tcx. hir ( ) . get ( hir_id) {
27
- Node :: AnonConst ( _) => ( ) ,
28
- _ => return None ,
29
- } ;
23
+ let Node :: AnonConst ( _) = tcx. hir ( ) . get ( hir_id) else { panic ! ( ) } ;
30
24
31
25
let parent_node_id = tcx. hir ( ) . parent_id ( hir_id) ;
32
26
let parent_node = tcx. hir ( ) . get ( parent_node_id) ;
33
27
34
28
let ( generics, arg_idx) = match parent_node {
29
+ // Easy case: arrays repeat expressions.
30
+ Node :: Ty ( & Ty { kind : TyKind :: Array ( _, ref constant) , .. } )
31
+ | Node :: Expr ( & Expr { kind : ExprKind :: Repeat ( _, ref constant) , .. } )
32
+ if constant. hir_id ( ) == hir_id =>
33
+ {
34
+ return tcx. types . usize
35
+ }
36
+ Node :: Ty ( & Ty { kind : TyKind :: Typeof ( ref e) , .. } ) if e. hir_id == hir_id => {
37
+ return tcx. typeck ( def_id) . node_type ( e. hir_id )
38
+ }
39
+ Node :: Expr ( & Expr { kind : ExprKind :: ConstBlock ( ref anon_const) , .. } )
40
+ if anon_const. hir_id == hir_id =>
41
+ {
42
+ let substs = InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ;
43
+ return substs. as_inline_const ( ) . ty ( )
44
+ }
45
+ Node :: Expr ( & Expr { kind : ExprKind :: InlineAsm ( asm) , .. } )
46
+ | Node :: Item ( & Item { kind : ItemKind :: GlobalAsm ( asm) , .. } )
47
+ if asm. operands . iter ( ) . any ( |( op, _op_sp) | match op {
48
+ hir:: InlineAsmOperand :: Const { anon_const }
49
+ | hir:: InlineAsmOperand :: SymFn { anon_const } => anon_const. hir_id == hir_id,
50
+ _ => false ,
51
+ } ) =>
52
+ {
53
+ return tcx. typeck ( def_id) . node_type ( hir_id)
54
+ }
55
+ Node :: Variant ( Variant { disr_expr : Some ( ref e) , .. } ) if e. hir_id == hir_id => {
56
+ return tcx
57
+ . adt_def ( tcx. hir ( ) . get_parent_item ( hir_id) )
58
+ . repr ( )
59
+ . discr_type ( )
60
+ . to_ty ( tcx)
61
+ }
62
+ Node :: GenericParam ( & GenericParam {
63
+ def_id : param_def_id,
64
+ kind : GenericParamKind :: Const { default : Some ( ct) , .. } ,
65
+ ..
66
+ } ) if ct. hir_id == hir_id => {
67
+ return tcx. type_of ( param_def_id)
68
+ . no_bound_vars ( )
69
+ . expect ( "const parameter types cannot be generic" )
70
+ }
71
+
72
+ Node :: TypeBinding ( binding @ & TypeBinding { hir_id : binding_id, .. } )
73
+ if let Node :: TraitRef ( trait_ref) = tcx. hir ( ) . get (
74
+ tcx. hir ( ) . parent_id ( binding_id)
75
+ ) =>
76
+ {
77
+ let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
78
+ return tcx. ty_error_with_message ( tcx. def_span ( def_id) , "Could not find trait" ) ;
79
+ } ;
80
+ let assoc_items = tcx. associated_items ( trait_def_id) ;
81
+ let assoc_item = assoc_items. find_by_name_and_kind (
82
+ tcx, binding. ident , ty:: AssocKind :: Const , def_id. to_def_id ( ) ,
83
+ ) ;
84
+ return if let Some ( assoc_item) = assoc_item {
85
+ tcx. type_of ( assoc_item. def_id )
86
+ . no_bound_vars ( )
87
+ . expect ( "const parameter types cannot be generic" )
88
+ } else {
89
+ // FIXME(associated_const_equality): add a useful error message here.
90
+ tcx. ty_error_with_message ( tcx. def_span ( def_id) , "Could not find associated const on trait" )
91
+ }
92
+ }
93
+
35
94
// This match arm is for when the def_id appears in a GAT whose
36
95
// path can't be resolved without typechecking e.g.
37
96
//
@@ -86,11 +145,10 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
86
145
( generics, arg_index)
87
146
} else {
88
147
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
89
- tcx. sess . delay_span_bug (
148
+ return tcx. ty_error_with_message (
90
149
tcx. def_span ( def_id) ,
91
150
"unexpected non-GAT usage of an anon const" ,
92
151
) ;
93
- return None ;
94
152
}
95
153
}
96
154
Node :: Expr ( & Expr {
@@ -103,7 +161,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
103
161
// This may fail in case the method/path does not actually exist.
104
162
// As there is no relevant param for `def_id`, we simply return
105
163
// `None` here.
106
- let type_dependent_def = tables. type_dependent_def_id ( parent_node_id) ?;
164
+ let Some ( type_dependent_def) = tables. type_dependent_def_id ( parent_node_id) else {
165
+ return tcx. ty_error_with_message (
166
+ tcx. def_span ( def_id) ,
167
+ & format ! ( "unable to find type-dependent def for {:?}" , parent_node_id) ,
168
+ ) ;
169
+ } ;
107
170
let idx = segment
108
171
. args
109
172
. and_then ( |args| {
@@ -140,19 +203,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
140
203
if let Some ( path) = get_path_containing_arg_in_pat ( pat, hir_id) {
141
204
path
142
205
} else {
143
- tcx. sess . delay_span_bug (
206
+ return tcx. ty_error_with_message (
144
207
tcx. def_span ( def_id) ,
145
208
& format ! ( "unable to find const parent for {} in pat {:?}" , hir_id, pat) ,
146
209
) ;
147
- return None ;
148
210
}
149
211
}
150
212
_ => {
151
- tcx. sess . delay_span_bug (
213
+ return tcx. ty_error_with_message (
152
214
tcx. def_span ( def_id) ,
153
215
& format ! ( "unexpected const parent path {:?}" , parent_node) ,
154
216
) ;
155
- return None ;
156
217
}
157
218
} ;
158
219
@@ -171,32 +232,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
171
232
. position ( |ct| ct. hir_id == hir_id)
172
233
. map ( |idx| ( idx, seg) ) )
173
234
} ) else {
174
- tcx. sess . delay_span_bug (
235
+ return tcx. ty_error_with_message (
175
236
tcx. def_span ( def_id) ,
176
237
"no arg matching AnonConst in path" ,
177
238
) ;
178
- return None ;
179
239
} ;
180
240
181
241
let generics = match tcx. res_generics_def_id ( segment. res ) {
182
242
Some ( def_id) => tcx. generics_of ( def_id) ,
183
243
None => {
184
- tcx. sess . delay_span_bug (
244
+ return tcx. ty_error_with_message (
185
245
tcx. def_span ( def_id) ,
186
246
& format ! ( "unexpected anon const res {:?} in path: {:?}" , segment. res, path) ,
187
247
) ;
188
- return None ;
189
248
}
190
249
} ;
191
250
192
251
( generics, arg_index)
193
252
}
194
- _ => return None ,
253
+
254
+ _ => return tcx. ty_error_with_message (
255
+ tcx. def_span ( def_id) ,
256
+ & format ! ( "unexpected const parent in type_of(): {parent_node:?}" ) ,
257
+ ) ,
195
258
} ;
196
259
197
260
debug ! ( ?parent_node) ;
198
261
debug ! ( ?generics, ?arg_idx) ;
199
- generics
262
+ if let Some ( param_def_id ) = generics
200
263
. params
201
264
. iter ( )
202
265
. filter ( |param| param. kind . is_ty_or_const ( ) )
@@ -211,6 +274,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
211
274
}
212
275
_ => None ,
213
276
} )
277
+ {
278
+ tcx. type_of ( param_def_id) . no_bound_vars ( ) . expect ( "const parameter types cannot be generic" )
279
+ } else {
280
+ return tcx. ty_error_with_message (
281
+ tcx. def_span ( def_id) ,
282
+ & format ! ( "const generic parameter not found in {generics:?} at position {arg_idx:?}" ) ,
283
+ ) ;
284
+ }
214
285
}
215
286
216
287
fn get_path_containing_arg_in_pat < ' hir > (
@@ -415,142 +486,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
415
486
tcx. typeck ( def_id) . node_type ( hir_id)
416
487
}
417
488
418
- Node :: AnonConst ( _) if let Some ( param) = tcx. opt_const_param_of ( def_id) => {
419
- // We defer to `type_of` of the corresponding parameter
420
- // for generic arguments.
421
- tcx. type_of ( param) . subst_identity ( )
422
- }
423
- Node :: AnonConst ( _) => {
424
- let parent_node = tcx. hir ( ) . get_parent ( hir_id) ;
425
- match parent_node {
426
- Node :: Ty ( Ty { kind : TyKind :: Array ( _, constant) , .. } )
427
- | Node :: Expr ( Expr { kind : ExprKind :: Repeat ( _, constant) , .. } )
428
- if constant. hir_id ( ) == hir_id =>
429
- {
430
- tcx. types . usize
431
- }
432
- Node :: Ty ( Ty { kind : TyKind :: Typeof ( e) , .. } ) if e. hir_id == hir_id => {
433
- tcx. typeck ( def_id) . node_type ( e. hir_id )
434
- }
435
-
436
- Node :: Expr ( Expr { kind : ExprKind :: ConstBlock ( anon_const) , .. } )
437
- if anon_const. hir_id == hir_id =>
438
- {
439
- let substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
440
- substs. as_inline_const ( ) . ty ( )
441
- }
442
-
443
- Node :: Expr ( & Expr { kind : ExprKind :: InlineAsm ( asm) , .. } )
444
- | Node :: Item ( & Item { kind : ItemKind :: GlobalAsm ( asm) , .. } )
445
- if asm. operands . iter ( ) . any ( |( op, _op_sp) | match op {
446
- hir:: InlineAsmOperand :: Const { anon_const }
447
- | hir:: InlineAsmOperand :: SymFn { anon_const } => {
448
- anon_const. hir_id == hir_id
449
- }
450
- _ => false ,
451
- } ) =>
452
- {
453
- tcx. typeck ( def_id) . node_type ( hir_id)
454
- }
455
-
456
- Node :: Variant ( Variant { disr_expr : Some ( e) , .. } ) if e. hir_id == hir_id => {
457
- tcx. adt_def ( tcx. hir ( ) . get_parent_item ( hir_id) ) . repr ( ) . discr_type ( ) . to_ty ( tcx)
458
- }
459
-
460
- Node :: TypeBinding ( TypeBinding {
461
- hir_id : binding_id,
462
- kind : TypeBindingKind :: Equality { term : Term :: Const ( e) } ,
463
- ident,
464
- ..
465
- } ) if let Node :: TraitRef ( trait_ref) = tcx. hir ( ) . get_parent ( * binding_id)
466
- && e. hir_id == hir_id =>
467
- {
468
- let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
469
- return ty:: EarlyBinder ( tcx. ty_error_with_message ( DUMMY_SP , "Could not find trait" ) ) ;
470
- } ;
471
- let assoc_items = tcx. associated_items ( trait_def_id) ;
472
- let assoc_item = assoc_items. find_by_name_and_kind (
473
- tcx,
474
- * ident,
475
- ty:: AssocKind :: Const ,
476
- def_id. to_def_id ( ) ,
477
- ) ;
478
- if let Some ( assoc_item) = assoc_item {
479
- tcx. type_of ( assoc_item. def_id )
480
- . no_bound_vars ( )
481
- . expect ( "const parameter types cannot be generic" )
482
- } else {
483
- // FIXME(associated_const_equality): add a useful error message here.
484
- tcx. ty_error_with_message (
485
- DUMMY_SP ,
486
- "Could not find associated const on trait" ,
487
- )
488
- }
489
- }
490
-
491
- Node :: TypeBinding ( TypeBinding {
492
- hir_id : binding_id,
493
- gen_args,
494
- kind,
495
- ident,
496
- ..
497
- } ) if let Node :: TraitRef ( trait_ref) = tcx. hir ( ) . get_parent ( * binding_id)
498
- && let Some ( ( idx, _) ) =
499
- gen_args. args . iter ( ) . enumerate ( ) . find ( |( _, arg) | {
500
- if let GenericArg :: Const ( ct) = arg {
501
- ct. value . hir_id == hir_id
502
- } else {
503
- false
504
- }
505
- } ) =>
506
- {
507
- let Some ( trait_def_id) = trait_ref. trait_def_id ( ) else {
508
- return ty:: EarlyBinder ( tcx. ty_error_with_message ( DUMMY_SP , "Could not find trait" ) ) ;
509
- } ;
510
- let assoc_items = tcx. associated_items ( trait_def_id) ;
511
- let assoc_item = assoc_items. find_by_name_and_kind (
512
- tcx,
513
- * ident,
514
- match kind {
515
- // I think `<A: T>` type bindings requires that `A` is a type
516
- TypeBindingKind :: Constraint { .. }
517
- | TypeBindingKind :: Equality { term : Term :: Ty ( ..) } => {
518
- ty:: AssocKind :: Type
519
- }
520
- TypeBindingKind :: Equality { term : Term :: Const ( ..) } => {
521
- ty:: AssocKind :: Const
522
- }
523
- } ,
524
- def_id. to_def_id ( ) ,
525
- ) ;
526
- if let Some ( assoc_item) = assoc_item
527
- && let param = & tcx. generics_of ( assoc_item. def_id ) . params [ idx]
528
- && matches ! ( param. kind, ty:: GenericParamDefKind :: Const { .. } )
529
- {
530
- tcx. type_of ( param. def_id )
531
- . no_bound_vars ( )
532
- . expect ( "const parameter types cannot be generic" )
533
- } else {
534
- // FIXME(associated_const_equality): add a useful error message here.
535
- tcx. ty_error_with_message (
536
- DUMMY_SP ,
537
- "Could not find const param on associated item" ,
538
- )
539
- }
540
- }
541
-
542
- Node :: GenericParam ( & GenericParam {
543
- def_id : param_def_id,
544
- kind : GenericParamKind :: Const { default : Some ( ct) , .. } ,
545
- ..
546
- } ) if ct. hir_id == hir_id => tcx. type_of ( param_def_id) . subst_identity ( ) ,
547
-
548
- x => tcx. ty_error_with_message (
549
- DUMMY_SP ,
550
- & format ! ( "unexpected const parent in type_of(): {x:?}" ) ,
551
- ) ,
552
- }
553
- }
489
+ Node :: AnonConst ( _) => anon_const_type_of ( tcx, def_id) ,
554
490
555
491
Node :: GenericParam ( param) => match & param. kind {
556
492
GenericParamKind :: Type { default : Some ( ty) , .. }
0 commit comments