Skip to content

Inlay Hints ​

clice renders inline annotations for the information the code leaves implicit: parameter names at call sites, deduced types, and the field names behind positional aggregate initialization. Hint categories can be toggled individually through the [inlay_hints] configuration section; the sections below describe the categories that are on by default.

Parameter Hints ​

Supported

Parameter name hints

Call sites show parameter names for functions and constructors

Supportedclangd#1877

Hint suppression

Named arguments and /*name=*/ comments suppress parameter hints

Supported

Setter and builtin suppression

setX(x) and std::move/std::forward arguments stay bare

Supportedclangd#1123

Mutable reference markers

& flags arguments passed by non-const lvalue reference

Supportedclangd#2324

Forwarding resolution

Packs forwarded through wrappers resolve to the target's parameter names

Supported

Names from definitions

Unnamed declaration parameters take the definition's names; leading underscores strip

Function pointers and call operators

Indirect calls still name their parameters

Supportedclangd#1777

Deducing this

The explicit object parameter never hints (C++23)

Supported

Dependent calls

Parameter names appear even when the callee is only known inside a template

Candidates are matched by argument count; only a unique surviving candidate names the parameters, so a call that could still hit several overloads stays bare rather than guessing.

Supported

Unexpanded packs

A written pack expansion breaks the 1:1 argument mapping and stops hinting

Supportedclangd#2620

Macros at call sites

Arguments spelled as macros hint; calls generated inside macro bodies do not

Supported

Implicit constructor calls

Conversions the code never wrote produce no hints of their own

Supported

Pseudo-object expressions

MS property accesses stay quiet; written subscripts keep the accessor's names

Supportedclangd#1034

Explicit instantiation

An explicit instantiation definition adds no duplicate hints, while its written template arguments hint normally

Sloppy name matching

aParam does not yet suppress an argument spelled param

Inherited constructors

using Base::Base calls lose their parameter names

Supported

Anonymous parameters

Unnamed parameters produce no name hint, though mutable references still show &

Supported

Operators and literals

Operator syntax and user-defined literals stay bare; member and default member initializers hint

Partial

Packs in constructor arguments

Outer calls resolve; hints inside the expansion are still missing

Type Hints ​

Supported

Deduced auto variables

The hint shows the full variable type, qualifiers included

Type sugar length limits

Aliases keep their spelling; over-long types fall back to the sugared name

Supported

Structured bindings

Each binding hints its canonical type; the aggregate itself stays bare

Supportedclangd#1163

Lambdas

Variables, deduced return types, and init-captures all hint

Supported

Deduced return types

Deduced return types appear as -> T after the parameter list

Supported

decltype spellings

The underlying type shows next to the written decltype

Supported

auto parameters

A template with exactly one instantiation reveals the deduced type

Explicitly spelled initializers

Casts and functional casts still hint redundantly

Dependent auto

Deduction inside an uninstantiated template body stays silent

Supported

Scope suppression

Namespace qualifiers drop from hints; class scopes stay

Supported

Tuple-protocol bindings

Hints print the canonical type, not tuple_element<I, T>::type

Instantiated templates

Instantiated bodies repeat no hints at the pattern; dependent auto could reveal the deduced type while exactly one instantiation exists

Designator Hints ​

Supportedclangd#2303

Field and index designators

Positional aggregate initialization shows .field= and [index]=

Supported

Nested aggregates

Written braces recurse; omitted braces flatten into .outer.inner=

Supported

Anonymous members

Unnamed unions and structs vanish from the designator path

Supported

Designator suppression

Written designators and /*name=*/ comments keep their inits bare

Supported

Aggregates only

Constructor calls, copies and idiomatic zero-init produce no designators

Supported

Broken initializers

Designators survive next to initializers that fail to compile

Unsupportedclangd#2540

Parenthesized aggregate initialization

C++20 Point(1, 2) gets no hints yet

Other Hint Kinds ​

Unsupportedclangd#2583

Template parameter hints

Template argument hints are not emitted at call sites yet

Unsupportedclangd#2331

CTAD arguments

CTAD does not display deduced class template arguments yet

Unsupportedclangd#2254

Implicit conversion hints

Implicit conversions at call sites have no hints yet

Block End Hints ​

Off by default (inlay_hints.block_end). After the closing brace of a block spanning at least two lines, clice shows the name of what the brace closes — functions, types, namespaces, and control-flow statements:

cpp
void Widget::process(const Config& cfg) {
    // ...
} // Widget::process

namespace detail {
    // ...
} // namespace detail

while (running) {
    // ...
} // while running

Condition summaries print for if/while/switch/for where a short spelling exists; an else if chain hints as plain // if. Labels longer than 60 characters are dropped.

A related idea, #endif hints showing the matching condition (clangd#2487), is not implemented.

Default Argument Hints ​

Off by default (inlay_hints.default_arguments). Call sites that rely on default arguments show what was omitted, abbreviated past the type-name limit:

cpp
void log(int level, bool flush = true, int repeat = 1);
log(2);
//     ^ , flush: true, repeat: 1

Configuration ​

The [inlay_hints] section of clice.toml (or the same keys via initializationOptions) controls every category: enabled, parameters, deduced_types, designators, block_end, default_arguments, and type_name_limit. See the configuration guide for details. Configuration changes take effect after a server restart — a recompile is never involved.

Interactive Behavior ​

  • Requests are range-scoped: hints outside the requested range are discarded.
  • Parameter hints anchor to the left of their argument; type and designator hints anchor to their declaration side with LSP padding flags instead of embedded spaces.
  • Identical duplicate hints (e.g. from template instantiations) collapse into one.

Other Known Gaps ​

  • Abbreviated type hints with expandable label parts via InlayHintLabelPart (clangd#2269)
  • Clickable type names — go-to-definition on the hinted type (clangd#1535)
  • Scope-aware type shortening — print Bar instead of foo::Bar inside namespace foo (clangd#2270)
  • Parameter hints lost when a coroutine returns a template type (clangd#2437)