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