@@ -2300,25 +2300,7 @@ fn explicit_predicates_of(
23002300 // Add predicates from associated type bounds.
23012301 if let Some ( ( self_trait_ref, trait_items) ) = is_trait {
23022302 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)
23222304 } ) )
23232305 }
23242306
@@ -2352,6 +2334,105 @@ fn explicit_predicates_of(
23522334 result
23532335}
23542336
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+
23552436/// Converts a specific `GenericBound` from the AST into a set of
23562437/// predicates that apply to the self type. A vector is returned
23572438/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
0 commit comments