1
+ use std:: ops:: ControlFlow ;
2
+
1
3
use rustc_errors:: { Applicability , StashKey } ;
2
4
use rustc_hir as hir;
3
5
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -7,8 +9,9 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
7
9
use rustc_middle:: ty:: util:: IntTypeExt ;
8
10
use rustc_middle:: ty:: { self , ImplTraitInTraitData , IsSuggestable , Ty , TyCtxt , TypeVisitableExt } ;
9
11
use rustc_span:: symbol:: Ident ;
10
- use rustc_span:: { Span , DUMMY_SP } ;
12
+ use rustc_span:: { ErrorGuaranteed , Span , Symbol , DUMMY_SP } ;
11
13
use rustc_trait_selection:: traits;
14
+ use rustc_type_ir:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
12
15
13
16
use super :: { bad_placeholder, is_suggestable_infer_ty} ;
14
17
use super :: { AstConv , ItemCtxt } ;
@@ -72,10 +75,11 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
72
75
) ;
73
76
} ;
74
77
75
- // FIXME(associated_const_equality): Doing all this work *here* isn't great.
76
- // Ideally, we would've computed this already somewhere else in a query.
78
+ // FIXME(associated_const_equality): We're now performing a full but ad-hoc type-based
79
+ // resolution of the associated constant. Doing all this work *here* isn't great.
80
+ // Ideally, we would've computed this already somewhere else (in a query?).
77
81
78
- let icx = ItemCtxt :: new ( tcx, trait_def_id . expect_local ( ) ) ;
82
+ let icx = ItemCtxt :: new ( tcx, def_id ) ;
79
83
let trait_segment = trait_ref. path . segments . last ( ) . unwrap ( ) ;
80
84
let ( trait_args, _) = icx. astconv ( ) . create_args_for_ast_path (
81
85
trait_ref. path . span ,
@@ -87,6 +91,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
87
91
// FIXME(associated_const_equality): This isn't correct, it should be the concrete /
88
92
// instantiated self type. Theoretically, we could search for it in the HIR of the
89
93
// parent item but that's super fragile and hairy.
94
+ // If the projected type ends up containing this `Self` parameter, we will reject it
95
+ // below, so not much harm done.
90
96
Some ( tcx. types . self_param ) ,
91
97
ty:: BoundConstness :: NotConst ,
92
98
) ;
@@ -124,14 +130,23 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
124
130
& hir:: PathSegment {
125
131
ident,
126
132
hir_id,
127
- res : def:: Res :: Err ,
133
+ res : def:: Res :: Def ( def :: DefKind :: AssocConst , assoc_item . def_id ) ,
128
134
args : Some ( gen_args) ,
129
135
infer_args : false ,
130
136
} ,
131
137
parent_args,
132
138
) ;
133
139
134
- return tcx. type_of ( assoc_item. def_id ) . instantiate ( tcx, args) ;
140
+ let ty = tcx. type_of ( assoc_item. def_id ) . instantiate ( tcx, args) ;
141
+
142
+ // FIXME(const_generics): Support generic const generics.
143
+ if ty. has_param ( ) {
144
+ // We can't catch this in the resolver, therefore we need to handle it here.
145
+ let reported = report_unsupported_generic_associated_const ( tcx, ident, ty, hir_id) ;
146
+ return Ty :: new_error ( tcx, reported) ;
147
+ }
148
+
149
+ return ty;
135
150
}
136
151
137
152
// This match arm is for when the def_id appears in a GAT whose
@@ -339,6 +354,72 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
339
354
}
340
355
}
341
356
357
+ fn report_unsupported_generic_associated_const < ' tcx > (
358
+ tcx : TyCtxt < ' tcx > ,
359
+ assoc_const : Ident ,
360
+ ty : Ty < ' tcx > ,
361
+ hir_id : HirId ,
362
+ ) -> ErrorGuaranteed {
363
+ // Just find the first generic parameter. This should be sufficient in practice.
364
+ let ControlFlow :: Break ( ( param_index, param_name) ) = ty. visit_with ( & mut GenericParamFinder )
365
+ else {
366
+ bug ! ( )
367
+ } ;
368
+
369
+ // FIXME(associated_const_equality): Since we use a `Self` type parameter as a hack in
370
+ // `anon_const_type_of`, we can't be sure where `Self` comes from: It may come from the
371
+ // def site or the usage site of the assoc const. Therefore, don't try to find its definition.
372
+ let ( param_kind, param_def_span) = if param_name != rustc_span:: symbol:: kw:: SelfUpper {
373
+ let body_owner = tcx. hir ( ) . enclosing_body_owner ( hir_id) ;
374
+ let param_def = tcx. generics_of ( body_owner) . param_at ( param_index as _ , tcx) ;
375
+ ( & param_def. kind , Some ( tcx. def_ident_span ( param_def. def_id ) . unwrap ( ) ) )
376
+ } else {
377
+ ( & ty:: GenericParamDefKind :: Type { has_default : false , synthetic : false } , None )
378
+ } ;
379
+
380
+ struct GenericParamFinder ;
381
+
382
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for GenericParamFinder {
383
+ type BreakTy = ( u32 , Symbol ) ;
384
+
385
+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
386
+ if let ty:: Param ( param) = ty. kind ( ) {
387
+ return ControlFlow :: Break ( ( param. index , param. name ) ) ;
388
+ }
389
+
390
+ ty. super_visit_with ( self )
391
+ }
392
+
393
+ fn visit_region ( & mut self , re : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
394
+ if let ty:: ReEarlyParam ( param) = re. kind ( ) {
395
+ return ControlFlow :: Break ( ( param. index , param. name ) ) ;
396
+ }
397
+
398
+ ControlFlow :: Continue ( ( ) )
399
+ }
400
+
401
+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
402
+ if let ty:: ConstKind :: Param ( param) = ct. kind ( ) {
403
+ return ControlFlow :: Break ( ( param. index , param. name ) ) ;
404
+ }
405
+
406
+ ct. super_visit_with ( self )
407
+ }
408
+ }
409
+
410
+ tcx. sess . emit_err ( crate :: errors:: ParamInTyOfAssocConst {
411
+ span : assoc_const. span ,
412
+ assoc_const,
413
+ param_name,
414
+ param_kind : match param_kind {
415
+ ty:: GenericParamDefKind :: Lifetime => "lifetime" ,
416
+ ty:: GenericParamDefKind :: Type { .. } => "type" ,
417
+ ty:: GenericParamDefKind :: Const { .. } => "const" ,
418
+ } ,
419
+ param_defined_here_label : param_def_span,
420
+ } )
421
+ }
422
+
342
423
fn get_path_containing_arg_in_pat < ' hir > (
343
424
pat : & ' hir hir:: Pat < ' hir > ,
344
425
arg_id : HirId ,
0 commit comments