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 if !data.bounds.is_empty() {
497 f.write_joined(&data.bounds, " + ")?;
499 if let Some(ty) = &data.type_ref {
507 impl HirDisplay for Module {
508 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
509 // FIXME: Module doesn't have visibility saved in data.
510 match self.name(f.db) {
511 Some(name) => write!(f, "mod {}", name),
512 None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) {
513 Some(name) => write!(f, "extern crate {}", name),
514 None => f.write_str("extern crate {unknown}"),
516 None => f.write_str("mod {unnamed}"),
521 impl HirDisplay for Macro {
522 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
524 hir_def::MacroId::Macro2Id(_) => f.write_str("macro"),
525 hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
526 hir_def::MacroId::ProcMacroId(_) => f.write_str("proc_macro"),
528 write!(f, " {}", self.name(f.db))