1use either::Either;
4use hir_def::{
5 AdtId, GenericDefId,
6 expr_store::ExpressionStore,
7 hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
8 item_tree::FieldsShape,
9 signatures::{StaticFlags, TraitFlags},
10 type_ref::{TypeBound, TypeRef, TypeRefId},
11};
12use hir_ty::{
13 GenericPredicates,
14 db::HirDatabase,
15 display::{
16 HirDisplay, HirDisplayWithExpressionStore, HirFormatter, Result, SizedByDefault,
17 hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
18 },
19 next_solver::ClauseKind,
20};
21use itertools::Itertools;
22use rustc_type_ir::inherent::IntoKind;
23
24use crate::{
25 Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
26 ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam,
27 Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, Type,
28 TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant,
29};
30
31impl<'db> HirDisplay<'db> for Function {
32 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
33 let db = f.db;
34 let data = db.function_signature(self.id);
35 let container = self.as_assoc_item(db).map(|it| it.container(db));
36 let mut module = self.module(db);
37
38 let container_params = match container {
40 Some(AssocItemContainer::Trait(trait_)) => {
41 let (params, params_store) = f.db.generic_params_and_store(trait_.id.into());
42 if f.show_container_bounds() && !params.is_empty() {
43 write_trait_header(&trait_, f)?;
44 f.write_char('\n')?;
45 has_disaplayable_predicates(f.db, ¶ms, ¶ms_store)
46 .then_some((params, params_store))
47 } else {
48 None
49 }
50 }
51 Some(AssocItemContainer::Impl(impl_)) => {
52 let (params, params_store) = f.db.generic_params_and_store(impl_.id.into());
53 if f.show_container_bounds() && !params.is_empty() {
54 write_impl_header(&impl_, f)?;
55 f.write_char('\n')?;
56 has_disaplayable_predicates(f.db, ¶ms, ¶ms_store)
57 .then_some((params, params_store))
58 } else {
59 None
60 }
61 }
62 None => None,
63 };
64
65 if let Some(AssocItemContainer::Impl(_)) = container {
69 module = module.nearest_non_block_module(db);
70 }
71 let module_id = module.id;
72
73 write_visibility(module_id, self.visibility(db), f)?;
74
75 if data.is_default() {
76 f.write_str("default ")?;
77 }
78 if data.is_const() {
79 f.write_str("const ")?;
80 }
81 if data.is_async() {
82 f.write_str("async ")?;
83 }
84 if self.is_unsafe_to_call(db, None, f.edition()) {
87 f.write_str("unsafe ")?;
88 }
89 if let Some(abi) = &data.abi {
90 write!(f, "extern \"{}\" ", abi.as_str())?;
91 }
92 write!(f, "fn {}", data.name.display(f.db, f.edition()))?;
93
94 write_generic_params(GenericDefId::FunctionId(self.id), f)?;
95
96 f.write_char('(')?;
97
98 let mut first = true;
99 let mut skip_self = 0;
100 if let Some(self_param) = self.self_param(db) {
101 self_param.hir_fmt(f)?;
102 first = false;
103 skip_self = 1;
104 }
105
106 let body = db.body(self.id.into());
108 for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
109 if !first {
110 f.write_str(", ")?;
111 } else {
112 first = false;
113 }
114
115 let pat_id = body.params[param.idx - body.self_param.is_some() as usize];
116 let pat_str = body.pretty_print_pat(db, self.id.into(), pat_id, true, f.edition());
117 f.write_str(&pat_str)?;
118
119 f.write_str(": ")?;
120 type_ref.hir_fmt(f, &data.store)?;
121 }
122
123 if data.is_varargs() {
124 if !first {
125 f.write_str(", ")?;
126 }
127 f.write_str("...")?;
128 }
129
130 f.write_char(')')?;
131
132 let ret_type = if !data.is_async() {
136 data.ret_type
137 } else if let Some(ret_type) = data.ret_type {
138 match &data.store[ret_type] {
139 TypeRef::ImplTrait(bounds) => match &bounds[0] {
140 &TypeBound::Path(path, _) => Some(
141 *data.store[path]
142 .segments()
143 .iter()
144 .last()
145 .unwrap()
146 .args_and_bindings
147 .unwrap()
148 .bindings[0]
149 .type_ref
150 .as_ref()
151 .unwrap(),
152 ),
153 _ => None,
154 },
155 _ => None,
156 }
157 } else {
158 None
159 };
160
161 if let Some(ret_type) = ret_type {
162 match &data.store[ret_type] {
163 TypeRef::Tuple(tup) if tup.is_empty() => {}
164 _ => {
165 f.write_str(" -> ")?;
166 ret_type.hir_fmt(f, &data.store)?;
167 }
168 }
169 }
170
171 let has_written_where = write_where_clause(GenericDefId::FunctionId(self.id), f)?;
173 if let Some((container_params, container_params_store)) = container_params {
174 if !has_written_where {
175 f.write_str("\nwhere")?;
176 }
177 let container_name = match container.unwrap() {
178 AssocItemContainer::Trait(_) => "trait",
179 AssocItemContainer::Impl(_) => "impl",
180 };
181 write!(f, "\n // Bounds from {container_name}:",)?;
182 write_where_predicates(&container_params, &container_params_store, f)?;
183 }
184 Ok(())
185 }
186}
187
188fn write_impl_header<'db>(impl_: &Impl, f: &mut HirFormatter<'_, 'db>) -> Result {
189 let db = f.db;
190
191 f.write_str("impl")?;
192 let def_id = GenericDefId::ImplId(impl_.id);
193 write_generic_params(def_id, f)?;
194
195 let impl_data = db.impl_signature(impl_.id);
196 if let Some(target_trait) = &impl_data.target_trait {
197 f.write_char(' ')?;
198 hir_display_with_store(&impl_data.store[target_trait.path], &impl_data.store).hir_fmt(f)?;
199 f.write_str(" for")?;
200 }
201
202 f.write_char(' ')?;
203 impl_.self_ty(db).hir_fmt(f)?;
204
205 Ok(())
206}
207
208impl<'db> HirDisplay<'db> for SelfParam {
209 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
210 let data = f.db.function_signature(self.func);
211 let param = *data.params.first().unwrap();
212 match &data.store[param] {
213 TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
214 TypeRef::Reference(ref_) if matches!(&data.store[ref_.ty], TypeRef::Path(p) if p.is_self_type()) =>
215 {
216 f.write_char('&')?;
217 if let Some(lifetime) = &ref_.lifetime {
218 lifetime.hir_fmt(f, &data.store)?;
219 f.write_char(' ')?;
220 }
221 if let hir_def::type_ref::Mutability::Mut = ref_.mutability {
222 f.write_str("mut ")?;
223 }
224 f.write_str("self")
225 }
226 _ => {
227 f.write_str("self: ")?;
228 param.hir_fmt(f, &data.store)
229 }
230 }
231 }
232}
233
234impl<'db> HirDisplay<'db> for Adt {
235 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
236 match self {
237 Adt::Struct(it) => it.hir_fmt(f),
238 Adt::Union(it) => it.hir_fmt(f),
239 Adt::Enum(it) => it.hir_fmt(f),
240 }
241 }
242}
243
244impl<'db> HirDisplay<'db> for Struct {
245 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
246 let module_id = self.module(f.db).id;
247 write_visibility(module_id, self.visibility(f.db), f)?;
249 f.write_str("struct ")?;
250 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
251 let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
252 write_generic_params(def_id, f)?;
253
254 let variant_data = self.variant_fields(f.db);
255 match self.kind(f.db) {
256 StructKind::Tuple => {
257 f.write_char('(')?;
258 let mut it = variant_data.fields().iter().peekable();
259
260 while let Some((id, _)) = it.next() {
261 let field = Field { parent: (*self).into(), id };
262 write_visibility(module_id, field.visibility(f.db), f)?;
263 field.ty(f.db).hir_fmt(f)?;
264 if it.peek().is_some() {
265 f.write_str(", ")?;
266 }
267 }
268
269 f.write_char(')')?;
270 write_where_clause(def_id, f)?;
271 }
272 StructKind::Record => {
273 let has_where_clause = write_where_clause(def_id, f)?;
274 if let Some(limit) = f.entity_limit {
275 write_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
276 }
277 }
278 StructKind::Unit => _ = write_where_clause(def_id, f)?,
279 }
280
281 Ok(())
282 }
283}
284
285impl<'db> HirDisplay<'db> for Enum {
286 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
287 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
288 f.write_str("enum ")?;
289 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
290 let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
291 write_generic_params(def_id, f)?;
292
293 let has_where_clause = write_where_clause(def_id, f)?;
294 if let Some(limit) = f.entity_limit {
295 write_variants(&self.variants(f.db), has_where_clause, limit, f)?;
296 }
297
298 Ok(())
299 }
300}
301
302impl<'db> HirDisplay<'db> for Union {
303 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
304 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
305 f.write_str("union ")?;
306 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
307 let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
308 write_generic_params(def_id, f)?;
309
310 let has_where_clause = write_where_clause(def_id, f)?;
311 if let Some(limit) = f.entity_limit {
312 write_fields(&self.fields(f.db), has_where_clause, limit, false, f)?;
313 }
314 Ok(())
315 }
316}
317
318fn write_fields<'db>(
319 fields: &[Field],
320 has_where_clause: bool,
321 limit: usize,
322 in_line: bool,
323 f: &mut HirFormatter<'_, 'db>,
324) -> Result {
325 let count = fields.len().min(limit);
326 let (indent, separator) = if in_line { ("", ' ') } else { (" ", '\n') };
327 f.write_char(if !has_where_clause { ' ' } else { separator })?;
328 if count == 0 {
329 f.write_str(if fields.is_empty() { "{}" } else { "{ /* … */ }" })?;
330 } else {
331 f.write_char('{')?;
332
333 if !fields.is_empty() {
334 f.write_char(separator)?;
335 for field in &fields[..count] {
336 f.write_str(indent)?;
337 field.hir_fmt(f)?;
338 write!(f, ",{separator}")?;
339 }
340
341 if fields.len() > count {
342 write!(f, "{indent}/* … */{separator}")?;
343 }
344 }
345
346 f.write_str("}")?;
347 }
348
349 Ok(())
350}
351
352fn write_variants<'db>(
353 variants: &[Variant],
354 has_where_clause: bool,
355 limit: usize,
356 f: &mut HirFormatter<'_, 'db>,
357) -> Result {
358 let count = variants.len().min(limit);
359 f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
360 if count == 0 {
361 let variants = if variants.is_empty() { "{}" } else { "{ /* … */ }" };
362 f.write_str(variants)?;
363 } else {
364 f.write_str("{\n")?;
365 for variant in &variants[..count] {
366 write!(f, " {}", variant.name(f.db).display(f.db, f.edition()))?;
367 match variant.kind(f.db) {
368 StructKind::Tuple => {
369 let fields_str =
370 if variant.fields(f.db).is_empty() { "()" } else { "( /* … */ )" };
371 f.write_str(fields_str)?;
372 }
373 StructKind::Record => {
374 let fields_str =
375 if variant.fields(f.db).is_empty() { " {}" } else { " { /* … */ }" };
376 f.write_str(fields_str)?;
377 }
378 StructKind::Unit => {}
379 }
380 f.write_str(",\n")?;
381 }
382
383 if variants.len() > count {
384 f.write_str(" /* … */\n")?;
385 }
386 f.write_str("}")?;
387 }
388
389 Ok(())
390}
391
392impl<'db> HirDisplay<'db> for Field {
393 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
394 write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
395 write!(f, "{}: ", self.name(f.db).display(f.db, f.edition()))?;
396 self.ty(f.db).hir_fmt(f)
397 }
398}
399
400impl<'db> HirDisplay<'db> for TupleField {
401 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
402 write!(f, "pub {}: ", self.name().display(f.db, f.edition()))?;
403 self.ty(f.db).hir_fmt(f)
404 }
405}
406
407impl<'db> HirDisplay<'db> for Variant {
408 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
409 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
410 let data = self.id.fields(f.db);
411 match data.shape {
412 FieldsShape::Unit => {}
413 FieldsShape::Tuple => {
414 f.write_char('(')?;
415 let mut first = true;
416 for (_, field) in data.fields().iter() {
417 if first {
418 first = false;
419 } else {
420 f.write_str(", ")?;
421 }
422 field.type_ref.hir_fmt(f, &data.store)?;
424 }
425 f.write_char(')')?;
426 }
427 FieldsShape::Record => {
428 if let Some(limit) = f.entity_limit {
429 write_fields(&self.fields(f.db), false, limit, true, f)?;
430 }
431 }
432 }
433 Ok(())
434 }
435}
436
437impl<'db> HirDisplay<'db> for Type<'db> {
438 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
439 self.ty.hir_fmt(f)
440 }
441}
442
443impl<'db> HirDisplay<'db> for TypeNs<'db> {
444 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
445 self.ty.hir_fmt(f)
446 }
447}
448
449impl<'db> HirDisplay<'db> for ExternCrateDecl {
450 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
451 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
452 f.write_str("extern crate ")?;
453 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
454 if let Some(alias) = self.alias(f.db) {
455 write!(f, " as {}", alias.display(f.edition()))?;
456 }
457 Ok(())
458 }
459}
460
461impl<'db> HirDisplay<'db> for GenericParam {
462 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
463 match self {
464 GenericParam::TypeParam(it) => it.hir_fmt(f),
465 GenericParam::ConstParam(it) => it.hir_fmt(f),
466 GenericParam::LifetimeParam(it) => it.hir_fmt(f),
467 }
468 }
469}
470
471impl<'db> HirDisplay<'db> for TypeOrConstParam {
472 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
473 match self.split(f.db) {
474 either::Either::Left(it) => it.hir_fmt(f),
475 either::Either::Right(it) => it.hir_fmt(f),
476 }
477 }
478}
479
480impl<'db> HirDisplay<'db> for TypeParam {
481 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
482 let params = f.db.generic_params(self.id.parent());
483 let param_data = ¶ms[self.id.local_id()];
484 let krate = self.id.parent().krate(f.db).id;
485 let ty = self.ty(f.db).ty;
486 let predicates = GenericPredicates::query_all(f.db, self.id.parent());
487 let predicates = predicates
488 .iter_identity_copied()
489 .filter(|wc| match wc.kind().skip_binder() {
490 ClauseKind::Trait(tr) => tr.self_ty() == ty,
491 ClauseKind::Projection(proj) => proj.self_ty() == ty,
492 ClauseKind::TypeOutlives(to) => to.0 == ty,
493 _ => false,
494 })
495 .collect::<Vec<_>>();
496
497 match param_data {
498 TypeOrConstParamData::TypeParamData(p) => match p.provenance {
499 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
500 write!(f, "{}", p.name.clone().unwrap().display(f.db, f.edition()))?
501 }
502 TypeParamProvenance::ArgumentImplTrait => {
503 return write_bounds_like_dyn_trait_with_prefix(
504 f,
505 "impl",
506 Either::Left(ty),
507 &predicates,
508 SizedByDefault::Sized { anchor: krate },
509 );
510 }
511 },
512 TypeOrConstParamData::ConstParamData(p) => {
513 write!(f, "{}", p.name.display(f.db, f.edition()))?;
514 }
515 }
516
517 if f.omit_verbose_types() {
518 return Ok(());
519 }
520
521 let sized_trait = f.lang_items().Sized;
522 let has_only_sized_bound =
523 predicates.iter().all(move |pred| match pred.kind().skip_binder() {
524 ClauseKind::Trait(it) => Some(it.def_id().0) == sized_trait,
525 _ => false,
526 });
527 let has_only_not_sized_bound = predicates.is_empty();
528 if !has_only_sized_bound || has_only_not_sized_bound {
529 let default_sized = SizedByDefault::Sized { anchor: krate };
530 write_bounds_like_dyn_trait_with_prefix(
531 f,
532 ":",
533 Either::Left(ty),
534 &predicates,
535 default_sized,
536 )?;
537 }
538 Ok(())
539 }
540}
541
542impl<'db> HirDisplay<'db> for LifetimeParam {
543 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
544 write!(f, "{}", self.name(f.db).display(f.db, f.edition()))
545 }
546}
547
548impl<'db> HirDisplay<'db> for ConstParam {
549 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
550 write!(f, "const {}: ", self.name(f.db).display(f.db, f.edition()))?;
551 self.ty(f.db).hir_fmt(f)
552 }
553}
554
555fn write_generic_params<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result {
556 let (params, store) = f.db.generic_params_and_store(def);
557 if params.iter_lt().next().is_none()
558 && params.iter_type_or_consts().all(|it| it.1.const_param().is_none())
559 && params
560 .iter_type_or_consts()
561 .filter_map(|it| it.1.type_param())
562 .all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
563 {
564 return Ok(());
565 }
566 f.write_char('<')?;
567
568 let mut first = true;
569 let mut delim = |f: &mut HirFormatter<'_, 'db>| {
570 if first {
571 first = false;
572 Ok(())
573 } else {
574 f.write_str(", ")
575 }
576 };
577 for (_, lifetime) in params.iter_lt() {
578 delim(f)?;
579 write!(f, "{}", lifetime.name.display(f.db, f.edition()))?;
580 }
581 for (_, ty) in params.iter_type_or_consts() {
582 if let Some(name) = &ty.name() {
583 match ty {
584 TypeOrConstParamData::TypeParamData(ty) => {
585 if ty.provenance != TypeParamProvenance::TypeParamList {
586 continue;
587 }
588 delim(f)?;
589 write!(f, "{}", name.display(f.db, f.edition()))?;
590 if let Some(default) = &ty.default {
591 f.write_str(" = ")?;
592 default.hir_fmt(f, &store)?;
593 }
594 }
595 TypeOrConstParamData::ConstParamData(c) => {
596 delim(f)?;
597 write!(f, "const {}: ", name.display(f.db, f.edition()))?;
598 c.ty.hir_fmt(f, &store)?;
599
600 if let Some(default) = &c.default {
601 f.write_str(" = ")?;
602 default.hir_fmt(f, &store)?;
603 }
604 }
605 }
606 }
607 }
608
609 f.write_char('>')?;
610 Ok(())
611}
612
613fn write_where_clause<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result<bool> {
614 let (params, store) = f.db.generic_params_and_store(def);
615 if !has_disaplayable_predicates(f.db, ¶ms, &store) {
616 return Ok(false);
617 }
618
619 f.write_str("\nwhere")?;
620 write_where_predicates(¶ms, &store, f)?;
621
622 Ok(true)
623}
624
625fn has_disaplayable_predicates(
626 db: &dyn HirDatabase,
627 params: &GenericParams,
628 store: &ExpressionStore,
629) -> bool {
630 params.where_predicates().iter().any(|pred| {
631 !matches!(
632 pred,
633 WherePredicate::TypeBound { target, .. }
634 if matches!(store[*target],
635 TypeRef::TypeParam(id) if db.generic_params(id.parent())[id.local_id()].name().is_none()
636 )
637 )
638 })
639}
640
641fn write_where_predicates<'db>(
642 params: &GenericParams,
643 store: &ExpressionStore,
644 f: &mut HirFormatter<'_, 'db>,
645) -> Result {
646 use WherePredicate::*;
647
648 let is_unnamed_type_target = |target: TypeRefId| {
650 matches!(store[target],
651 TypeRef::TypeParam(id) if f.db.generic_params(id.parent())[id.local_id()].name().is_none()
652 )
653 };
654
655 let check_same_target = |pred1: &WherePredicate, pred2: &WherePredicate| match (pred1, pred2) {
656 (TypeBound { target: t1, .. }, TypeBound { target: t2, .. }) => t1 == t2,
657 (Lifetime { target: t1, .. }, Lifetime { target: t2, .. }) => t1 == t2,
658 (
659 ForLifetime { lifetimes: l1, target: t1, .. },
660 ForLifetime { lifetimes: l2, target: t2, .. },
661 ) => l1 == l2 && t1 == t2,
662 _ => false,
663 };
664
665 let mut iter = params.where_predicates().iter().peekable();
666 while let Some(pred) = iter.next() {
667 if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
668 continue;
669 }
670
671 f.write_str("\n ")?;
672 match pred {
673 TypeBound { target, bound } => {
674 target.hir_fmt(f, store)?;
675 f.write_str(": ")?;
676 bound.hir_fmt(f, store)?;
677 }
678 Lifetime { target, bound } => {
679 target.hir_fmt(f, store)?;
680 write!(f, ": ")?;
681 bound.hir_fmt(f, store)?;
682 }
683 ForLifetime { lifetimes, target, bound } => {
684 let lifetimes = lifetimes.iter().map(|it| it.display(f.db, f.edition())).join(", ");
685 write!(f, "for<{lifetimes}> ")?;
686 target.hir_fmt(f, store)?;
687 f.write_str(": ")?;
688 bound.hir_fmt(f, store)?;
689 }
690 }
691
692 while let Some(nxt) = iter.next_if(|nxt| check_same_target(pred, nxt)) {
693 f.write_str(" + ")?;
694 match nxt {
695 TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f, store)?,
696 Lifetime { bound, .. } => bound.hir_fmt(f, store)?,
697 }
698 }
699 f.write_str(",")?;
700 }
701
702 Ok(())
703}
704
705impl<'db> HirDisplay<'db> for Const {
706 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
707 let db = f.db;
708 let container = self.as_assoc_item(db).map(|it| it.container(db));
709 let mut module = self.module(db);
710 if let Some(AssocItemContainer::Impl(_)) = container {
711 module = module.nearest_non_block_module(db);
713 }
714 write_visibility(module.id, self.visibility(db), f)?;
715 let data = db.const_signature(self.id);
716 f.write_str("const ")?;
717 match &data.name {
718 Some(name) => write!(f, "{}: ", name.display(f.db, f.edition()))?,
719 None => f.write_str("_: ")?,
720 }
721 data.type_ref.hir_fmt(f, &data.store)?;
722 Ok(())
723 }
724}
725
726impl<'db> HirDisplay<'db> for Static {
727 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
728 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
729 let data = f.db.static_signature(self.id);
730 f.write_str("static ")?;
731 if data.flags.contains(StaticFlags::MUTABLE) {
732 f.write_str("mut ")?;
733 }
734 write!(f, "{}: ", data.name.display(f.db, f.edition()))?;
735 data.type_ref.hir_fmt(f, &data.store)?;
736 Ok(())
737 }
738}
739
740impl<'db> HirDisplay<'db> for TraitRef<'db> {
741 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
742 self.trait_ref.hir_fmt(f)
743 }
744}
745
746impl<'db> HirDisplay<'db> for Trait {
747 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
748 write_trait_header(self, f)?;
750 let def_id = GenericDefId::TraitId(self.id);
751 let has_where_clause = write_where_clause(def_id, f)?;
752
753 if let Some(limit) = f.entity_limit {
754 let assoc_items = self.items(f.db);
755 let count = assoc_items.len().min(limit);
756 f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
757 if count == 0 {
758 if assoc_items.is_empty() {
759 f.write_str("{}")?;
760 } else {
761 f.write_str("{ /* … */ }")?;
762 }
763 } else {
764 f.write_str("{\n")?;
765 for item in &assoc_items[..count] {
766 f.write_str(" ")?;
767 match item {
768 AssocItem::Function(func) => func.hir_fmt(f),
769 AssocItem::Const(cst) => cst.hir_fmt(f),
770 AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f),
771 }?;
772 f.write_str(";\n")?;
773 }
774
775 if assoc_items.len() > count {
776 f.write_str(" /* … */\n")?;
777 }
778 f.write_str("}")?;
779 }
780 }
781
782 Ok(())
783 }
784}
785
786fn write_trait_header<'db>(trait_: &Trait, f: &mut HirFormatter<'_, 'db>) -> Result {
787 write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
788 let data = f.db.trait_signature(trait_.id);
789 if data.flags.contains(TraitFlags::UNSAFE) {
790 f.write_str("unsafe ")?;
791 }
792 if data.flags.contains(TraitFlags::AUTO) {
793 f.write_str("auto ")?;
794 }
795 write!(f, "trait {}", data.name.display(f.db, f.edition()))?;
796 write_generic_params(GenericDefId::TraitId(trait_.id), f)?;
797 Ok(())
798}
799
800impl<'db> HirDisplay<'db> for TypeAlias {
801 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
802 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
803 let data = f.db.type_alias_signature(self.id);
804 write!(f, "type {}", data.name.display(f.db, f.edition()))?;
805 let def_id = GenericDefId::TypeAliasId(self.id);
806 write_generic_params(def_id, f)?;
807 if !data.bounds.is_empty() {
808 f.write_str(": ")?;
809 f.write_joined(
810 data.bounds.iter().map(|bound| hir_display_with_store(bound, &data.store)),
811 " + ",
812 )?;
813 }
814 if let Some(ty) = data.ty {
815 f.write_str(" = ")?;
816 ty.hir_fmt(f, &data.store)?;
817 }
818 write_where_clause(def_id, f)?;
819 Ok(())
820 }
821}
822
823impl<'db> HirDisplay<'db> for Module {
824 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
825 match self.parent(f.db) {
826 Some(m) => write_visibility(m.id, self.visibility(f.db), f)?,
827 None => {
828 return match self.krate(f.db).display_name(f.db) {
829 Some(name) => write!(f, "extern crate {name}"),
830 None => f.write_str("extern crate {unknown}"),
831 };
832 }
833 }
834 match self.name(f.db) {
835 Some(name) => write!(f, "mod {}", name.display(f.db, f.edition())),
836 None => f.write_str("mod {unknown}"),
837 }
838 }
839}
840
841impl<'db> HirDisplay<'db> for Crate {
842 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
843 match self.display_name(f.db) {
844 Some(name) => write!(f, "extern crate {name}"),
845 None => f.write_str("extern crate {unknown}"),
846 }
847 }
848}
849
850impl<'db> HirDisplay<'db> for Macro {
851 fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
852 match self.id {
853 hir_def::MacroId::Macro2Id(_) => f.write_str("macro"),
854 hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
855 hir_def::MacroId::ProcMacroId(_) => f.write_str("proc_macro"),
856 }?;
857 write!(f, " {}", self.name(f.db).display(f.db, f.edition()))
858 }
859}