@@ -1290,6 +1290,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
12901290 hir:: TyKind :: Path ( qpath) => qpath,
12911291 _ => unreachable ! ( ) ,
12921292 } ;
1293+
12931294 match qpath {
12941295 hir:: QPath :: Resolved ( None , ref path) => {
12951296 if let Res :: Def ( DefKind :: TyParam , did) = path. res {
@@ -1393,6 +1394,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
13931394 resolve_type ( cx, path. clean ( cx) , hir_id)
13941395 }
13951396 hir:: QPath :: Resolved ( Some ( ref qself) , ref p) => {
1397+ // Try to normalize `<X as Y>::T` to a type
1398+ let ty = hir_ty_to_ty ( cx. tcx , hir_ty) ;
1399+ if let Some ( normalized_value) = normalize ( cx. tcx , ty) {
1400+ return normalized_value. clean ( cx) ;
1401+ }
1402+
13961403 let segments = if p. is_global ( ) { & p. segments [ 1 ..] } else { & p. segments } ;
13971404 let trait_segments = & segments[ ..segments. len ( ) - 1 ] ;
13981405 let trait_path = self :: Path {
@@ -1410,18 +1417,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type {
14101417 }
14111418 }
14121419 hir:: QPath :: TypeRelative ( ref qself, ref segment) => {
1413- let mut res = Res :: Err ;
1414- /*
1415- let hir_ty = hir::Ty {
1416- kind: hir::TyKind::Path((*qpath).clone()),
1417- hir_id,
1418- span,
1419- };
1420- */
14211420 let ty = hir_ty_to_ty ( cx. tcx , hir_ty) ;
1422- if let ty:: Projection ( proj) = ty. kind ( ) {
1423- res = Res :: Def ( DefKind :: Trait , proj. trait_ref ( cx. tcx ) . def_id ) ;
1424- }
1421+ let res = if let ty:: Projection ( proj) = ty. kind ( ) {
1422+ Res :: Def ( DefKind :: Trait , proj. trait_ref ( cx. tcx ) . def_id )
1423+ } else {
1424+ Res :: Err
1425+ } ;
14251426 let trait_path = hir:: Path { span, res, segments : & [ ] } ;
14261427 Type :: QPath {
14271428 name : segment. ident . name . clean ( cx) ,
@@ -1496,10 +1497,42 @@ impl Clean<Type> for hir::Ty<'_> {
14961497 }
14971498}
14981499
1500+ /// Returns `None` if the type could not be normalized
1501+ fn normalize ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
1502+ use crate :: rustc_trait_selection:: infer:: TyCtxtInferExt ;
1503+ use crate :: rustc_trait_selection:: traits:: query:: normalize:: AtExt ;
1504+ use rustc_middle:: traits:: ObligationCause ;
1505+ use rustc_middle:: ty:: ParamEnv ;
1506+
1507+ // Try to normalize `<X as Y>::T` to a type
1508+ // FIXME: rustdoc won't be able to perform 'partial' normalization
1509+ // until this param env is actually correct
1510+ // 'partial': `<Vec<T> as IntoIterator>::IntoIter>` -> `vec::IntoIter<T>`
1511+ let param_env = ParamEnv :: empty ( ) ;
1512+ let lifted = ty. lift_to_tcx ( tcx) . unwrap ( ) ;
1513+ let normalized = tcx. infer_ctxt ( ) . enter ( |infcx| {
1514+ infcx
1515+ . at ( & ObligationCause :: dummy ( ) , param_env)
1516+ . normalize ( lifted)
1517+ . map ( |resolved| infcx. resolve_vars_if_possible ( resolved. value ) )
1518+ } ) ;
1519+ match normalized {
1520+ Ok ( normalized_value) => {
1521+ debug ! ( "resolved {:?} to {:?}" , ty, normalized_value) ;
1522+ Some ( normalized_value)
1523+ }
1524+ Err ( err) => {
1525+ debug ! ( "failed to resolve {:?}: {:?}" , ty, err) ;
1526+ None
1527+ }
1528+ }
1529+ }
1530+
14991531impl < ' tcx > Clean < Type > for Ty < ' tcx > {
15001532 fn clean ( & self , cx : & DocContext < ' _ > ) -> Type {
15011533 debug ! ( "cleaning type: {:?}" , self ) ;
1502- match * self . kind ( ) {
1534+ let ty = normalize ( cx. tcx , self . lift_to_tcx ( cx. tcx ) . unwrap ( ) ) . unwrap_or ( self ) ;
1535+ match * ty. kind ( ) {
15031536 ty:: Never => Never ,
15041537 ty:: Bool => Primitive ( PrimitiveType :: Bool ) ,
15051538 ty:: Char => Primitive ( PrimitiveType :: Char ) ,
0 commit comments