11use rustc_errors:: { Applicability , StashKey } ;
22use rustc_hir as hir;
3- use rustc_hir:: def_id:: { DefId , LocalDefId } ;
3+ use rustc_hir:: def_id:: LocalDefId ;
44use rustc_hir:: intravisit;
55use rustc_hir:: intravisit:: Visitor ;
66use rustc_hir:: { HirId , Node } ;
@@ -16,22 +16,81 @@ use super::ItemCtxt;
1616use super :: { bad_placeholder, is_suggestable_infer_ty} ;
1717use crate :: errors:: UnconstrainedOpaqueType ;
1818
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 > {
2320 use hir:: * ;
2421 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
2522
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 ! ( ) } ;
3024
3125 let parent_node_id = tcx. hir ( ) . parent_id ( hir_id) ;
3226 let parent_node = tcx. hir ( ) . get ( parent_node_id) ;
3327
3428 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+
3594 // This match arm is for when the def_id appears in a GAT whose
3695 // path can't be resolved without typechecking e.g.
3796 //
@@ -86,11 +145,10 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
86145 ( generics, arg_index)
87146 } else {
88147 // 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 (
90149 tcx. def_span ( def_id) ,
91150 "unexpected non-GAT usage of an anon const" ,
92151 ) ;
93- return None ;
94152 }
95153 }
96154 Node :: Expr ( & Expr {
@@ -103,7 +161,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
103161 // This may fail in case the method/path does not actually exist.
104162 // As there is no relevant param for `def_id`, we simply return
105163 // `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+ } ;
107170 let idx = segment
108171 . args
109172 . and_then ( |args| {
@@ -140,19 +203,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
140203 if let Some ( path) = get_path_containing_arg_in_pat ( pat, hir_id) {
141204 path
142205 } else {
143- tcx. sess . delay_span_bug (
206+ return tcx. ty_error_with_message (
144207 tcx. def_span ( def_id) ,
145208 & format ! ( "unable to find const parent for {} in pat {:?}" , hir_id, pat) ,
146209 ) ;
147- return None ;
148210 }
149211 }
150212 _ => {
151- tcx. sess . delay_span_bug (
213+ return tcx. ty_error_with_message (
152214 tcx. def_span ( def_id) ,
153215 & format ! ( "unexpected const parent path {:?}" , parent_node) ,
154216 ) ;
155- return None ;
156217 }
157218 } ;
158219
@@ -171,32 +232,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
171232 . position ( |ct| ct. hir_id == hir_id)
172233 . map ( |idx| ( idx, seg) ) )
173234 } ) else {
174- tcx. sess . delay_span_bug (
235+ return tcx. ty_error_with_message (
175236 tcx. def_span ( def_id) ,
176237 "no arg matching AnonConst in path" ,
177238 ) ;
178- return None ;
179239 } ;
180240
181241 let generics = match tcx. res_generics_def_id ( segment. res ) {
182242 Some ( def_id) => tcx. generics_of ( def_id) ,
183243 None => {
184- tcx. sess . delay_span_bug (
244+ return tcx. ty_error_with_message (
185245 tcx. def_span ( def_id) ,
186246 & format ! ( "unexpected anon const res {:?} in path: {:?}" , segment. res, path) ,
187247 ) ;
188- return None ;
189248 }
190249 } ;
191250
192251 ( generics, arg_index)
193252 }
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+ ) ,
195258 } ;
196259
197260 debug ! ( ?parent_node) ;
198261 debug ! ( ?generics, ?arg_idx) ;
199- generics
262+ if let Some ( param_def_id ) = generics
200263 . params
201264 . iter ( )
202265 . 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<
211274 }
212275 _ => None ,
213276 } )
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+ }
214285}
215286
216287fn get_path_containing_arg_in_pat < ' hir > (
@@ -415,142 +486,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
415486 tcx. typeck ( def_id) . node_type ( hir_id)
416487 }
417488
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) ,
554490
555491 Node :: GenericParam ( param) => match & param. kind {
556492 GenericParamKind :: Type { default : Some ( ty) , .. }
0 commit comments