Skip to content

Commit 13bf0b2

Browse files
committed
Auto merge of rust-lang#85479 - Stupremee:render-Self_as-type-casts, r=CraftSpider
rustdoc: render `<Self as X>::Y` type casts properly Rustdoc didn't render any `<Self as X>` casts which causes invalid code inside the documentation. This is fixed by this PR by checking if the target type `X` is different from `Self`, and if so, it will render a typecast. Resolves rust-lang#85454
2 parents 0f8cd43 + d637ed4 commit 13bf0b2

File tree

8 files changed

+38
-13
lines changed

8 files changed

+38
-13
lines changed

src/librustdoc/clean/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
561561
}
562562
WherePredicate::EqPredicate { lhs, rhs } => {
563563
match lhs {
564-
Type::QPath { name: left_name, ref self_type, ref trait_ } => {
564+
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
565565
let ty = &*self_type;
566566
match **trait_ {
567567
Type::ResolvedPath {

src/librustdoc/clean/inline.rs

+1
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
588588
self_type: box clean::Generic(ref s),
589589
trait_: box clean::ResolvedPath { did, .. },
590590
name: ref _name,
591+
..
591592
},
592593
ref bounds,
593594
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),

src/librustdoc/clean/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -418,9 +418,11 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
418418
GenericBound::TraitBound(t, _) => t.trait_,
419419
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
420420
};
421+
let self_type = self.self_ty().clean(cx);
421422
Type::QPath {
422423
name: cx.tcx.associated_item(self.item_def_id).ident.name,
423-
self_type: box self.self_ty().clean(cx),
424+
self_def_id: self_type.def_id(),
425+
self_type: box self_type,
424426
trait_: box trait_,
425427
}
426428
}
@@ -1104,7 +1106,7 @@ impl Clean<Item> for ty::AssocItem {
11041106
.filter_map(|pred| {
11051107
let (name, self_type, trait_, bounds) = match *pred {
11061108
WherePredicate::BoundPredicate {
1107-
ty: QPath { ref name, ref self_type, ref trait_ },
1109+
ty: QPath { ref name, ref self_type, ref trait_, .. },
11081110
ref bounds,
11091111
} => (name, self_type, trait_, bounds),
11101112
_ => return None,
@@ -1282,16 +1284,15 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
12821284

12831285
let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
12841286
let trait_segments = &segments[..segments.len() - 1];
1287+
let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
12851288
let trait_path = self::Path {
12861289
global: p.is_global(),
1287-
res: Res::Def(
1288-
DefKind::Trait,
1289-
cx.tcx.associated_item(p.res.def_id()).container.id(),
1290-
),
1290+
res: Res::Def(DefKind::Trait, trait_def),
12911291
segments: trait_segments.clean(cx),
12921292
};
12931293
Type::QPath {
12941294
name: p.segments.last().expect("segments were empty").ident.name,
1295+
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
12951296
self_type: box qself.clean(cx),
12961297
trait_: box resolve_type(cx, trait_path, hir_id),
12971298
}
@@ -1306,6 +1307,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
13061307
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
13071308
Type::QPath {
13081309
name: segment.ident.name,
1310+
self_def_id: res.opt_def_id(),
13091311
self_type: box qself.clean(cx),
13101312
trait_: box resolve_type(cx, trait_path, hir_id),
13111313
}

src/librustdoc/clean/types.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,7 @@ crate enum Type {
15191519
QPath {
15201520
name: Symbol,
15211521
self_type: Box<Type>,
1522+
self_def_id: Option<DefId>,
15221523
trait_: Box<Type>,
15231524
},
15241525

@@ -1665,7 +1666,7 @@ impl Type {
16651666

16661667
crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
16671668
let (self_, trait_, name) = match self {
1668-
QPath { self_type, trait_, name } => (self_type, trait_, name),
1669+
QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
16691670
_ => return None,
16701671
};
16711672
let trait_did = match **trait_ {

src/librustdoc/clean/utils.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ crate fn strip_type(ty: Type) -> Type {
175175
Type::BorrowedRef { lifetime, mutability, type_ } => {
176176
Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
177177
}
178-
Type::QPath { name, self_type, trait_ } => Type::QPath {
178+
Type::QPath { name, self_type, trait_, self_def_id } => Type::QPath {
179179
name,
180+
self_def_id,
180181
self_type: Box::new(strip_type(*self_type)),
181182
trait_: Box::new(strip_type(*trait_)),
182183
},

src/librustdoc/html/format.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_span::def_id::CRATE_DEF_INDEX;
1818
use rustc_target::spec::abi::Abi;
1919

2020
use crate::clean::{
21-
self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, PrimitiveType,
21+
self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType,
2222
};
2323
use crate::formats::item_type::ItemType;
2424
use crate::html::escape::Escape;
@@ -836,10 +836,13 @@ fn fmt_type<'cx>(
836836
write!(f, "impl {}", print_generic_bounds(bounds, cx))
837837
}
838838
}
839-
clean::QPath { ref name, ref self_type, ref trait_ } => {
839+
clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
840840
let should_show_cast = match *trait_ {
841841
box clean::ResolvedPath { ref path, .. } => {
842-
!path.segments.is_empty() && !self_type.is_self_type()
842+
!path.segments.is_empty()
843+
&& self_def_id
844+
.zip(trait_.def_id())
845+
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
843846
}
844847
_ => true,
845848
};

src/librustdoc/json/conversions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ impl FromWithTcx<clean::Type> for Type {
396396
mutable: mutability == ast::Mutability::Mut,
397397
type_: Box::new((*type_).into_tcx(tcx)),
398398
},
399-
QPath { name, self_type, trait_ } => Type::QualifiedPath {
399+
QPath { name, self_type, trait_, .. } => Type::QualifiedPath {
400400
name: name.to_string(),
401401
self_type: Box::new((*self_type).into_tcx(tcx)),
402402
trait_: Box::new((*trait_).into_tcx(tcx)),

src/test/rustdoc/issue-85454.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @has issue_85454/trait.FromResidual.html
2+
// @has - '//pre[@class="rust trait"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
3+
pub trait FromResidual<R = <Self as Try>::Residual> {
4+
fn from_residual(residual: R) -> Self;
5+
}
6+
7+
pub trait Try: FromResidual {
8+
type Output;
9+
type Residual;
10+
fn from_output(output: Self::Output) -> Self;
11+
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
12+
}
13+
14+
pub enum ControlFlow<B, C = ()> {
15+
Continue(C),
16+
Break(B),
17+
}

0 commit comments

Comments
 (0)