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