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