@@ -12,7 +12,6 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
1212use rustc_middle:: { bug, span_bug} ;
1313use rustc_span:: symbol:: Ident ;
1414use rustc_span:: { DUMMY_SP , Span } ;
15- use tracing:: debug;
1615
1716use super :: { ItemCtxt , bad_placeholder} ;
1817use crate :: errors:: TypeofReservedKeywordUsed ;
@@ -138,252 +137,26 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
138137 use hir:: * ;
139138 use rustc_middle:: ty:: Ty ;
140139
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.
146143 Node :: Ty ( & hir:: Ty { kind : TyKind :: Array ( _, ref constant) , .. } )
147144 | Node :: Expr ( & Expr { kind : ExprKind :: Repeat ( _, ref constant) , .. } )
148145 if constant. hir_id == arg_hir_id =>
149146 {
150147 return tcx. types . usize ;
151148 }
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- }
321149
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 (
352153 tcx,
353154 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+ ) ,
356157 }
357158}
358159
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-
387160pub ( super ) fn type_of ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> ty:: EarlyBinder < ' _ , Ty < ' _ > > {
388161 use rustc_hir:: * ;
389162 use rustc_middle:: ty:: Ty ;
0 commit comments