-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
Add intra-doc field@
disambiguator
#83546
Conversation
Some changes occurred in intra-doc-links. cc @jyn514 |
r? @jyn514 (rust-highfive has picked a reviewer for you, use r? to override) |
This change required some refactoring because fields (1) don't get their own `Res` (instead they seem to use the `Res` of their parent node) and (2) `DefKind::Field::ns()` returns `None`, so rustdoc has to special-case fields. For some reason, we treat fields as if they're in the value namespace - I'm not sure why that is.
842fb22
to
58de79f
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually kinda iffy on this, I prefer the current behavior and we get to avoid clashes with foo.com.
Yeah I'm just worried about the possibilities of ambiguity. It was listed as an optional extension in the rfc and iirc this was part of why.
@Manishearth are you happy with this now that there's no ambiguity?
if expect_field { | ||
self.resolve_variant_or_field(item_name, did, ty_res, extra_fragment) | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is already super long with lots of indentation - could you change this to a separate match arm? Res::Def(...) if expect_field => { ... }
Alternatively you could turn this whole match into a separate function, which lets you do an early return.
match self.cx.tcx.type_of(did).kind() { | ||
ty::Adt(def, _) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would make this an early return so you don't have so much indentation.
match self.cx.tcx.type_of(did).kind() { | |
ty::Adt(def, _) => { | |
let def = match self.cx.tcx.type_of(did).kind() { | |
ty::Adt(def, _) => def, | |
_ => return None, | |
}; |
// Fields are resolved to their parent type's Res. | ||
// FIXME: what about DefKind::Variant? | ||
| (DefKind::Struct | DefKind::Enum, Some(Disambiguator::Kind(DefKind::Field))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks suspicious ... I'd have to look into how exactly rustc_resolve behaves here, but I'd rather not allow people to write
/// [field@S]
struct S;
and have it work. Maybe you could add this to yet another side channel? 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks suspicious ... I'd have to look into how exactly rustc_resolve behaves here, but I'd rather not allow people to write
/// [field@S] struct S;and have it work.
Your suspicion is correct, because that code works fine....
I don't think it's rustc_resolve
behavior; we seem to use rustc_resolve
to resolve everything up until the field, and then resolve that manually ourselves somehow. It seems like this code could use some cleanup; I think it would be a good idea for us to have our own Res
enum that includes fields. Maybe it would be a good idea to do that first before implementing this feature?
Or, is there some way that rustc_resolve
can resolve fields for us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, is there some way that rustc_resolve can resolve fields for us?
I wouldn't expect so, since that needs type information (put another way, it can only resolve things that have a namespace).
I think it would be a good idea for us to have our own Res enum that includes fields.
Ok, there's already a custom Res
type you could modify:
enum Res { |
Res::Def(DefKind::Field)
to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be a good idea for us to have our own Res enum that includes fields.
Ok, there's already a custom
Res
type you could modify:
enum Res { . But I'm not sure why that needs a new variant, I would expect using a normal
Res::Def(DefKind::Field)
to work.
Sounds good! I said that because I didn't understand why we didn't just use Res::Def(DefKind::Field)
for the field resolution. So I think a good cleanup to do before I add this feature is to use Res::Def(DefKind::Field)
to resolve fields instead of resolving them to their parent struct/enum. I think I'll play around with that a bit to see if I can get it working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think a good cleanup to do before I add this feature is to use Res::Def(DefKind::Field) to resolve fields instead of resolving them to their parent struct/enum. I think I'll play around with that a bit to see if I can get it working.
Buyer beware:
rust/src/librustdoc/passes/collect_intra_doc_links.rs
Lines 605 to 608 in d474075
// HACK(jynelson): `clean` expects the type, not the associated item | |
// but the disambiguator logic expects the associated item. | |
// Store the kind in a side channel so that only the disambiguator logic looks at it. | |
self.kind_side_channel.set(Some((kind.as_def_kind(), id))); |
but if you get it working that would be amazing :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh-oh... ;)
// Fields technically don't have a namespace, but we treat | ||
// fields as if they belong to the value namespace. | ||
DefKind::Field => TypeNS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Fields technically don't have a namespace, but we treat | |
// fields as if they belong to the value namespace. | |
DefKind::Field => TypeNS, | |
// Fields technically don't have a namespace, but we treat | |
// fields as if they belong to the value namespace. | |
DefKind::Field => ValueNS, |
Do we need to return a namespace here? Would it be better to return an Option, the same way DefKind::ns
does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops... I said they belong to the value namespace because I saw that elsewhere, but I think in my mind I thought type namespace fitted better. Need to figure out if it makes sense to update elsewhere to use TypeNS
or to switch to using ValueNS
here...
@jyn514 If this is allowing |
Ok great, that's what this is :) |
Great! 👍 I had an idea on how to get this to be like |
That would be the first time we clean up the displayed text in intra doc links, no? Or do we do that already? |
We remove disambiguators from the displayed text, so |
I would rather not change the display. |
Yeah I think I'm aligned with @jyn514 on this one for now |
Actually this is a good point - I think we should only remove the disambiguator if it's not a field, since otherwise it's ambiguous with the method (and |
I actually meant without the ambiguity that Manish was concerned about re domain names. I think we should still strip the disambiguator. It's inconsistent and surprising if we strip all disambiguators except just |
Yeah I'm happy to strip the disambiguator. |
Ok, in that case this is just waiting on questions about the implementation. |
I think I would like to talk about #83546 (comment) before I address the review comments, since I don't want to waste time working on things that would be fixed by doing the cleanup. |
The job Click to see the possible cause of the failure (guessed by this bot)
|
This link doesn't go anywhere for me - can you summarize what it says so I can find it? |
Hmm, the link doesn't work for me either. It's the comment that you just replied to. Here's a working link: #83546 (comment) |
☔ The latest upstream changes (presumably #83905) made this pull request unmergeable. Please resolve the merge conflicts. |
@camelid are you planning to follow up on this? |
I'm not sure if I'll have the time soon to do the necessary refactor to get this working. I'm trying to make progress on some smaller PRs that I've had open for a while. I might be able to get to this after those. |
@camelid I'm going to close this so someone else can pick up the issue - feel free to come back to this if you have time :) |
This change required some refactoring because fields (1) don't get their
own
Res
(instead they seem to use theRes
of their parent node) and(2)
DefKind::Field::ns()
returnsNone
, so rustdoc has tospecial-case fields. For some reason, we treat fields as if they're in
the value namespace - I'm not sure why that is.
Fixes #80283.