This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Parameter hints for template specialization
AbandonedPublic

Authored by v1nh1shungry on Nov 21 2022, 5:55 AM.

Details

Diff Detail

Event Timeline

v1nh1shungry created this revision.Nov 21 2022, 5:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 21 2022, 5:55 AM
v1nh1shungry requested review of this revision.Nov 21 2022, 5:55 AM

This patch implements:

  • Template specialization type
  • Class template specialization declaration
  • Variable template specialization declaration
  • Function specialization declaration

It would be sweet to also implement:

template <class T> constexpr int value = 0;
int I = value</*T: */int>;

template <class T> T add(T lhs, T rhs);
add</*T: */int>(1, 2);

But I got stuck on implementing these. I tried VisitDeclRefExpr but failed and have no idea. I prefer to implement these in future patches. But yes, if anyone could give me some hints I am happy to update the patch.

The code looks pretty good and this makes a lot of logical sense.

However, there's an ugly practical issue: it's overwhelmingly common for template parameters to have cryptic and useless names.
It seems like turning vector<int> into vector</*Tp: */int> actually makes things worse.

And this gets yet worse: because this is type parameter and controlled by that config option, so people can't disable this without disabling the (very practically useful) function param hints.

Have you been using this for a while? Do you find it to be a practical help? Spammy?

clang-tools-extra/clangd/InlayHints.cpp
378

we need a bailout if (!Cfg.InlayHints.Parameters)

434

we're missing some mangling of the name to remove the leading _
(stripLeadingUnderscore?)

553

I think we should avoid running the printer on every arg. Instead probably switch over the types of templatearguments, and delegate to shouldHintName(Expr, handle TagType/Typedef/other common nodes specifically, as done in shouldHintName).

@sammccall Thank you for reviewing and giving suggestions!

I must admit I didn't use it for very long. But I do think this is helpful, at least for templates I'm unfamiliar with.

Yes, there is a common situation where people use a meaningless template parameter name, but I think the same for functions. I have seen many meaningless parameter names like D, E even in the LLVM codebase. Since we can tolerate these, why can't we bear the template parameter?

And yes, it is a serious problem this is unconfigurable.

clang-tools-extra/clangd/InlayHints.cpp
434

I don't think we should, since we don't do this for function parameters, are there any special reasons for us to do this for template parameters?

@sammccall Thank you for reviewing and giving suggestions!

I must admit I didn't use it for very long. But I do think this is helpful, at least for templates I'm unfamiliar with.

That sounds good, maybe you can give some examples?
I'm thinking about a heuristic like "show hints where the param name is >2 chars long" or something, at least as a starting point - would be good to see whether this would still provide the value you're seeing.

Yes, there is a common situation where people use a meaningless template parameter name, but I think the same for functions.

I don't think it's the same: my wild guess would be 30% of function params have useless names, and 90% of template params do.
If this were accurate, it seems function param hints are usually (potentially) useful, while template params are almost always useless.

I have seen many meaningless parameter names like D, E even in the LLVM codebase.

Agree. LLVM does this (much) more than the other codebases I'm familiar with.
I'd personally be very happy if we could somehow detect and suppress hints for such params.
But it's not clear-cut: template<class K, class V> class map can be meaningful, and with push-to-show-hints interaction the lack of a hint can be confusing.

Since we can tolerate these, why can't we bear the template parameter?

If template params are useless a larger fraction of the time, then enabling them without doing some filtering might be a net negative in practice.

And yes, it is a serious problem this is unconfigurable.

We can add a new config category for these (use Config::InlayHints::TemplateParameters), it's just a bit ugly to do so.

clang-tools-extra/clangd/InlayHints.cpp
434

We do this for function params, see line 574 of the LHS

Yes, there is a common situation where people use a meaningless template parameter name, but I think the same for functions.

I don't think it's the same: my wild guess would be 30% of function params have useless names, and 90% of template params do.
If this were accurate, it seems function param hints are usually (potentially) useful, while template params are almost always useless.

I agree that is usually useless and too much noise, especially for container like types. But, it could maybe be useful for template parameters that have a default value? For example, I'll never need an inlay hint for something like `std::map<K, V>, but when passing a custom comparator and allocator as the 3rd and 4th template type, inlay hints might actually be helpful there.

FWIW, in codebases/components where I do code reviews, I tend to insist on template parameters having meaningful (and longer-than-one-character) names, and would find this quite useful.

I agree that while template parameters are technically a kind of parameter, they're different enough from function parameters that configuring this type of hint separately (and thus giving them their own kind) would make sense.

v1nh1shungry abandoned this revision.Nov 21 2022, 5:56 PM

Sorry for the delay.

I'd say I was convinced and about to abandon this patch.

Sincere apologies for wasting everyone's time.