1 //! HirDisplay implementations for various hir types.
4 generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
5 type_ref::{TypeBound, TypeRef},
10 write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
11 HirFormatter, SizedByDefault,
13 Interner, TraitRefExt, WhereClause,
18 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
19 LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union,
23 impl HirDisplay for Function {
24 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
25 let data = f.db.function_data(self.id);
26 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
27 if data.is_default() {
28 write!(f, "default ")?;
37 write!(f, "unsafe ")?;
39 if let Some(abi) = &data.abi {
40 // FIXME: String escape?
41 write!(f, "extern \"{}\" ", &**abi)?;
43 write!(f, "fn {}", data.name)?;
45 write_generic_params(GenericDefId::FunctionId(self.id), f)?;
49 let write_self_param = |ty: &TypeRef, f: &mut HirFormatter| match ty {
50 TypeRef::Path(p) if p.is_self_type() => write!(f, "self"),
51 TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner,TypeRef::Path(p) if p.is_self_type()) =>
54 if let Some(lifetime) = lifetime {
55 write!(f, "{} ", lifetime.name)?;
57 if let hir_def::type_ref::Mutability::Mut = mut_ {
69 for (name, type_ref) in &data.params {
74 if data.has_self_param() {
75 write_self_param(type_ref, f)?;
80 Some(name) => write!(f, "{}: ", name)?,
81 None => write!(f, "_: ")?,
83 // FIXME: Use resolved `param.ty` or raw `type_ref`?
84 // The former will ignore lifetime arguments currently.
89 // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
90 // Use ugly pattern match to strip the Future trait.
92 let ret_type = if !data.is_async() {
95 match &*data.ret_type {
96 TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
97 TypeBound::Path(path, _) => {
98 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
104 _ => panic!("Async fn ret_type should be impl Future"),
106 _ => panic!("Async fn ret_type should be impl Future"),
111 TypeRef::Tuple(tup) if tup.is_empty() => {}
118 write_where_clause(GenericDefId::FunctionId(self.id), f)?;
124 impl HirDisplay for Adt {
125 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
127 Adt::Struct(it) => it.hir_fmt(f),
128 Adt::Union(it) => it.hir_fmt(f),
129 Adt::Enum(it) => it.hir_fmt(f),
134 impl HirDisplay for Struct {
135 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
136 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
137 write!(f, "struct ")?;
138 write!(f, "{}", self.name(f.db))?;
139 let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
140 write_generic_params(def_id, f)?;
141 write_where_clause(def_id, f)?;
146 impl HirDisplay for Enum {
147 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
148 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
150 write!(f, "{}", self.name(f.db))?;
151 let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
152 write_generic_params(def_id, f)?;
153 write_where_clause(def_id, f)?;
158 impl HirDisplay for Union {
159 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
160 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
161 write!(f, "union ")?;
162 write!(f, "{}", self.name(f.db))?;
163 let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
164 write_generic_params(def_id, f)?;
165 write_where_clause(def_id, f)?;
170 impl HirDisplay for Field {
171 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
172 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
173 write!(f, "{}: ", self.name(f.db))?;
174 self.ty(f.db).hir_fmt(f)
178 impl HirDisplay for Variant {
179 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
180 write!(f, "{}", self.name(f.db))?;
181 let data = self.variant_data(f.db);
183 VariantData::Unit => {}
184 VariantData::Tuple(fields) => {
186 let mut first = true;
187 for (_, field) in fields.iter() {
193 // Enum variant fields must be pub.
194 field.type_ref.hir_fmt(f)?;
198 VariantData::Record(fields) => {
200 let mut first = true;
201 for (_, field) in fields.iter() {
208 // Enum variant fields must be pub.
209 write!(f, "{}: ", field.name)?;
210 field.type_ref.hir_fmt(f)?;
219 impl HirDisplay for Type {
220 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
225 impl HirDisplay for GenericParam {
226 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
228 GenericParam::TypeParam(it) => it.hir_fmt(f),
229 GenericParam::LifetimeParam(it) => it.hir_fmt(f),
230 GenericParam::ConstParam(it) => it.hir_fmt(f),
235 impl HirDisplay for TypeParam {
236 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
237 write!(f, "{}", self.name(f.db))?;
238 if f.omit_verbose_types() {
242 let bounds = f.db.generic_predicates_for_param(self.id, None);
243 let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
244 let predicates: Vec<_> =
245 bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
246 let krate = self.id.parent.krate(f.db).id;
248 f.db.lang_item(krate, SmolStr::new_inline("sized"))
249 .and_then(|lang_item| lang_item.as_trait());
250 let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
251 WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
254 let has_only_not_sized_bound = predicates.is_empty();
255 if !has_only_sized_bound || has_only_not_sized_bound {
256 let default_sized = SizedByDefault::Sized { anchor: krate };
257 write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
263 impl HirDisplay for LifetimeParam {
264 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
265 write!(f, "{}", self.name(f.db))
269 impl HirDisplay for ConstParam {
270 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
271 write!(f, "const {}: ", self.name(f.db))?;
272 self.ty(f.db).hir_fmt(f)
276 fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
277 let params = f.db.generic_params(def);
278 if params.lifetimes.is_empty()
279 && params.consts.is_empty()
283 .all(|(_, param)| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
289 let mut first = true;
290 let mut delim = |f: &mut HirFormatter| {
298 for (_, lifetime) in params.lifetimes.iter() {
300 write!(f, "{}", lifetime.name)?;
302 for (_, ty) in params.types.iter() {
303 if ty.provenance != TypeParamProvenance::TypeParamList {
306 if let Some(name) = &ty.name {
308 write!(f, "{}", name)?;
309 if let Some(default) = &ty.default {
315 for (_, konst) in params.consts.iter() {
317 write!(f, "const {}: ", konst.name)?;
318 konst.ty.hir_fmt(f)?;
325 fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
326 let params = f.db.generic_params(def);
328 // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
329 let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
330 WherePredicateTypeTarget::TypeRef(_) => false,
331 WherePredicateTypeTarget::TypeParam(id) => params.types[*id].name.is_none(),
334 let has_displayable_predicate = params
338 !matches!(pred, WherePredicate::TypeBound { target, .. } if is_unnamed_type_target(target))
341 if !has_displayable_predicate {
345 let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
346 WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
347 WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name {
348 Some(name) => write!(f, "{}", name),
349 None => write!(f, "{{unnamed}}"),
353 write!(f, "\nwhere")?;
355 for (pred_idx, pred) in params.where_predicates.iter().enumerate() {
357 if pred_idx == 0 { None } else { Some(¶ms.where_predicates[pred_idx - 1]) };
359 let new_predicate = |f: &mut HirFormatter| {
360 write!(f, "{}", if pred_idx == 0 { "\n " } else { ",\n " })
364 WherePredicate::TypeBound { target, .. } if is_unnamed_type_target(target) => {}
365 WherePredicate::TypeBound { target, bound } => {
366 if matches!(prev_pred, Some(WherePredicate::TypeBound { target: target_, .. }) if target_ == target)
371 write_target(target, f)?;
376 WherePredicate::Lifetime { target, bound } => {
377 if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target)
379 write!(f, " + {}", bound.name)?;
382 write!(f, "{}: {}", target.name, bound.name)?;
385 WherePredicate::ForLifetime { lifetimes, target, bound } => {
388 Some(WherePredicate::ForLifetime { lifetimes: lifetimes_, target: target_, .. })
389 if lifetimes_ == lifetimes && target_ == target,
395 for (idx, lifetime) in lifetimes.iter().enumerate() {
399 write!(f, "{}", lifetime)?;
402 write_target(target, f)?;
410 // End of final predicate. There must be at least one predicate here.
416 impl HirDisplay for Const {
417 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
418 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
419 let data = f.db.const_data(self.id);
420 write!(f, "const ")?;
422 Some(name) => write!(f, "{}: ", name)?,
423 None => write!(f, "_: ")?,
425 data.type_ref.hir_fmt(f)?;
430 impl HirDisplay for Static {
431 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
432 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
433 let data = f.db.static_data(self.id);
434 write!(f, "static ")?;
438 write!(f, "{}: ", &data.name)?;
439 data.type_ref.hir_fmt(f)?;
444 impl HirDisplay for Trait {
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.trait_data(self.id);
449 write!(f, "unsafe ")?;
454 write!(f, "trait {}", data.name)?;
455 let def_id = GenericDefId::TraitId(self.id);
456 write_generic_params(def_id, f)?;
457 write_where_clause(def_id, f)?;
462 impl HirDisplay for TypeAlias {
463 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
464 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
465 let data = f.db.type_alias_data(self.id);
466 write!(f, "type {}", data.name)?;
467 if !data.bounds.is_empty() {
469 f.write_joined(&data.bounds, " + ")?;
471 if let Some(ty) = &data.type_ref {
479 impl HirDisplay for Module {
480 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
481 // FIXME: Module doesn't have visibility saved in data.
482 match self.name(f.db) {
483 Some(name) => write!(f, "mod {}", name),
484 None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) {
485 Some(name) => write!(f, "extern crate {}", name),
486 None => write!(f, "extern crate {{unknown}}"),
488 None => write!(f, "mod {{unnamed}}"),