Skip to content

rustdoc: render <Self as X>::Y type casts properly #85479

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustdoc/clean/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
WherePredicate::EqPredicate { lhs, rhs } => {
match lhs {
Type::QPath { name: left_name, ref self_type, ref trait_ } => {
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
let ty = &*self_type;
match **trait_ {
Type::ResolvedPath {
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
self_type: box clean::Generic(ref s),
trait_: box clean::ResolvedPath { did, .. },
name: ref _name,
..
},
ref bounds,
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
Expand Down
14 changes: 8 additions & 6 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,11 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
GenericBound::TraitBound(t, _) => t.trait_,
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
};
let self_type = self.self_ty().clean(cx);
Type::QPath {
name: cx.tcx.associated_item(self.item_def_id).ident.name,
self_type: box self.self_ty().clean(cx),
self_def_id: self_type.def_id(),
self_type: box self_type,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add a separate def_id field? You can just call self_type.def_id() wherever you need it.

Copy link
Member Author

@Stupremee Stupremee May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because self_type is a Generic(Symbol("Self")) most of the time, and it was much easier to pass is that way. I also have a git stash that adds a new Type called SelfType, but it was much more work to implement and still has some bugs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally feel a bit uncomfortable with the added field, would it make sense to add a helper function/method somewhere instead?

Copy link
Member Author

@Stupremee Stupremee May 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason the field exists that the DefId of the Self type is lost after cleaning because the Self generic parameter is resolved to Generic("Self"), which does not contain any DefId, but a DefId is required to check if the cast should be displayed.
I don't know how a new helper function would help with that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, sorry, I misread your above comment. Request withdrawn.

trait_: box trait_,
}
}
Expand Down Expand Up @@ -1104,7 +1106,7 @@ impl Clean<Item> for ty::AssocItem {
.filter_map(|pred| {
let (name, self_type, trait_, bounds) = match *pred {
WherePredicate::BoundPredicate {
ty: QPath { ref name, ref self_type, ref trait_ },
ty: QPath { ref name, ref self_type, ref trait_, .. },
ref bounds,
} => (name, self_type, trait_, bounds),
_ => return None,
Expand Down Expand Up @@ -1282,16 +1284,15 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {

let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
let trait_segments = &segments[..segments.len() - 1];
let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
let trait_path = self::Path {
global: p.is_global(),
res: Res::Def(
DefKind::Trait,
cx.tcx.associated_item(p.res.def_id()).container.id(),
),
res: Res::Def(DefKind::Trait, trait_def),
segments: trait_segments.clean(cx),
};
Type::QPath {
name: p.segments.last().expect("segments were empty").ident.name,
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path, hir_id),
}
Expand All @@ -1306,6 +1307,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
Type::QPath {
name: segment.ident.name,
self_def_id: res.opt_def_id(),
self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path, hir_id),
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,7 @@ crate enum Type {
QPath {
name: Symbol,
self_type: Box<Type>,
self_def_id: Option<DefId>,
trait_: Box<Type>,
},

Expand Down Expand Up @@ -1665,7 +1666,7 @@ impl Type {

crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
let (self_, trait_, name) = match self {
QPath { self_type, trait_, name } => (self_type, trait_, name),
QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
_ => return None,
};
let trait_did = match **trait_ {
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ crate fn strip_type(ty: Type) -> Type {
Type::BorrowedRef { lifetime, mutability, type_ } => {
Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
}
Type::QPath { name, self_type, trait_ } => Type::QPath {
Type::QPath { name, self_type, trait_, self_def_id } => Type::QPath {
name,
self_def_id,
self_type: Box::new(strip_type(*self_type)),
trait_: Box::new(strip_type(*trait_)),
},
Expand Down
9 changes: 6 additions & 3 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_target::spec::abi::Abi;

use crate::clean::{
self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, PrimitiveType,
self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType,
};
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
Expand Down Expand Up @@ -836,10 +836,13 @@ fn fmt_type<'cx>(
write!(f, "impl {}", print_generic_bounds(bounds, cx))
}
}
clean::QPath { ref name, ref self_type, ref trait_ } => {
clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
let should_show_cast = match *trait_ {
box clean::ResolvedPath { ref path, .. } => {
!path.segments.is_empty() && !self_type.is_self_type()
!path.segments.is_empty()
&& self_def_id
.zip(trait_.def_id())
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
}
_ => true,
};
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl FromWithTcx<clean::Type> for Type {
mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)),
},
QPath { name, self_type, trait_ } => Type::QualifiedPath {
QPath { name, self_type, trait_, .. } => Type::QualifiedPath {
name: name.to_string(),
self_type: Box::new((*self_type).into_tcx(tcx)),
trait_: Box::new((*trait_).into_tcx(tcx)),
Expand Down
17 changes: 17 additions & 0 deletions src/test/rustdoc/issue-85454.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @has issue_85454/trait.FromResidual.html
// @has - '//pre[@class="rust trait"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}

pub trait Try: FromResidual {
type Output;
type Residual;
fn from_output(output: Self::Output) -> Self;
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}

pub enum ControlFlow<B, C = ()> {
Continue(C),
Break(B),
}