Skip to content
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

[rustdoc] Improve "in parameters" search and search more generally #59004

Merged
merged 7 commits into from
Mar 27, 2019

Conversation

GuillaumeGomez
Copy link
Member

@GuillaumeGomez GuillaumeGomez commented Mar 7, 2019

@rust-highfive
Copy link
Collaborator

Some changes occurred in HTML/CSS.

cc @GuillaumeGomez

@rust-highfive
Copy link
Collaborator

r? @steveklabnik

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 7, 2019
@GuillaumeGomez GuillaumeGomez changed the title Generics handling [rustdoc] Improve "in parameters" search and search more generally Mar 7, 2019
@GuillaumeGomez
Copy link
Member Author

r? @QuietMisdreavus

@Dylan-DPC-zz
Copy link

ping from triage @QuietMisdreavus waiting for your review on this

Copy link
Member

@QuietMisdreavus QuietMisdreavus left a comment

Choose a reason for hiding this comment

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

Looks good, just a couple small comments. This may clash with #59170 whenever that lands.

@@ -1694,22 +1737,135 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
}
}

// The point is to replace bounds with types.
Copy link
Member

Choose a reason for hiding this comment

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

Can you write doc comments for the functions you added? For example, this could be something like "Extract the types from a function's parameters and generics" with maybe a note about trait bounds since you've already added the comment for it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah sure.

generics: &Generics,
arg: &Type,
cx: &DocContext<'_, '_, '_>,
) -> FxHashSet<Type> {
Copy link
Member

Choose a reason for hiding this comment

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

If you use a BTreeSet instead, it comes pre-sorted - otherwise it comes out in an arbitrary order. I'm not sure if you wanted it to be properly sorted or just deduplicated, though.

Copy link
Member Author

Choose a reason for hiding this comment

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

Dedup, the order doesn't matter. ;)

if !adds.is_empty() {
for a in adds.into_iter() {
res.insert(a);
}
Copy link
Member

Choose a reason for hiding this comment

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

You can replace this loop with res.extend(adds), since the sets implement the Extend trait.

@Dylan-DPC-zz Dylan-DPC-zz added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 18, 2019
@bors
Copy link
Contributor

bors commented Mar 21, 2019

☔ The latest upstream changes (presumably #58927) made this pull request unmergeable. Please resolve the merge conflicts.

@GuillaumeGomez
Copy link
Member Author

@QuietMisdreavus I applied your comments.

Copy link
Member

@QuietMisdreavus QuietMisdreavus left a comment

Choose a reason for hiding this comment

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

Excellent, thanks for doing this! This will make the in-doc search much more powerful.

@QuietMisdreavus
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Mar 26, 2019

📌 Commit befe9ca has been approved by QuietMisdreavus

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 26, 2019
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Mar 26, 2019
…=QuietMisdreavus

[rustdoc] Improve "in parameters" search and search more generally

Fixes rust-lang#58230.

r? @QuietMisdreavus
bors added a commit that referenced this pull request Mar 26, 2019
Rollup of 7 pull requests

Successful merges:

 - #59004 ([rustdoc] Improve "in parameters" search and search more generally)
 - #59026 (Fix moving text in search tabs headers)
 - #59197 (Exclude old book redirect stubs from search engines)
 - #59330 (Improve the documentation for std::convert (From, Into, AsRef and AsMut))
 - #59424 (Fix code block display in portability element in dark theme)
 - #59427 (Link to PhantomData in NonNull documentation)
 - #59432 (Improve some compiletest documentation)

Failed merges:

r? @ghost
bors added a commit that referenced this pull request Mar 27, 2019
Rollup of 7 pull requests

Successful merges:

 - #59004 ([rustdoc] Improve "in parameters" search and search more generally)
 - #59026 (Fix moving text in search tabs headers)
 - #59197 (Exclude old book redirect stubs from search engines)
 - #59330 (Improve the documentation for std::convert (From, Into, AsRef and AsMut))
 - #59424 (Fix code block display in portability element in dark theme)
 - #59427 (Link to PhantomData in NonNull documentation)
 - #59432 (Improve some compiletest documentation)

Failed merges:

r? @ghost
@bors bors merged commit befe9ca into rust-lang:master Mar 27, 2019
@GuillaumeGomez GuillaumeGomez deleted the generics-handling branch March 27, 2019 09:10
@eddyb
Copy link
Member

eddyb commented Mar 28, 2019

@GuillaumeGomez @QuietMisdreavus Please do not merge PRs that change the compiler (in this case, typeck) without a review from @rust-lang/compiler.

pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
match *self {
GenericParamDefKind::Type { did, .. } => {
rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx))
Copy link
Member

Choose a reason for hiding this comment

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

You didn't have to do any of the typeck changes, the default is already there:

GenericParamDefKind::Type { ref default, .. } => default.clone(),

@@ -1707,12 +1750,122 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
}
}

/// The point of this function is to replace bounds with types.
///
/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
Copy link
Member

Choose a reason for hiding this comment

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

Option<T> is not a bound... how does this make sense?

Copy link
Member Author

Choose a reason for hiding this comment

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

The point is to replace T by the type/trait if any. For example:

fn<T>(x: T)
where T: Display

In there, T should be replaced with Display. In here, it's all about the rustdoc search, not about finding exact types. If we have two types with the same name, we don't care, we just remove one name from the list and that's it.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, but you can get the desired effect without using confusing terminology.

So what you want is "types of arguments" and "bounds on parameters in those arguments"?

Why bother with that complication tho? Why not just record all paths in a signature, be it args/return, or bounds/where clauses? Getting all that is less work and much easier to reason about.


pub fn is_full_generic(&self) -> bool {
match *self {
Type::Generic(_) => true,
Copy link
Member

Choose a reason for hiding this comment

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

This should be called Param or GenericParam.

@@ -2410,6 +2581,13 @@ impl Type {
_ => None
}
}

pub fn is_full_generic(&self) -> bool {
Copy link
Member

Choose a reason for hiding this comment

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

This should be called is_param or is_generic_param.

/// wrapped types in here).
fn get_real_types(
generics: &Generics,
arg: &Type,
Copy link
Member

Choose a reason for hiding this comment

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

This should probably be called ty?

continue
}
if let Some(ty) = x.get_type(cx) {
let adds = get_real_types(generics, &ty, cx);
Copy link
Member

@eddyb eddyb Mar 28, 2019

Choose a reason for hiding this comment

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

This is unguarded recursion, can easily become infinite, probably the cause of #59502.

Copy link
Member Author

Choose a reason for hiding this comment

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

It was indeed.

}) {
for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
if let Some(ty) = bound.get_trait_type() {
let adds = get_real_types(generics, &ty, cx);
Copy link
Member

Choose a reason for hiding this comment

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

Same here, unguarded recursion.

if let Some(gens) = arg.generics() {
for gen in gens.iter() {
if gen.is_full_generic() {
let adds = get_real_types(generics, gen, cx);
Copy link
Member

Choose a reason for hiding this comment

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

Same here, unguarded recursion.

/// Return the full list of types when bounds have been resolved.
///
/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
/// `[u32, Display, Option]`.
Copy link
Member

Choose a reason for hiding this comment

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

Same here, Option<A> is not a bound.

}
}
}
if let Some(bound) = generics.params.iter().find(|g| {
Copy link
Member

Choose a reason for hiding this comment

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

bound here seems to be a misnomer, this is a param.

Copy link
Member

Choose a reason for hiding this comment

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

IMO this should be above the where handling above, doing it this way is far more confusing.

}
}
if let Some(bound) = generics.params.iter().find(|g| {
g.is_type() && g.name == arg_s
Copy link
Member

Choose a reason for hiding this comment

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

Why is this by name instead of by DefId?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't care about DefId in here, I only care about names. Don't forget it's to generate rustdoc search array. I'm not looking for a given type but for a given type name.

Copy link
Member

Choose a reason for hiding this comment

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

You're searching for a type parameter though, not a struct/enum.
And you implemented the other search for type parameters by DefId, so it's inconsistent.

let adds = get_real_types(generics, &ty, cx);
if !adds.is_empty() {
res.extend(adds);
} else if !ty.is_full_generic() {
Copy link
Member

Choose a reason for hiding this comment

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

ty is a trait, not a type, so is_full_generic() should never be the case.

/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
/// `[Display, Option]` (we just returns the list of the types, we don't care about the
/// wrapped types in here).
fn get_real_types(
Copy link
Member

Choose a reason for hiding this comment

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

This name should be find_concrete_types, or, even better, find_type_paths.

res.insert(arg.clone());
if let Some(gens) = arg.generics() {
for gen in gens.iter() {
if gen.is_full_generic() {
Copy link
Member

Choose a reason for hiding this comment

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

So this means that get_real_types(Option<T>) will look at T's bounds... why?

if !adds.is_empty() {
res.extend(adds);
} else if !ty.is_full_generic() {
res.insert(ty.clone());
Copy link
Member

Choose a reason for hiding this comment

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

ty is a trait, so your returned set contains both types and traits?

@@ -1084,9 +1084,10 @@ impl GenericBound {

fn get_trait_type(&self) -> Option<Type> {
Copy link
Member

@eddyb eddyb Mar 28, 2019

Choose a reason for hiding this comment

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

The existence of a trait path as a value of Type was a mistake, IMO.

If you move DefId into Path, you can replace trait_: Type with path: Path in:

pub struct PolyTrait {
pub trait_: Type,
pub generic_params: Vec<GenericParamDef>,
}

and this (and other places) with PolyTrait { path, generic_params: late_bounds }:
trait_: ResolvedPath {
path,
param_names: None,
did: trait_ref.def_id,
is_generic: false,
},

Wait, Path has a Def which contains a DefId:

pub struct Path {
pub global: bool,
pub def: Def,
pub segments: Vec<PathSegment>,
}

So Type::ResolvedPath's DefId is just redundant?!

Copy link
Member

Choose a reason for hiding this comment

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

Oh, you'd need this to take a Def, too (which can replace trait_did):

fn external_path(cx: &DocContext<'_>, name: &str, trait_did: Option<DefId>, has_self: bool,
bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> Path {

@eddyb
Copy link
Member

eddyb commented Apr 8, 2019

Opened #59789.

bors added a commit that referenced this pull request Apr 9, 2019
Revert two unapproved changes to rustc_typeck.

There was a breakdown in process (#59004 (comment), #58894 (comment)) and two changes were made to `rustc_typeck`'s "collect" queries, for rustdoc, that were neither needed *nor* correct.
I'm reverting them here, and will fix up rustdoc *somehow*, if necessary.

cc @rust-lang/compiler How do we ensure this doesn't happen again?

r? @nikomatsakis or @oli-obk
Centril added a commit to Centril/rust that referenced this pull request Nov 7, 2019
Revert two unapproved changes to rustc_typeck.

There was a breakdown in process (rust-lang#59004 (comment), rust-lang#58894 (comment)) and two changes were made to `rustc_typeck`'s "collect" queries, for rustdoc, that were neither needed *nor* correct.
I'm reverting them here, and will fix up rustdoc *somehow*, if necessary.

cc @rust-lang/compiler How do we ensure this doesn't happen again?

r? @nikomatsakis or @oli-obk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants