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