@@ -42,7 +42,7 @@ use rustc_hir as hir;
4242use rustc_hir:: attrs:: { AttributeKind , DocAttribute , DocInline } ;
4343use rustc_hir:: def:: { CtorKind , DefKind , MacroKinds , Res } ;
4444use rustc_hir:: def_id:: { DefId , DefIdMap , DefIdSet , LOCAL_CRATE , LocalDefId } ;
45- use rustc_hir:: { LangItem , PredicateOrigin , find_attr} ;
45+ use rustc_hir:: { LangItem , OpaqueTyOrigin , PredicateOrigin , find_attr} ;
4646use rustc_hir_analysis:: { lower_const_arg_for_rustdoc, lower_ty} ;
4747use rustc_middle:: metadata:: Reexport ;
4848use rustc_middle:: middle:: resolve_bound_vars as rbv;
@@ -458,7 +458,7 @@ fn clean_type_outlives_predicate<'tcx>(
458458 }
459459}
460460
461- fn clean_middle_term < ' tcx > (
461+ pub ( crate ) fn clean_middle_term < ' tcx > (
462462 term : ty:: Binder < ' tcx , ty:: Term < ' tcx > > ,
463463 cx : & mut DocContext < ' tcx > ,
464464) -> Term {
@@ -526,7 +526,7 @@ fn should_fully_qualify_path(self_def_id: Option<DefId>, trait_: &Path, self_typ
526526 . map_or ( !self_type. is_self_type ( ) , |( id, trait_) | id != trait_)
527527}
528528
529- fn projection_to_path_segment < ' tcx > (
529+ pub ( crate ) fn projection_to_path_segment < ' tcx > (
530530 proj : ty:: Binder < ' tcx , ty:: AliasTerm < ' tcx > > ,
531531 cx : & mut DocContext < ' tcx > ,
532532) -> PathSegment {
@@ -698,8 +698,13 @@ pub(crate) fn clean_generics<'tcx>(
698698 let param = clean_generic_param ( cx, Some ( gens) , param) ;
699699 match param. kind {
700700 GenericParamDefKind :: Lifetime { .. } => unreachable ! ( ) ,
701- GenericParamDefKind :: Type { ref bounds, .. } => {
702- cx. impl_trait_bounds . insert ( param. def_id . into ( ) , bounds. to_vec ( ) ) ;
701+ GenericParamDefKind :: Type { ref bounds, ref synthetic, .. } => {
702+ debug_assert ! ( * synthetic, "non-synthetic generic for impl trait: {param:?}" ) ;
703+ let param_def_id = param. def_id ;
704+ cx. impl_trait_bounds . insert (
705+ param_def_id. into ( ) ,
706+ ( bounds. to_vec ( ) , ImplTraitOrigin :: Param { def_id : param_def_id } ) ,
707+ ) ;
703708 }
704709 GenericParamDefKind :: Const { .. } => unreachable ! ( ) ,
705710 }
@@ -819,7 +824,7 @@ fn clean_ty_generics_inner<'tcx>(
819824) -> Generics {
820825 // Don't populate `cx.impl_trait_bounds` before cleaning where clauses,
821826 // since `clean_predicate` would consume them.
822- let mut impl_trait = BTreeMap :: < u32 , Vec < GenericBound > > :: default ( ) ;
827+ let mut impl_trait = BTreeMap :: < u32 , ( DefId , Vec < GenericBound > ) > :: default ( ) ;
823828
824829 let params: ThinVec < _ > = gens
825830 . own_params
@@ -832,7 +837,7 @@ fn clean_ty_generics_inner<'tcx>(
832837 return false ;
833838 }
834839 if synthetic {
835- impl_trait. insert ( param. index , vec ! [ ] ) ;
840+ impl_trait. insert ( param. index , ( param . def_id , vec ! [ ] ) ) ;
836841 return false ;
837842 }
838843 true
@@ -873,7 +878,7 @@ fn clean_ty_generics_inner<'tcx>(
873878 } ;
874879
875880 if let Some ( param_idx) = param_idx
876- && let Some ( bounds) = impl_trait. get_mut ( & param_idx)
881+ && let Some ( ( _ , bounds) ) = impl_trait. get_mut ( & param_idx)
877882 {
878883 let pred = clean_predicate ( * pred, cx) ?;
879884
@@ -895,7 +900,7 @@ fn clean_ty_generics_inner<'tcx>(
895900 } )
896901 . collect :: < Vec < _ > > ( ) ;
897902
898- for ( idx, mut bounds) in impl_trait {
903+ for ( idx, ( param_def_id , mut bounds) ) in impl_trait {
899904 let mut has_sized = false ;
900905 bounds. retain ( |b| {
901906 if b. is_sized_bound ( cx) {
@@ -929,7 +934,8 @@ fn clean_ty_generics_inner<'tcx>(
929934 }
930935 }
931936
932- cx. impl_trait_bounds . insert ( idx. into ( ) , bounds) ;
937+ cx. impl_trait_bounds
938+ . insert ( idx. into ( ) , ( bounds, ImplTraitOrigin :: Param { def_id : param_def_id } ) ) ;
933939 }
934940
935941 // Now that `cx.impl_trait_bounds` is populated, we can process
@@ -1157,7 +1163,7 @@ fn clean_poly_fn_sig<'tcx>(
11571163 // function isn't async without needing to execute the query `asyncness` at
11581164 // all which gives us a noticeable performance boost.
11591165 if let Some ( did) = did
1160- && let Type :: ImplTrait ( _ ) = output
1166+ && let Type :: ImplTrait { .. } = output
11611167 && cx. tcx . asyncness ( did) . is_async ( )
11621168 {
11631169 output = output. sugared_async_return_type ( ) ;
@@ -1648,8 +1654,8 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
16481654 if let Some ( new_ty) = cx. args . get ( & did) . and_then ( |p| p. as_ty ( ) ) . cloned ( ) {
16491655 return new_ty;
16501656 }
1651- if let Some ( bounds) = cx. impl_trait_bounds . remove ( & did. into ( ) ) {
1652- return ImplTrait ( bounds) ;
1657+ if let Some ( ( bounds, origin ) ) = cx. impl_trait_bounds . remove ( & did. into ( ) ) {
1658+ return ImplTrait { bounds, origin } ;
16531659 }
16541660 }
16551661
@@ -1838,7 +1844,15 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18381844 }
18391845 TyKind :: Tup ( tys) => Tuple ( tys. iter ( ) . map ( |ty| clean_ty ( ty, cx) ) . collect ( ) ) ,
18401846 TyKind :: OpaqueDef ( ty) => {
1841- ImplTrait ( ty. bounds . iter ( ) . filter_map ( |x| clean_generic_bound ( x, cx) ) . collect ( ) )
1847+ let bounds =
1848+ ty. bounds . iter ( ) . filter_map ( |x| clean_generic_bound ( x, cx) ) . collect :: < Vec < _ > > ( ) ;
1849+ ImplTrait {
1850+ bounds,
1851+ origin : ImplTraitOrigin :: Opaque {
1852+ def_id : ty. def_id . to_def_id ( ) ,
1853+ needs_sized_check : opaque_needs_sized_check ( & ty. origin ) ,
1854+ } ,
1855+ }
18421856 }
18431857 TyKind :: Path ( _) => clean_qpath ( ty, cx) ,
18441858 TyKind :: TraitObject ( bounds, lifetime) => {
@@ -2226,8 +2240,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
22262240 }
22272241
22282242 ty:: Param ( ref p) => {
2229- if let Some ( bounds) = cx. impl_trait_bounds . remove ( & p. index . into ( ) ) {
2230- ImplTrait ( bounds)
2243+ if let Some ( ( bounds, origin ) ) = cx. impl_trait_bounds . remove ( & p. index . into ( ) ) {
2244+ ImplTrait { bounds, origin }
22312245 } else if p. name == kw:: SelfUpper {
22322246 SelfTy
22332247 } else {
@@ -2363,7 +2377,24 @@ fn clean_middle_opaque_bounds<'tcx>(
23632377 ) ) ;
23642378 }
23652379
2366- ImplTrait ( bounds)
2380+ ImplTrait {
2381+ bounds,
2382+ origin : ImplTraitOrigin :: Opaque {
2383+ def_id : impl_trait_def_id,
2384+ needs_sized_check : if cx. tcx . opt_rpitit_info ( impl_trait_def_id) . is_some ( ) {
2385+ // RPITIT uses can imply `Sized` unless used behind indirection,
2386+ // so a precise check is necessary.
2387+ true
2388+ } else if impl_trait_def_id. is_local ( ) {
2389+ opaque_needs_sized_check ( & cx. tcx . opaque_ty_origin ( impl_trait_def_id) )
2390+ } else {
2391+ // Extern opaques don't carry origin metadata.
2392+ // Skip the use-site check to avoid an ICE.
2393+ // FIXME: Get metadata on sizedness for extern opaques, then make this precise.
2394+ false
2395+ } ,
2396+ } ,
2397+ }
23672398}
23682399
23692400pub ( crate ) fn clean_field < ' tcx > ( field : & hir:: FieldDef < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Item {
@@ -2626,6 +2657,17 @@ fn clean_unsafe_binder_ty<'tcx>(
26262657 UnsafeBinderTy { generic_params, ty }
26272658}
26282659
2660+ fn opaque_needs_sized_check < D > ( origin : & OpaqueTyOrigin < D > ) -> bool {
2661+ match origin {
2662+ // Return-position opaques need a sizedness check at their use-site,
2663+ // even if they have a `?Sized` bound.
2664+ OpaqueTyOrigin :: FnReturn { .. } | OpaqueTyOrigin :: AsyncFn { .. } => true ,
2665+ // TAITs don't need a use-site sizedness check.
2666+ // `?Sized` in their definition always opts them out of being sized.
2667+ OpaqueTyOrigin :: TyAlias { .. } => false ,
2668+ }
2669+ }
2670+
26292671pub ( crate ) fn reexport_chain (
26302672 tcx : TyCtxt < ' _ > ,
26312673 import_def_id : LocalDefId ,
@@ -3177,7 +3219,7 @@ fn clean_assoc_item_constraint<'tcx>(
31773219 }
31783220}
31793221
3180- fn clean_bound_vars < ' tcx > (
3222+ pub ( crate ) fn clean_bound_vars < ' tcx > (
31813223 bound_vars : & ty:: List < ty:: BoundVariableKind > ,
31823224 cx : & mut DocContext < ' tcx > ,
31833225) -> Vec < GenericParamDef > {
0 commit comments