@@ -2300,25 +2300,7 @@ fn explicit_predicates_of(
2300
2300
// Add predicates from associated type bounds.
2301
2301
if let Some ( ( self_trait_ref, trait_items) ) = is_trait {
2302
2302
predicates. extend ( trait_items. iter ( ) . flat_map ( |trait_item_ref| {
2303
- let trait_item = tcx. hir ( ) . trait_item ( trait_item_ref. id ) ;
2304
- let bounds = match trait_item. kind {
2305
- hir:: TraitItemKind :: Type ( ref bounds, _) => bounds,
2306
- _ => return Vec :: new ( ) . into_iter ( )
2307
- } ;
2308
-
2309
- let assoc_ty =
2310
- tcx. mk_projection ( tcx. hir ( ) . local_def_id ( trait_item. hir_id ) ,
2311
- self_trait_ref. substs ) ;
2312
-
2313
- let bounds = AstConv :: compute_bounds (
2314
- & ItemCtxt :: new ( tcx, def_id) ,
2315
- assoc_ty,
2316
- bounds,
2317
- SizedByDefault :: Yes ,
2318
- trait_item. span ,
2319
- ) ;
2320
-
2321
- bounds. predicates ( tcx, assoc_ty) . into_iter ( )
2303
+ associated_item_predicates ( tcx, def_id, self_trait_ref, trait_item_ref)
2322
2304
} ) )
2323
2305
}
2324
2306
@@ -2352,6 +2334,105 @@ fn explicit_predicates_of(
2352
2334
result
2353
2335
}
2354
2336
2337
+ fn associated_item_predicates (
2338
+ tcx : TyCtxt < ' tcx > ,
2339
+ def_id : DefId ,
2340
+ self_trait_ref : ty:: TraitRef < ' tcx > ,
2341
+ trait_item_ref : & hir:: TraitItemRef ,
2342
+ ) -> Vec < ( ty:: Predicate < ' tcx > , Span ) > {
2343
+ let trait_item = tcx. hir ( ) . trait_item ( trait_item_ref. id ) ;
2344
+ let item_def_id = tcx. hir ( ) . local_def_id ( trait_item_ref. id . hir_id ) ;
2345
+ let bounds = match trait_item. kind {
2346
+ hir:: TraitItemKind :: Type ( ref bounds, _) => bounds,
2347
+ _ => return Vec :: new ( )
2348
+ } ;
2349
+
2350
+ let is_gat = !tcx. generics_of ( item_def_id) . params . is_empty ( ) ;
2351
+
2352
+ let mut had_error = false ;
2353
+
2354
+ let mut unimplemented_error = |arg_kind : & str | {
2355
+ if !had_error {
2356
+ tcx. sess . struct_span_err (
2357
+ trait_item. span ,
2358
+ & format ! ( "{}-generic associated types are not yet implemented" , arg_kind) ,
2359
+ )
2360
+ . note ( "for more information, see https://github.com/rust-lang/rust/issues/44265" )
2361
+ . emit ( ) ;
2362
+ had_error = true ;
2363
+ }
2364
+ } ;
2365
+
2366
+ let mk_bound_param = |param : & ty:: GenericParamDef , _: & _ | {
2367
+ match param. kind {
2368
+ ty:: GenericParamDefKind :: Lifetime => {
2369
+ tcx. mk_region ( ty:: RegionKind :: ReLateBound (
2370
+ ty:: INNERMOST ,
2371
+ ty:: BoundRegion :: BrNamed ( param. def_id , param. name )
2372
+ ) ) . into ( )
2373
+ }
2374
+ // FIXME(generic_associated_types): Use bound types and constants
2375
+ // once they are handled by the trait system.
2376
+ ty:: GenericParamDefKind :: Type { .. } => {
2377
+ unimplemented_error ( "type" ) ;
2378
+ tcx. types . err . into ( )
2379
+ }
2380
+ ty:: GenericParamDefKind :: Const => {
2381
+ unimplemented_error ( "const" ) ;
2382
+ tcx. consts . err . into ( )
2383
+ }
2384
+ }
2385
+ } ;
2386
+
2387
+ let bound_substs = if is_gat {
2388
+ // Given:
2389
+ //
2390
+ // trait X<'a, B, const C: usize> {
2391
+ // type T<'d, E, const F: usize>: Default;
2392
+ // }
2393
+ //
2394
+ // We need to create predicates on the trait:
2395
+ //
2396
+ // for<'d, E, const F: usize>
2397
+ // <Self as X<'a, B, const C: usize>>::T<'d, E, const F: usize>: Sized + Default
2398
+ //
2399
+ // We substitute escaping bound parameters for the generic
2400
+ // arguments to the associated type which are then bound by
2401
+ // the `Binder` around the the predicate.
2402
+ //
2403
+ // FIXME(generic_associated_types): Currently only lifetimes are handled.
2404
+ self_trait_ref. substs . extend_to ( tcx, item_def_id, mk_bound_param)
2405
+ } else {
2406
+ self_trait_ref. substs
2407
+ } ;
2408
+
2409
+ let assoc_ty = tcx. mk_projection (
2410
+ tcx. hir ( ) . local_def_id ( trait_item. hir_id ) ,
2411
+ bound_substs,
2412
+ ) ;
2413
+
2414
+ let bounds = AstConv :: compute_bounds (
2415
+ & ItemCtxt :: new ( tcx, def_id) ,
2416
+ assoc_ty,
2417
+ bounds,
2418
+ SizedByDefault :: Yes ,
2419
+ trait_item. span ,
2420
+ ) ;
2421
+
2422
+ let predicates = bounds. predicates ( tcx, assoc_ty) ;
2423
+
2424
+ if is_gat {
2425
+ // We use shifts to get the regions that we're substituting to
2426
+ // be bound by the binders in the `Predicate`s rather that
2427
+ // escaping.
2428
+ let shifted_in = ty:: fold:: shift_vars ( tcx, & predicates, 1 ) ;
2429
+ let substituted = shifted_in. subst ( tcx, bound_substs) ;
2430
+ ty:: fold:: shift_out_vars ( tcx, & substituted, 1 )
2431
+ } else {
2432
+ predicates
2433
+ }
2434
+ }
2435
+
2355
2436
/// Converts a specific `GenericBound` from the AST into a set of
2356
2437
/// predicates that apply to the self type. A vector is returned
2357
2438
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
0 commit comments