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