1 //! HirDisplay implementations for various hir types.
5 TypeOrConstParamData
, TypeParamProvenance
, WherePredicate
, WherePredicateTypeTarget
,
7 type_ref
::{TypeBound, TypeRef}
,
12 write_bounds_like_dyn_trait_with_prefix
, write_visibility
, HirDisplay
, HirDisplayError
,
13 HirFormatter
, SizedByDefault
,
15 Interner
, TraitRefExt
, WhereClause
,
20 Adt
, Const
, ConstParam
, Enum
, Field
, Function
, GenericParam
, HasCrate
, HasVisibility
,
21 LifetimeParam
, Macro
, Module
, Static
, Struct
, Trait
, TyBuilder
, Type
, TypeAlias
,
22 TypeOrConstParam
, TypeParam
, Union
, Variant
,
25 impl HirDisplay
for Function
{
26 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
27 let data
= f
.db
.function_data(self.id
);
28 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
29 if data
.has_default_kw() {
30 f
.write_str("default ")?
;
32 if data
.has_const_kw() {
33 f
.write_str("const ")?
;
35 if data
.has_async_kw() {
36 f
.write_str("async ")?
;
38 if self.is_unsafe_to_call(f
.db
) {
39 f
.write_str("unsafe ")?
;
41 if let Some(abi
) = &data
.abi
{
42 // FIXME: String escape?
43 write
!(f
, "extern \"{}\" ", &**abi
)?
;
45 write
!(f
, "fn {}", data
.name
)?
;
47 write_generic_params(GenericDefId
::FunctionId(self.id
), f
)?
;
51 let write_self_param
= |ty
: &TypeRef
, f
: &mut HirFormatter
<'_
>| match ty
{
52 TypeRef
::Path(p
) if p
.is_self_type() => f
.write_str("self"),
53 TypeRef
::Reference(inner
, lifetime
, mut_
) if matches
!(&**inner
,TypeRef
::Path(p
) if p
.is_self_type()) =>
56 if let Some(lifetime
) = lifetime
{
57 write
!(f
, "{} ", lifetime
.name
)?
;
59 if let hir_def
::type_ref
::Mutability
::Mut
= mut_
{
65 f
.write_str("self: ")?
;
71 for (name
, type_ref
) in &data
.params
{
76 if data
.has_self_param() {
77 write_self_param(type_ref
, f
)?
;
82 Some(name
) => write
!(f
, "{}: ", name
)?
,
83 None
=> f
.write_str("_: ")?
,
85 // FIXME: Use resolved `param.ty` or raw `type_ref`?
86 // The former will ignore lifetime arguments currently.
90 if data
.is_varargs() {
91 f
.write_str(", ...")?
;
96 // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
97 // Use ugly pattern match to strip the Future trait.
99 let ret_type
= if !data
.has_async_kw() {
102 match &*data
.ret_type
{
103 TypeRef
::ImplTrait(bounds
) => match bounds
[0].as_ref() {
104 TypeBound
::Path(path
, _
) => {
105 path
.segments().iter().last().unwrap().args_and_bindings
.unwrap().bindings
111 _
=> panic
!("Async fn ret_type should be impl Future"),
113 _
=> panic
!("Async fn ret_type should be impl Future"),
118 TypeRef
::Tuple(tup
) if tup
.is_empty() => {}
120 f
.write_str(" -> ")?
;
125 write_where_clause(GenericDefId
::FunctionId(self.id
), f
)?
;
131 impl HirDisplay
for Adt
{
132 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
134 Adt
::Struct(it
) => it
.hir_fmt(f
),
135 Adt
::Union(it
) => it
.hir_fmt(f
),
136 Adt
::Enum(it
) => it
.hir_fmt(f
),
141 impl HirDisplay
for Struct
{
142 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
143 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
144 f
.write_str("struct ")?
;
145 write
!(f
, "{}", self.name(f
.db
))?
;
146 let def_id
= GenericDefId
::AdtId(AdtId
::StructId(self.id
));
147 write_generic_params(def_id
, f
)?
;
148 write_where_clause(def_id
, f
)?
;
153 impl HirDisplay
for Enum
{
154 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
155 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
156 f
.write_str("enum ")?
;
157 write
!(f
, "{}", self.name(f
.db
))?
;
158 let def_id
= GenericDefId
::AdtId(AdtId
::EnumId(self.id
));
159 write_generic_params(def_id
, f
)?
;
160 write_where_clause(def_id
, f
)?
;
165 impl HirDisplay
for Union
{
166 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
167 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
168 f
.write_str("union ")?
;
169 write
!(f
, "{}", self.name(f
.db
))?
;
170 let def_id
= GenericDefId
::AdtId(AdtId
::UnionId(self.id
));
171 write_generic_params(def_id
, f
)?
;
172 write_where_clause(def_id
, f
)?
;
177 impl HirDisplay
for Field
{
178 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
179 write_visibility(self.parent
.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
180 write
!(f
, "{}: ", self.name(f
.db
))?
;
181 self.ty(f
.db
).hir_fmt(f
)
185 impl HirDisplay
for Variant
{
186 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
187 write
!(f
, "{}", self.name(f
.db
))?
;
188 let data
= self.variant_data(f
.db
);
190 VariantData
::Unit
=> {}
191 VariantData
::Tuple(fields
) => {
193 let mut first
= true;
194 for (_
, field
) in fields
.iter() {
200 // Enum variant fields must be pub.
201 field
.type_ref
.hir_fmt(f
)?
;
205 VariantData
::Record(fields
) => {
207 let mut first
= true;
208 for (_
, field
) in fields
.iter() {
215 // Enum variant fields must be pub.
216 write
!(f
, "{}: ", field
.name
)?
;
217 field
.type_ref
.hir_fmt(f
)?
;
226 impl HirDisplay
for Type
{
227 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
232 impl HirDisplay
for GenericParam
{
233 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
235 GenericParam
::TypeParam(it
) => it
.hir_fmt(f
),
236 GenericParam
::ConstParam(it
) => it
.hir_fmt(f
),
237 GenericParam
::LifetimeParam(it
) => it
.hir_fmt(f
),
242 impl HirDisplay
for TypeOrConstParam
{
243 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
244 match self.split(f
.db
) {
245 either
::Either
::Left(x
) => x
.hir_fmt(f
),
246 either
::Either
::Right(x
) => x
.hir_fmt(f
),
251 impl HirDisplay
for TypeParam
{
252 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
253 write
!(f
, "{}", self.name(f
.db
))?
;
254 if f
.omit_verbose_types() {
258 let bounds
= f
.db
.generic_predicates_for_param(self.id
.parent(), self.id
.into(), None
);
259 let substs
= TyBuilder
::placeholder_subst(f
.db
, self.id
.parent());
260 let predicates
: Vec
<_
> =
261 bounds
.iter().cloned().map(|b
| b
.substitute(Interner
, &substs
)).collect();
262 let krate
= self.id
.parent().krate(f
.db
).id
;
264 f
.db
.lang_item(krate
, SmolStr
::new_inline("sized"))
265 .and_then(|lang_item
| lang_item
.as_trait());
266 let has_only_sized_bound
= predicates
.iter().all(move |pred
| match pred
.skip_binders() {
267 WhereClause
::Implemented(it
) => Some(it
.hir_trait_id()) == sized_trait
,
270 let has_only_not_sized_bound
= predicates
.is_empty();
271 if !has_only_sized_bound
|| has_only_not_sized_bound
{
272 let default_sized
= SizedByDefault
::Sized { anchor: krate }
;
273 write_bounds_like_dyn_trait_with_prefix(":", &predicates
, default_sized
, f
)?
;
279 impl HirDisplay
for LifetimeParam
{
280 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
281 write
!(f
, "{}", self.name(f
.db
))
285 impl HirDisplay
for ConstParam
{
286 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
287 write
!(f
, "const {}: ", self.name(f
.db
))?
;
288 self.ty(f
.db
).hir_fmt(f
)
292 fn write_generic_params(
294 f
: &mut HirFormatter
<'_
>,
295 ) -> Result
<(), HirDisplayError
> {
296 let params
= f
.db
.generic_params(def
);
297 if params
.lifetimes
.is_empty()
298 && params
.type_or_consts
.iter().all(|x
| x
.1.const_param().is_none())
302 .filter_map(|x
| x
.1.type_param())
303 .all(|param
| !matches
!(param
.provenance
, TypeParamProvenance
::TypeParamList
))
309 let mut first
= true;
310 let mut delim
= |f
: &mut HirFormatter
<'_
>| {
318 for (_
, lifetime
) in params
.lifetimes
.iter() {
320 write
!(f
, "{}", lifetime
.name
)?
;
322 for (_
, ty
) in params
.type_or_consts
.iter() {
323 if let Some(name
) = &ty
.name() {
325 TypeOrConstParamData
::TypeParamData(ty
) => {
326 if ty
.provenance
!= TypeParamProvenance
::TypeParamList
{
330 write
!(f
, "{}", name
)?
;
331 if let Some(default) = &ty
.default {
336 TypeOrConstParamData
::ConstParamData(c
) => {
338 write
!(f
, "const {}: ", name
)?
;
349 fn write_where_clause(def
: GenericDefId
, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
350 let params
= f
.db
.generic_params(def
);
352 // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
353 let is_unnamed_type_target
= |target
: &WherePredicateTypeTarget
| match target
{
354 WherePredicateTypeTarget
::TypeRef(_
) => false,
355 WherePredicateTypeTarget
::TypeOrConstParam(id
) => {
356 params
.type_or_consts
[*id
].name().is_none()
360 let has_displayable_predicate
= params
364 !matches
!(pred
, WherePredicate
::TypeBound { target, .. }
if is_unnamed_type_target(target
))
367 if !has_displayable_predicate
{
371 let write_target
= |target
: &WherePredicateTypeTarget
, f
: &mut HirFormatter
<'_
>| match target
{
372 WherePredicateTypeTarget
::TypeRef(ty
) => ty
.hir_fmt(f
),
373 WherePredicateTypeTarget
::TypeOrConstParam(id
) => {
374 match ¶ms
.type_or_consts
[*id
].name() {
375 Some(name
) => write
!(f
, "{}", name
),
376 None
=> f
.write_str("{unnamed}"),
381 f
.write_str("\nwhere")?
;
383 for (pred_idx
, pred
) in params
.where_predicates
.iter().enumerate() {
385 if pred_idx
== 0 { None }
else { Some(¶ms.where_predicates[pred_idx - 1]) }
;
387 let new_predicate
= |f
: &mut HirFormatter
<'_
>| {
388 f
.write_str(if pred_idx
== 0 { "\n " }
else { ",\n " }
)
392 WherePredicate
::TypeBound { target, .. }
if is_unnamed_type_target(target
) => {}
393 WherePredicate
::TypeBound { target, bound }
=> {
394 if matches
!(prev_pred
, Some(WherePredicate
::TypeBound { target: target_, .. }
) if target_
== target
)
399 write_target(target
, f
)?
;
404 WherePredicate
::Lifetime { target, bound }
=> {
405 if matches
!(prev_pred
, Some(WherePredicate
::Lifetime { target: target_, .. }
) if target_
== target
)
407 write
!(f
, " + {}", bound
.name
)?
;
410 write
!(f
, "{}: {}", target
.name
, bound
.name
)?
;
413 WherePredicate
::ForLifetime { lifetimes, target, bound }
=> {
416 Some(WherePredicate
::ForLifetime { lifetimes: lifetimes_, target: target_, .. }
)
417 if lifetimes_
== lifetimes
&& target_
== target
,
422 f
.write_str("for<")?
;
423 for (idx
, lifetime
) in lifetimes
.iter().enumerate() {
427 write
!(f
, "{}", lifetime
)?
;
430 write_target(target
, f
)?
;
438 // End of final predicate. There must be at least one predicate here.
444 impl HirDisplay
for Const
{
445 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
446 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
447 let data
= f
.db
.const_data(self.id
);
448 f
.write_str("const ")?
;
450 Some(name
) => write
!(f
, "{}: ", name
)?
,
451 None
=> f
.write_str("_: ")?
,
453 data
.type_ref
.hir_fmt(f
)?
;
458 impl HirDisplay
for Static
{
459 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
460 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
461 let data
= f
.db
.static_data(self.id
);
462 f
.write_str("static ")?
;
464 f
.write_str("mut ")?
;
466 write
!(f
, "{}: ", &data
.name
)?
;
467 data
.type_ref
.hir_fmt(f
)?
;
472 impl HirDisplay
for Trait
{
473 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
474 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
475 let data
= f
.db
.trait_data(self.id
);
477 f
.write_str("unsafe ")?
;
480 f
.write_str("auto ")?
;
482 write
!(f
, "trait {}", data
.name
)?
;
483 let def_id
= GenericDefId
::TraitId(self.id
);
484 write_generic_params(def_id
, f
)?
;
485 write_where_clause(def_id
, f
)?
;
490 impl HirDisplay
for TypeAlias
{
491 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
492 write_visibility(self.module(f
.db
).id
, self.visibility(f
.db
), f
)?
;
493 let data
= f
.db
.type_alias_data(self.id
);
494 write
!(f
, "type {}", data
.name
)?
;
495 let def_id
= GenericDefId
::TypeAliasId(self.id
);
496 write_generic_params(def_id
, f
)?
;
497 write_where_clause(def_id
, f
)?
;
498 if !data
.bounds
.is_empty() {
500 f
.write_joined(&data
.bounds
, " + ")?
;
502 if let Some(ty
) = &data
.type_ref
{
510 impl HirDisplay
for Module
{
511 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
512 // FIXME: Module doesn't have visibility saved in data.
513 match self.name(f
.db
) {
514 Some(name
) => write
!(f
, "mod {}", name
),
515 None
if self.is_crate_root(f
.db
) => match self.krate(f
.db
).display_name(f
.db
) {
516 Some(name
) => write
!(f
, "extern crate {}", name
),
517 None
=> f
.write_str("extern crate {unknown}"),
519 None
=> f
.write_str("mod {unnamed}"),
524 impl HirDisplay
for Macro
{
525 fn hir_fmt(&self, f
: &mut HirFormatter
<'_
>) -> Result
<(), HirDisplayError
> {
527 hir_def
::MacroId
::Macro2Id(_
) => f
.write_str("macro"),
528 hir_def
::MacroId
::MacroRulesId(_
) => f
.write_str("macro_rules!"),
529 hir_def
::MacroId
::ProcMacroId(_
) => f
.write_str("proc_macro"),
531 write
!(f
, " {}", self.name(f
.db
))