ilya-biryukov added inline comments.
================ Comment at: clang-tools-extra/clangd/FindTarget.h:194 +llvm::SmallVector<const NamedDecl *, 1> +explicitReferenceTargets(ast_type_traits::DynTypedNode N, + DeclRelationSet Mask = {}); ---------------- ilya-biryukov wrote: > sammccall wrote: > > ilya-biryukov wrote: > > > sammccall wrote: > > > > ilya-biryukov wrote: > > > > > sammccall wrote: > > > > > > ilya-biryukov wrote: > > > > > > > sammccall wrote: > > > > > > > > ilya-biryukov wrote: > > > > > > > > > sammccall wrote: > > > > > > > > > > ilya-biryukov wrote: > > > > > > > > > > > No need to fix this. > > > > > > > > > > > > > > > > > > > > > > The name could probably be better, but we can fix this > > > > > > > > > > > later. Don't have any good ideas. > > > > > > > > > > I think as a public API this should be clearer on how/when > > > > > > > > > > to use and its relation to other things (planning to send a > > > > > > > > > > patch, but wanted to discuss a bit here first). > > > > > > > > > > > > > > > > > > > > - This is essentially a filter of allTargetDecls (as is > > > > > > > > > > targetDecl), but the relationship between the two isn't > > > > > > > > > > clear. They should have closely related names (variant) or > > > > > > > > > > maybe better be more orthogonal and composed at the > > > > > > > > > > callsite. > > > > > > > > > > - The most distinctive word in the name is `explicit`, but > > > > > > > > > > this function doesn't actually have anything to do with > > > > > > > > > > explicit vs non-explicit references (just history?) > > > > > > > > > > - It's not clear to me whether we actually want to > > > > > > > > > > encapsulate/hide the preference for instantiations over > > > > > > > > > > templates here, or whether it should be expressed at the > > > > > > > > > > callsite because the policy is decided feature-by-feature. > > > > > > > > > > `chooseBest(...)` vs `prefer(TemplateInstantiation, > > > > > > > > > > TemplatePattern, ...)`. The latter seems safer to me, based > > > > > > > > > > on experience with targetDecl so far. > > > > > > > > > > > > > > > > > > > > A couple of ideas: > > > > > > > > > > - caller invokes allTargetDecls() and then this is a > > > > > > > > > > helper function `prefer(DeclRelation, DeclRelation, > > > > > > > > > > Results)` that mutates Results > > > > > > > > > > - targetDecl() becomes the swiss-army filter and accepts a > > > > > > > > > > list of "prefer-X-over-Y", which it applies before > > > > > > > > > > returning the results with flags dropped > > > > > > > > > I don't like the idea of `targetDecl` becoming the swiss-army > > > > > > > > > knife, it's complicated to use as is. > > > > > > > > > The contract of `explicitReferenceTargets` is to expose only > > > > > > > > > the decls written in the source code and nothing else, it's > > > > > > > > > much simpler to explain and to use. > > > > > > > > > > > > > > > > > > It's useful for many things, essentially for anything that > > > > > > > > > needs to answer the question of "what does this name in the > > > > > > > > > source code refers to". > > > > > > > > > > > > > > > > > > The name could be clearer, the comments might need to be > > > > > > > > > improved. > > > > > > > > > The only crucial improvement that I'd attempt is getting rid > > > > > > > > > of the `Mask` parameter, I think there was just one or two > > > > > > > > > cases where it was useful. > > > > > > > > > > > > > > > > > > > > > > > > > > > I don't like the idea of targetDecl becoming the swiss-army > > > > > > > > > knife > > > > > > > > Fair enough. I'll poke more in the direction of making it > > > > > > > > easier to compose allTargetDecls then. > > > > > > > > > > > > > > > > > The contract of explicitReferenceTargets is to expose only > > > > > > > > > the decls written in the source code and nothing else, it's > > > > > > > > > much simpler to explain and to use. > > > > > > > > So I agree that the interface of targetDecl() is complicated, > > > > > > > > but I don't think this one is simpler to explain or use - or at > > > > > > > > least it hasn't been well-explained so far. > > > > > > > > > > > > > > > > For example, > > > > > > > > - "to expose only the decls written in the source code" - > > > > > > > > `vector<int>` isn't a decl written in the source code. > > > > > > > > - "find declarations explicitly referenced in the source code" > > > > > > > > - `return [[{foo}]];` - the class/constructor isn't explicitly > > > > > > > > referenced, but this function returns it. > > > > > > > > - "what does this name in the source code refers to" - a > > > > > > > > template name refers to the primary template, the (possible) > > > > > > > > partial specialization, and specialization all at once. > > > > > > > > Features like find refs/highlight show the equivalence class of > > > > > > > > names that refer to the same thing, but they don't prefer the > > > > > > > > specialization for that. > > > > > > > > - none of these explanations explains why the function is > > > > > > > > opinionated about template vs expansion but not about alias vs > > > > > > > > underlying. > > > > > > > > > > > > > > > > > No need to fix this. > > > > > > > > > The name could probably be better, but we can fix this later. > > > > > > > > > Don't have any good ideas. > > > > > > > > > > > > > > > > I think it's fine (and good!) that we this got added to unblock > > > > > > > > the hover work and to understand more use cases for this API. > > > > > > > > But I do think it's time to fix it now, and I'm not convinced a > > > > > > > > better name will do it (I can't think of a good name to > > > > > > > > describe the current functionality, either). Let me put a patch > > > > > > > > together and take a look? > > > > > > > What's the proposed fix? > > > > > > > > > > > > > > I might miss some context with the examples you provided, but > > > > > > > here's my view on how each of those should be handled: > > > > > > > - `vector<int>`. This function **can** return decls, not written > > > > > > > in the source code (e.g. template instantiations). References to > > > > > > > those decls should be written in the source code explicitly, not > > > > > > > the decls themselves. > > > > > > > - `return {foo}`. I agree this one is a corner case that we > > > > > > > should describe. It still provides sensible results that could be > > > > > > > used by hover, etc. > > > > > > > - "what does this name in the source code refers to". That's > > > > > > > exactly what this function is about. We want to pick the most > > > > > > > specific thing possible (i.e. the instantiation). Client code can > > > > > > > go from instantiation to template pattern, it can't go the other > > > > > > > way. There are exceptions where returning instantiation is not > > > > > > > possible - instantiations of template type aliases, dependent > > > > > > > template instantiations. We choose template pattern there, but we > > > > > > > don't really loose any information (if we choose to return Decl, > > > > > > > there's nothing else we can return). > > > > > > > - "none of these explanations explains why the function is > > > > > > > opinionated about template vs expansion but not about alias vs > > > > > > > underlying." That I agree with, I think it's possible to make it > > > > > > > opinionated there and remove the `Mask` parameter. I'm happy to > > > > > > > take a look, but don't want to clash with you if you're doing the > > > > > > > same thing. Would you want me to give it a try? > > > > > > > > > > > > > > What's the proposed fix? > > > > > > (FWIW I wrote this post upside-down, because I don't/didn't have > > > > > > the ideas worked out and this discussion has shaped my thinking a > > > > > > lot) > > > > > > > > > > > > My proposal would be to evolve both `targetDecl()` and > > > > > > `explicitReferenceTargets` into composable functions that help > > > > > > select the desired results of `allTargetDecls()`. Policy would be > > > > > > encoded at callsites, so functions would be quite specific (e.g. > > > > > > `preferTemplateInstantations`), or data-driven > > > > > > `filter(DeclRelationSet)`. > > > > > > Some reasoning below - basically I'm not convinced that the "do > > > > > > what I mean" behavior is well-defined here. > > > > > > > > > > > > > I agree this one is a corner case that we should describe. It > > > > > > > still provides sensible results that could be used by hover, etc. > > > > > > > > > > > > Yeah, it's the right behaviour. My point is that I don't think the > > > > > > policy being implemented here is "explicitness" - another example > > > > > > from a recent patch, CTAD `^vector x{1,2,3}` we want the > > > > > > instantiation. > > > > > > > > > > > > Maybe it's "specificness", but this raises questions: > > > > > > - how often is "most specific" the thing we want, vs "decl that's > > > > > > in source code" or "everything for completeness" > > > > > > - does the concept of 'specificness' generalize to alias vs > > > > > > underlying? > > > > > > > > > > > > My impression is that it's *sometimes* what we want, but not > > > > > > overwhelmingly often (e.g. not go-to-def or documentHighlights) and > > > > > > that it doesn't generalize well[1]. If that's the case, I think > > > > > > this should be apolicy expressed at callsites in features > > > > > > (`preferTemplateInstantiations` or something). > > > > > > > > > > > > It would be nice if there's some global concept of "preferredness", > > > > > > but looking at the needs of different features, I really don't see > > > > > > one - that's why targetDecl is so complicated. > > > > > > > > > > > > [1] Example of it not generalizing well - for hover we want > > > > > > instantiations over patterns, but after discussing with Kadir I > > > > > > think we want *both* the alias and the underlying so we can show > > > > > > the docs/association from the alias and the structured info from > > > > > > the underlying. > > > > > - `vector x{1,2,3}` should definitely return an instantiation, that > > > > > aligns with the contract of the function. > > > > > I know explicit is a bad name for this concept, it's more intricate. > > > > > > > > > > I would argue we want the most specific one for hover and if we want > > > > > to look into the underlying decls hover code is simple if it does so > > > > > explicitly, rather than passing custom filters to `allTargetDecls`. > > > > > > > > > > My impression is that evolving this into custom filter for > > > > > `allTargetDecls` makes the callsites more complicated. Having a > > > > > single "swiss-knife"-style function is good for sharing > > > > > implementation, but the client code is more complicated and > > > > > error-prone with it. > > > > > > > > > > I would strongly suggest to keep `explicitReferenceTargets`, most > > > > > code is simpler with it. Most "filtering" and "getting underlying > > > > > decls" can be done in the client code and the client code is more > > > > > straightforward with it. > > > > > I know explicit is a bad name for this concept, it's more intricate. > > > > So at this point, I don't understand what the concept is, neither the > > > > name nor the doc comment describe it well. If you want to keep it, can > > > > you describe what the concept is at a high level and how it should > > > > interact with aliases, and suggest a name that is specific enough that > > > > it at least hints at the true distinction vs generic allTargetDecls()? > > > > > > > > > rather than passing custom filters to allTargetDecls > > > > allTargetDecls doesn't accept filters, and I don't suggest changing > > > > that. Are you referring to targetDecls? If so I think we're agreed on > > > > that point. > > > > > > > > > I would argue we want the most specific one for hover and if we want > > > > > to look into the underlying decls hover code is simple if it does so > > > > > explicitly > > > > I guess you're saying the alias is more specific here? Unfortunately > > > > the alias doesn't preserve the underlying decl in general. We need both > > > > decls - one preserving the alias and the other preserving the type > > > > arg/overload. > > > > > > > > > I would strongly suggest to keep explicitReferenceTargets, most code > > > > > is simpler with it. Most "filtering" and "getting underlying decls" > > > > > can be done in the client code and the client code is more > > > > > straightforward with it. > > > > This is what I'm not convinced of. Currently there are 2 users of > > > > explicitReferenceTargets, the original internal user and now hover. > > > > Which of the other targetDecl callsites (Rename and 5 in XRefs) can use > > > > explicitReferenceTargets? How much "getting underlying decls" would > > > > they become responsible for? targetDecl() was in part an effort to > > > > unify this unwrapping because I found it too difficult to maintain the > > > > mechanical bits when they were embedded in each feature. > > > > > > > Here's rough description of the concept: > > > - pick the most specific Decl, whenever possible. That means > > > instantiations for templates instead of patterns and never look through > > > typedefs (Mask has to be removed, this needs a separate refactoring). > > > - I described behaviour on particular examples you mentioned. > > > > > > It's useful because it's a simple way to get the most specific thing > > > written in the source code (even for implicit nodes, we choose to not do > > > complicated things like looking through typedefs). > > > > > > I suggest to call it `getReferencedDecls`. > > > > > > > I guess you're saying the alias is more specific here? Unfortunately > > > > the alias doesn't preserve the underlying decl in general. We need both > > > > decls - one preserving the alias and the other preserving the type > > > > arg/overload. > > > > > > We can get the underlying type in that particular case inside hover, it's > > > just a few lines of code. I don't think there are other cases where we > > > loose information. > > > > > > > > > > This is what I'm not convinced of. Currently there are 2 users of > > > > explicitReferenceTargets, the original internal user and now hover. > > > > Which of the other targetDecl callsites (Rename and 5 in XRefs) can use > > > > explicitReferenceTargets? > > > Rename uses `findExplicitReferences`, which uses > > > `explicitReferenceTargets` internally. XRefs, Rename, Code actions and > > > any refactorings (if we ever do any of those) will benefit from it, but > > > mostly indirectly by using `findExplicitReferences`. It also provides > > > information about source locations of the identifiers that name things, > > > which is crucial for many of those features. > > > > > > > > > > How much "getting underlying decls" would they become responsible for? > > > > targetDecl() was in part an effort to unify this unwrapping because I > > > > found it too difficult to maintain the mechanical bits when they were > > > > embedded in each feature. > > > > > > They would sometimes need to go from template instantiation to template > > > declaration or template pattern and (very rarely) get from typedef to its > > > underlying type. Both are very simple operations. > > > I described behaviour on particular examples you mentioned. > > Those examples weren't cases where I was questioning the behavior, they > > were examples of where the behavior wasn't motivated by the description. > > > > The questions I'm referring to are: > > > - how often is "most specific" the thing we want, vs "decl that's in > > > source code" or "everything for completeness" > > > - does the concept of 'specificness' generalize to alias vs underlying? > > > > I think the latter is answered but not the former. > > > > > We can get the underlying type in that particular case inside hover, it's > > > just a few lines of code. I don't think there are other cases where we > > > loose information. > > There are several cases - at least alias instantiations and using decls of > > overloads. Note that the reported alias decl is the UsingDecl, not the > > UsingShadowDecl. (Changing that case is possible, but would make more work > > for all the other callers). > > > > > I suggest to call it getReferencedDecls. > > This doesn't describe the distinction from targetDecl(). > > > > > Rename uses findExplicitReferences, which uses explicitReferenceTargets > > > internally. XRefs, Rename, Code actions and any refactorings (if we ever > > > do any of those) will benefit from it, but mostly indirectly by using > > > findExplicitReferences. > > > > findExplicitReferences is certainly useful and has a clear API, but that > > doens't require `explicitReferenceTargets` to be public, which is what I'm > > asking here. > > > > Rename uses `targetDecl` together with `TemplatePattern`, which is the > > callsite I was referring to there. > > > > If the answer is that 2/7 current callsites will prefer > > `explicitReferenceTargets` and 5/7 need `targetDecl`, that doesn't seem > > like most code, nor does it seem self-evident that code actions added in > > the future will fall into the first bucket. > > how often is "most specific" the thing we want, vs "decl that's in source > > code" or "everything for completeness" > As mentioned before, I believe the following features would benefit from > this: rename, cross-references, code actions and other refactorings. > > > Note that the reported alias decl is the UsingDecl, not the > > UsingShadowDecl. (Changing that case is possible, but would make more work > > for all the other callers). > What are the callers that would need more work for `UsingShadowDecl`? I lack > context to understand this example. > > This function is useful because it's simpler to use in some cases than > `targetDecl` (if we get rid of `Mask`). > Sure, you **could** write all code using `targetDecl`, it's also ok to add a > few helpers like this to simplify some common cases from my POV. Note that rename and other features using `targetDecl` now would actually be totally fine if they switched to the new function. They actually don't care, but the new function has a simpler interface. It was never intended to be a replacement. `targetDecl` does more stuff. However, this one can have a simpler interface. I prefer to have both and use the one with a simpler interface whenever possible. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D71596/new/ https://reviews.llvm.org/D71596 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits