1use std::{
6 fmt::{self, Debug},
7 mem,
8};
9
10use base_db::Crate;
11use chalk_ir::{BoundVar, Safety, TyKind};
12use either::Either;
13use hir_def::{
14 GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId,
15 ModuleId, TraitId,
16 db::DefDatabase,
17 expr_store::{ExpressionStore, path::Path},
18 find_path::{self, PrefixKind},
19 hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
20 item_scope::ItemInNs,
21 item_tree::FieldsShape,
22 lang_item::LangItem,
23 nameres::DefMap,
24 signatures::VariantFields,
25 type_ref::{
26 ConstRef, LifetimeRef, LifetimeRefId, TraitBoundModifier, TypeBound, TypeRef, TypeRefId,
27 UseArgRef,
28 },
29 visibility::Visibility,
30};
31use hir_expand::{mod_path::PathKind, name::Name};
32use intern::{Internable, Interned, sym};
33use itertools::Itertools;
34use la_arena::ArenaMap;
35use rustc_apfloat::{
36 Float,
37 ieee::{Half as f16, Quad as f128},
38};
39use rustc_hash::FxHashSet;
40use smallvec::SmallVec;
41use span::Edition;
42use stdx::never;
43use triomphe::Arc;
44
45use crate::{
46 AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
47 ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
48 LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
49 QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty,
50 TyExt, WhereClause,
51 consteval::try_const_usize,
52 db::{HirDatabase, InternedClosure},
53 from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
54 generics::generics,
55 infer::normalize,
56 layout::Layout,
57 lt_from_placeholder_idx,
58 mapping::from_chalk,
59 mir::pad16,
60 primitive, to_assoc_type_id,
61 utils::{self, ClosureSubst, detect_variant_from_bytes},
62};
63
64pub trait HirWrite: fmt::Write {
65 fn start_location_link(&mut self, _location: ModuleDefId) {}
66 fn end_location_link(&mut self) {}
67}
68
69impl HirWrite for String {}
71
72impl HirWrite for fmt::Formatter<'_> {}
74
75pub struct HirFormatter<'a> {
76 pub db: &'a dyn HirDatabase,
78 fmt: &'a mut dyn HirWrite,
80 buf: String,
82 curr_size: usize,
84 max_size: Option<usize>,
86 pub entity_limit: Option<usize>,
89 show_container_bounds: bool,
91 omit_verbose_types: bool,
92 closure_style: ClosureStyle,
93 display_lifetimes: DisplayLifetime,
94 display_kind: DisplayKind,
95 display_target: DisplayTarget,
96 bounds_formatting_ctx: BoundsFormattingCtx,
97}
98
99#[derive(Copy, Clone)]
105pub enum DisplayLifetime {
106 Always,
107 OnlyStatic,
108 OnlyNamed,
109 OnlyNamedOrStatic,
110 Never,
111}
112
113#[derive(Default)]
114enum BoundsFormattingCtx {
115 Entered {
116 projection_tys_met: FxHashSet<ProjectionTy>,
125 },
126 #[default]
127 Exited,
128}
129
130impl BoundsFormattingCtx {
131 fn contains(&mut self, proj: &ProjectionTy) -> bool {
132 match self {
133 BoundsFormattingCtx::Entered { projection_tys_met } => {
134 projection_tys_met.contains(proj)
135 }
136 BoundsFormattingCtx::Exited => false,
137 }
138 }
139}
140
141impl HirFormatter<'_> {
142 fn start_location_link(&mut self, location: ModuleDefId) {
143 self.fmt.start_location_link(location);
144 }
145
146 fn end_location_link(&mut self) {
147 self.fmt.end_location_link();
148 }
149
150 fn format_bounds_with<T, F: FnOnce(&mut Self) -> T>(
151 &mut self,
152 target: ProjectionTy,
153 format_bounds: F,
154 ) -> T {
155 match self.bounds_formatting_ctx {
156 BoundsFormattingCtx::Entered { ref mut projection_tys_met } => {
157 projection_tys_met.insert(target);
158 format_bounds(self)
159 }
160 BoundsFormattingCtx::Exited => {
161 let mut projection_tys_met = FxHashSet::default();
162 projection_tys_met.insert(target);
163 self.bounds_formatting_ctx = BoundsFormattingCtx::Entered { projection_tys_met };
164 let res = format_bounds(self);
165 self.bounds_formatting_ctx = BoundsFormattingCtx::Exited;
169 res
170 }
171 }
172 }
173
174 fn render_lifetime(&self, lifetime: &Lifetime) -> bool {
175 match self.display_lifetimes {
176 DisplayLifetime::Always => true,
177 DisplayLifetime::OnlyStatic => matches!(***lifetime.interned(), LifetimeData::Static),
178 DisplayLifetime::OnlyNamed => {
179 matches!(***lifetime.interned(), LifetimeData::Placeholder(_))
180 }
181 DisplayLifetime::OnlyNamedOrStatic => matches!(
182 ***lifetime.interned(),
183 LifetimeData::Static | LifetimeData::Placeholder(_)
184 ),
185 DisplayLifetime::Never => false,
186 }
187 }
188}
189
190pub trait HirDisplay {
191 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
192
193 fn into_displayable<'a>(
195 &'a self,
196 db: &'a dyn HirDatabase,
197 max_size: Option<usize>,
198 limited_size: Option<usize>,
199 omit_verbose_types: bool,
200 display_target: DisplayTarget,
201 display_kind: DisplayKind,
202 closure_style: ClosureStyle,
203 show_container_bounds: bool,
204 ) -> HirDisplayWrapper<'a, Self>
205 where
206 Self: Sized,
207 {
208 assert!(
209 !matches!(display_kind, DisplayKind::SourceCode { .. }),
210 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
211 );
212 HirDisplayWrapper {
213 db,
214 t: self,
215 max_size,
216 limited_size,
217 omit_verbose_types,
218 display_target,
219 display_kind,
220 closure_style,
221 show_container_bounds,
222 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
223 }
224 }
225
226 fn display<'a>(
229 &'a self,
230 db: &'a dyn HirDatabase,
231 display_target: DisplayTarget,
232 ) -> HirDisplayWrapper<'a, Self>
233 where
234 Self: Sized,
235 {
236 HirDisplayWrapper {
237 db,
238 t: self,
239 max_size: None,
240 limited_size: None,
241 omit_verbose_types: false,
242 closure_style: ClosureStyle::ImplFn,
243 display_target,
244 display_kind: DisplayKind::Diagnostics,
245 show_container_bounds: false,
246 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
247 }
248 }
249
250 fn display_truncated<'a>(
253 &'a self,
254 db: &'a dyn HirDatabase,
255 max_size: Option<usize>,
256 display_target: DisplayTarget,
257 ) -> HirDisplayWrapper<'a, Self>
258 where
259 Self: Sized,
260 {
261 HirDisplayWrapper {
262 db,
263 t: self,
264 max_size,
265 limited_size: None,
266 omit_verbose_types: true,
267 closure_style: ClosureStyle::ImplFn,
268 display_target,
269 display_kind: DisplayKind::Diagnostics,
270 show_container_bounds: false,
271 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
272 }
273 }
274
275 fn display_limited<'a>(
278 &'a self,
279 db: &'a dyn HirDatabase,
280 limited_size: Option<usize>,
281 display_target: DisplayTarget,
282 ) -> HirDisplayWrapper<'a, Self>
283 where
284 Self: Sized,
285 {
286 HirDisplayWrapper {
287 db,
288 t: self,
289 max_size: None,
290 limited_size,
291 omit_verbose_types: true,
292 closure_style: ClosureStyle::ImplFn,
293 display_target,
294 display_kind: DisplayKind::Diagnostics,
295 show_container_bounds: false,
296 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
297 }
298 }
299
300 fn display_source_code<'a>(
303 &'a self,
304 db: &'a dyn HirDatabase,
305 module_id: ModuleId,
306 allow_opaque: bool,
307 ) -> Result<String, DisplaySourceCodeError> {
308 let mut result = String::new();
309 match self.hir_fmt(&mut HirFormatter {
310 db,
311 fmt: &mut result,
312 buf: String::with_capacity(20),
313 curr_size: 0,
314 max_size: None,
315 entity_limit: None,
316 omit_verbose_types: false,
317 closure_style: ClosureStyle::ImplFn,
318 display_target: DisplayTarget::from_crate(db, module_id.krate()),
319 display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },
320 show_container_bounds: false,
321 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
322 bounds_formatting_ctx: Default::default(),
323 }) {
324 Ok(()) => {}
325 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
326 Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
327 };
328 Ok(result)
329 }
330
331 fn display_test<'a>(
333 &'a self,
334 db: &'a dyn HirDatabase,
335 display_target: DisplayTarget,
336 ) -> HirDisplayWrapper<'a, Self>
337 where
338 Self: Sized,
339 {
340 HirDisplayWrapper {
341 db,
342 t: self,
343 max_size: None,
344 limited_size: None,
345 omit_verbose_types: false,
346 closure_style: ClosureStyle::ImplFn,
347 display_target,
348 display_kind: DisplayKind::Test,
349 show_container_bounds: false,
350 display_lifetimes: DisplayLifetime::Always,
351 }
352 }
353
354 fn display_with_container_bounds<'a>(
357 &'a self,
358 db: &'a dyn HirDatabase,
359 show_container_bounds: bool,
360 display_target: DisplayTarget,
361 ) -> HirDisplayWrapper<'a, Self>
362 where
363 Self: Sized,
364 {
365 HirDisplayWrapper {
366 db,
367 t: self,
368 max_size: None,
369 limited_size: None,
370 omit_verbose_types: false,
371 closure_style: ClosureStyle::ImplFn,
372 display_target,
373 display_kind: DisplayKind::Diagnostics,
374 show_container_bounds,
375 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
376 }
377 }
378}
379
380impl HirFormatter<'_> {
381 pub fn krate(&self) -> Crate {
382 self.display_target.krate
383 }
384
385 pub fn edition(&self) -> Edition {
386 self.display_target.edition
387 }
388
389 pub fn write_joined<T: HirDisplay>(
390 &mut self,
391 iter: impl IntoIterator<Item = T>,
392 sep: &str,
393 ) -> Result<(), HirDisplayError> {
394 let mut first = true;
395 for e in iter {
396 if !first {
397 write!(self, "{sep}")?;
398 }
399 first = false;
400
401 if self.should_truncate() {
403 return write!(self, "{TYPE_HINT_TRUNCATION}");
404 }
405
406 e.hir_fmt(self)?;
407 }
408 Ok(())
409 }
410
411 pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> {
413 self.buf.clear();
415 fmt::write(&mut self.buf, args)?;
416 self.curr_size += self.buf.len();
417
418 self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
420 }
421
422 pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> {
423 self.fmt.write_str(s)?;
424 Ok(())
425 }
426
427 pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> {
428 self.fmt.write_char(c)?;
429 Ok(())
430 }
431
432 pub fn should_truncate(&self) -> bool {
433 match self.max_size {
434 Some(max_size) => self.curr_size >= max_size,
435 None => false,
436 }
437 }
438
439 pub fn omit_verbose_types(&self) -> bool {
440 self.omit_verbose_types
441 }
442
443 pub fn show_container_bounds(&self) -> bool {
444 self.show_container_bounds
445 }
446}
447
448#[derive(Debug, Clone, Copy)]
449pub struct DisplayTarget {
450 krate: Crate,
451 pub edition: Edition,
452}
453
454impl DisplayTarget {
455 pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self {
456 let edition = krate.data(db).edition;
457 Self { krate, edition }
458 }
459}
460
461#[derive(Clone, Copy)]
462pub enum DisplayKind {
463 Diagnostics,
467 SourceCode { target_module_id: ModuleId, allow_opaque: bool },
470 Test,
472}
473
474impl DisplayKind {
475 fn is_source_code(self) -> bool {
476 matches!(self, Self::SourceCode { .. })
477 }
478
479 fn is_test(self) -> bool {
480 matches!(self, Self::Test)
481 }
482
483 fn allows_opaque(self) -> bool {
484 match self {
485 Self::SourceCode { allow_opaque, .. } => allow_opaque,
486 _ => true,
487 }
488 }
489}
490
491#[derive(Debug)]
492pub enum DisplaySourceCodeError {
493 PathNotFound,
494 Coroutine,
495 OpaqueType,
496}
497
498pub enum HirDisplayError {
499 DisplaySourceCodeError(DisplaySourceCodeError),
501 FmtError,
503}
504impl From<fmt::Error> for HirDisplayError {
505 fn from(_: fmt::Error) -> Self {
506 Self::FmtError
507 }
508}
509
510pub struct HirDisplayWrapper<'a, T> {
511 db: &'a dyn HirDatabase,
512 t: &'a T,
513 max_size: Option<usize>,
514 limited_size: Option<usize>,
515 omit_verbose_types: bool,
516 closure_style: ClosureStyle,
517 display_kind: DisplayKind,
518 display_target: DisplayTarget,
519 show_container_bounds: bool,
520 display_lifetimes: DisplayLifetime,
521}
522
523#[derive(Debug, PartialEq, Eq, Clone, Copy)]
524pub enum ClosureStyle {
525 ImplFn,
528 RANotation,
530 ClosureWithId,
532 ClosureWithSubst,
534 Hide,
536}
537
538impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
539 pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
540 self.t.hir_fmt(&mut HirFormatter {
541 db: self.db,
542 fmt: f,
543 buf: String::with_capacity(self.max_size.unwrap_or(20)),
544 curr_size: 0,
545 max_size: self.max_size,
546 entity_limit: self.limited_size,
547 omit_verbose_types: self.omit_verbose_types,
548 display_kind: self.display_kind,
549 display_target: self.display_target,
550 closure_style: self.closure_style,
551 show_container_bounds: self.show_container_bounds,
552 display_lifetimes: self.display_lifetimes,
553 bounds_formatting_ctx: Default::default(),
554 })
555 }
556
557 pub fn with_closure_style(mut self, c: ClosureStyle) -> Self {
558 self.closure_style = c;
559 self
560 }
561
562 pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self {
563 self.display_lifetimes = l;
564 self
565 }
566}
567
568impl<T> fmt::Display for HirDisplayWrapper<'_, T>
569where
570 T: HirDisplay,
571{
572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573 match self.write_to(f) {
574 Ok(()) => Ok(()),
575 Err(HirDisplayError::FmtError) => Err(fmt::Error),
576 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
577 panic!(
579 "HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!"
580 )
581 }
582 }
583 }
584}
585
586const TYPE_HINT_TRUNCATION: &str = "…";
587
588impl<T: HirDisplay> HirDisplay for &T {
589 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
590 HirDisplay::hir_fmt(*self, f)
591 }
592}
593
594impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
595 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
596 HirDisplay::hir_fmt(self.as_ref(), f)
597 }
598}
599
600impl HirDisplay for ProjectionTy {
601 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
602 if f.should_truncate() {
603 return write!(f, "{TYPE_HINT_TRUNCATION}");
604 }
605 let trait_ref = self.trait_ref(f.db);
606 let self_ty = trait_ref.self_type_parameter(Interner);
607
608 if !f.display_kind.is_source_code() {
612 if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
613 if !f.bounds_formatting_ctx.contains(self) {
614 let db = f.db;
615 let id = from_placeholder_idx(db, *idx);
616 let generics = generics(db, id.parent);
617
618 let substs = generics.placeholder_subst(db);
619 let bounds = db
620 .generic_predicates(id.parent)
621 .iter()
622 .map(|pred| pred.clone().substitute(Interner, &substs))
623 .filter(|wc| match wc.skip_binders() {
624 WhereClause::Implemented(tr) => {
625 matches!(
626 tr.self_type_parameter(Interner).kind(Interner),
627 TyKind::Alias(_)
628 )
629 }
630 WhereClause::TypeOutlives(t) => {
631 matches!(t.ty.kind(Interner), TyKind::Alias(_))
632 }
633 WhereClause::AliasEq(_) => false,
635 WhereClause::LifetimeOutlives(_) => false,
636 })
637 .collect::<Vec<_>>();
638 if !bounds.is_empty() {
639 return f.format_bounds_with(self.clone(), |f| {
640 write_bounds_like_dyn_trait_with_prefix(
641 f,
642 "impl",
643 Either::Left(
644 &TyKind::Alias(AliasTy::Projection(self.clone()))
645 .intern(Interner),
646 ),
647 &bounds,
648 SizedByDefault::NotSized,
649 )
650 });
651 }
652 }
653 }
654 }
655
656 write!(f, "<")?;
657 self_ty.hir_fmt(f)?;
658 write!(f, " as ")?;
659 trait_ref.hir_fmt(f)?;
660 write!(
661 f,
662 ">::{}",
663 f.db.type_alias_signature(from_assoc_type_id(self.associated_ty_id))
664 .name
665 .display(f.db, f.edition())
666 )?;
667 let proj_params =
668 &self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..];
669 hir_fmt_generics(f, proj_params, None, None)
670 }
671}
672
673impl HirDisplay for OpaqueTy {
674 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
675 if f.should_truncate() {
676 return write!(f, "{TYPE_HINT_TRUNCATION}");
677 }
678
679 self.substitution.at(Interner, 0).hir_fmt(f)
680 }
681}
682
683impl HirDisplay for GenericArg {
684 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
685 match self.interned() {
686 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
687 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
688 crate::GenericArgData::Const(c) => c.hir_fmt(f),
689 }
690 }
691}
692
693impl HirDisplay for Const {
694 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
695 let data = self.interned();
696 match &data.value {
697 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
698 ConstValue::InferenceVar(..) => write!(f, "#c#"),
699 ConstValue::Placeholder(idx) => {
700 let id = from_placeholder_idx(f.db, *idx);
701 let generics = generics(f.db, id.parent);
702 let param_data = &generics[id.local_id];
703 write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
704 Ok(())
705 }
706 ConstValue::Concrete(c) => match &c.interned {
707 ConstScalar::Bytes(b, m) => render_const_scalar(f, b, m, &data.ty),
708 ConstScalar::UnevaluatedConst(c, parameters) => {
709 write!(f, "{}", c.name(f.db))?;
710 hir_fmt_generics(f, parameters.as_slice(Interner), c.generic_def(f.db), None)?;
711 Ok(())
712 }
713 ConstScalar::Unknown => f.write_char('_'),
714 },
715 }
716 }
717}
718
719fn render_const_scalar(
720 f: &mut HirFormatter<'_>,
721 b: &[u8],
722 memory_map: &MemoryMap,
723 ty: &Ty,
724) -> Result<(), HirDisplayError> {
725 let trait_env = TraitEnvironment::empty(f.krate());
726 let ty = normalize(f.db, trait_env.clone(), ty.clone());
727 match ty.kind(Interner) {
728 TyKind::Scalar(s) => match s {
729 Scalar::Bool => write!(f, "{}", b[0] != 0),
730 Scalar::Char => {
731 let it = u128::from_le_bytes(pad16(b, false)) as u32;
732 let Ok(c) = char::try_from(it) else {
733 return f.write_str("<unicode-error>");
734 };
735 write!(f, "{c:?}")
736 }
737 Scalar::Int(_) => {
738 let it = i128::from_le_bytes(pad16(b, true));
739 write!(f, "{it}")
740 }
741 Scalar::Uint(_) => {
742 let it = u128::from_le_bytes(pad16(b, false));
743 write!(f, "{it}")
744 }
745 Scalar::Float(fl) => match fl {
746 chalk_ir::FloatTy::F16 => {
747 let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());
749 let s = it.to_string();
750 if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
751 write!(f, "{s}.0")
753 } else {
754 write!(f, "{s}")
755 }
756 }
757 chalk_ir::FloatTy::F32 => {
758 let it = f32::from_le_bytes(b.try_into().unwrap());
759 write!(f, "{it:?}")
760 }
761 chalk_ir::FloatTy::F64 => {
762 let it = f64::from_le_bytes(b.try_into().unwrap());
763 write!(f, "{it:?}")
764 }
765 chalk_ir::FloatTy::F128 => {
766 let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));
768 let s = it.to_string();
769 if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
770 write!(f, "{s}.0")
772 } else {
773 write!(f, "{s}")
774 }
775 }
776 },
777 },
778 TyKind::Ref(_, _, t) => match t.kind(Interner) {
779 TyKind::Str => {
780 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
781 let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
782 let Some(bytes) = memory_map.get(addr, size) else {
783 return f.write_str("<ref-data-not-available>");
784 };
785 let s = std::str::from_utf8(bytes).unwrap_or("<utf8-error>");
786 write!(f, "{s:?}")
787 }
788 TyKind::Slice(ty) => {
789 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
790 let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
791 let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
792 return f.write_str("<layout-error>");
793 };
794 let size_one = layout.size.bytes_usize();
795 let Some(bytes) = memory_map.get(addr, size_one * count) else {
796 return f.write_str("<ref-data-not-available>");
797 };
798 f.write_str("&[")?;
799 let mut first = true;
800 for i in 0..count {
801 if first {
802 first = false;
803 } else {
804 f.write_str(", ")?;
805 }
806 let offset = size_one * i;
807 render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, ty)?;
808 }
809 f.write_str("]")
810 }
811 TyKind::Dyn(_) => {
812 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
813 let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
814 let Ok(t) = memory_map.vtable_ty(ty_id) else {
815 return f.write_str("<ty-missing-in-vtable-map>");
816 };
817 let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
818 return f.write_str("<layout-error>");
819 };
820 let size = layout.size.bytes_usize();
821 let Some(bytes) = memory_map.get(addr, size) else {
822 return f.write_str("<ref-data-not-available>");
823 };
824 f.write_str("&")?;
825 render_const_scalar(f, bytes, memory_map, t)
826 }
827 TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.0 {
828 hir_def::AdtId::StructId(s) => {
829 let data = f.db.struct_signature(s);
830 write!(f, "&{}", data.name.display(f.db, f.edition()))?;
831 Ok(())
832 }
833 _ => f.write_str("<unsized-enum-or-union>"),
834 },
835 _ => {
836 let addr = usize::from_le_bytes(match b.try_into() {
837 Ok(b) => b,
838 Err(_) => {
839 never!(
840 "tried rendering ty {:?} in const ref with incorrect byte count {}",
841 t,
842 b.len()
843 );
844 return f.write_str("<layout-error>");
845 }
846 });
847 let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
848 return f.write_str("<layout-error>");
849 };
850 let size = layout.size.bytes_usize();
851 let Some(bytes) = memory_map.get(addr, size) else {
852 return f.write_str("<ref-data-not-available>");
853 };
854 f.write_str("&")?;
855 render_const_scalar(f, bytes, memory_map, t)
856 }
857 },
858 TyKind::Tuple(_, subst) => {
859 let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
860 return f.write_str("<layout-error>");
861 };
862 f.write_str("(")?;
863 let mut first = true;
864 for (id, ty) in subst.iter(Interner).enumerate() {
865 if first {
866 first = false;
867 } else {
868 f.write_str(", ")?;
869 }
870 let ty = ty.assert_ty_ref(Interner); let offset = layout.fields.offset(id).bytes_usize();
872 let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
873 f.write_str("<layout-error>")?;
874 continue;
875 };
876 let size = layout.size.bytes_usize();
877 render_const_scalar(f, &b[offset..offset + size], memory_map, ty)?;
878 }
879 f.write_str(")")
880 }
881 TyKind::Adt(adt, subst) => {
882 let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else {
883 return f.write_str("<layout-error>");
884 };
885 match adt.0 {
886 hir_def::AdtId::StructId(s) => {
887 let data = f.db.struct_signature(s);
888 write!(f, "{}", data.name.display(f.db, f.edition()))?;
889 let field_types = f.db.field_types(s.into());
890 render_variant_after_name(
891 &f.db.variant_fields(s.into()),
892 f,
893 &field_types,
894 f.db.trait_environment(adt.0.into()),
895 &layout,
896 subst,
897 b,
898 memory_map,
899 )
900 }
901 hir_def::AdtId::UnionId(u) => {
902 write!(f, "{}", f.db.union_signature(u).name.display(f.db, f.edition()))
903 }
904 hir_def::AdtId::EnumId(e) => {
905 let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else {
906 return f.write_str("<target-layout-not-available>");
907 };
908 let Some((var_id, var_layout)) =
909 detect_variant_from_bytes(&layout, f.db, &target_data_layout, b, e)
910 else {
911 return f.write_str("<failed-to-detect-variant>");
912 };
913 let loc = var_id.lookup(f.db);
914 write!(
915 f,
916 "{}",
917 loc.parent.enum_variants(f.db).variants[loc.index as usize]
918 .1
919 .display(f.db, f.edition())
920 )?;
921 let field_types = f.db.field_types(var_id.into());
922 render_variant_after_name(
923 &f.db.variant_fields(var_id.into()),
924 f,
925 &field_types,
926 f.db.trait_environment(adt.0.into()),
927 var_layout,
928 subst,
929 b,
930 memory_map,
931 )
932 }
933 }
934 }
935 TyKind::FnDef(..) => ty.hir_fmt(f),
936 TyKind::Function(_) | TyKind::Raw(_, _) => {
937 let it = u128::from_le_bytes(pad16(b, false));
938 write!(f, "{it:#X} as ")?;
939 ty.hir_fmt(f)
940 }
941 TyKind::Array(ty, len) => {
942 let Some(len) = try_const_usize(f.db, len) else {
943 return f.write_str("<unknown-array-len>");
944 };
945 let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
946 return f.write_str("<layout-error>");
947 };
948 let size_one = layout.size.bytes_usize();
949 f.write_str("[")?;
950 let mut first = true;
951 for i in 0..len as usize {
952 if first {
953 first = false;
954 } else {
955 f.write_str(", ")?;
956 }
957 let offset = size_one * i;
958 render_const_scalar(f, &b[offset..offset + size_one], memory_map, ty)?;
959 }
960 f.write_str("]")
961 }
962 TyKind::Never => f.write_str("!"),
963 TyKind::Closure(_, _) => f.write_str("<closure>"),
964 TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),
965 TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),
966 TyKind::Foreign(_) => f.write_str("<extern-type>"),
968 TyKind::Error
969 | TyKind::Placeholder(_)
970 | TyKind::Alias(_)
971 | TyKind::AssociatedType(_, _)
972 | TyKind::OpaqueType(_, _)
973 | TyKind::BoundVar(_)
974 | TyKind::InferenceVar(_, _) => f.write_str("<placeholder-or-unknown-type>"),
975 TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => f.write_str("<unsized-value>"),
977 }
978}
979
980fn render_variant_after_name(
981 data: &VariantFields,
982 f: &mut HirFormatter<'_>,
983 field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
984 trait_env: Arc<TraitEnvironment>,
985 layout: &Layout,
986 subst: &Substitution,
987 b: &[u8],
988 memory_map: &MemoryMap,
989) -> Result<(), HirDisplayError> {
990 match data.shape {
991 FieldsShape::Record | FieldsShape::Tuple => {
992 let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
993 let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
994 let ty = field_types[id].clone().substitute(Interner, subst);
995 let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
996 return f.write_str("<layout-error>");
997 };
998 let size = layout.size.bytes_usize();
999 render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)
1000 };
1001 let mut it = data.fields().iter();
1002 if matches!(data.shape, FieldsShape::Record) {
1003 write!(f, " {{")?;
1004 if let Some((id, data)) = it.next() {
1005 write!(f, " {}: ", data.name.display(f.db, f.edition()))?;
1006 render_field(f, id)?;
1007 }
1008 for (id, data) in it {
1009 write!(f, ", {}: ", data.name.display(f.db, f.edition()))?;
1010 render_field(f, id)?;
1011 }
1012 write!(f, " }}")?;
1013 } else {
1014 let mut it = it.map(|it| it.0);
1015 write!(f, "(")?;
1016 if let Some(id) = it.next() {
1017 render_field(f, id)?;
1018 }
1019 for id in it {
1020 write!(f, ", ")?;
1021 render_field(f, id)?;
1022 }
1023 write!(f, ")")?;
1024 }
1025 Ok(())
1026 }
1027 FieldsShape::Unit => Ok(()),
1028 }
1029}
1030
1031impl HirDisplay for BoundVar {
1032 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1033 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
1034 }
1035}
1036
1037impl HirDisplay for Ty {
1038 fn hir_fmt(
1039 &self,
1040 f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
1041 ) -> Result<(), HirDisplayError> {
1042 if f.should_truncate() {
1043 return write!(f, "{TYPE_HINT_TRUNCATION}");
1044 }
1045
1046 match self.kind(Interner) {
1047 TyKind::Never => write!(f, "!")?,
1048 TyKind::Str => write!(f, "str")?,
1049 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
1050 TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
1051 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
1052 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
1053 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
1054 TyKind::Slice(t) => {
1055 write!(f, "[")?;
1056 t.hir_fmt(f)?;
1057 write!(f, "]")?;
1058 }
1059 TyKind::Array(t, c) => {
1060 write!(f, "[")?;
1061 t.hir_fmt(f)?;
1062 write!(f, "; ")?;
1063 c.hir_fmt(f)?;
1064 write!(f, "]")?;
1065 }
1066 kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
1067 if let TyKind::Ref(_, l, _) = kind {
1068 f.write_char('&')?;
1069 if f.render_lifetime(l) {
1070 l.hir_fmt(f)?;
1071 f.write_char(' ')?;
1072 }
1073 match m {
1074 Mutability::Not => (),
1075 Mutability::Mut => f.write_str("mut ")?,
1076 }
1077 } else {
1078 write!(
1079 f,
1080 "*{}",
1081 match m {
1082 Mutability::Not => "const ",
1083 Mutability::Mut => "mut ",
1084 }
1085 )?;
1086 }
1087
1088 let contains_impl_fn = |bounds: &[QuantifiedWhereClause]| {
1090 bounds.iter().any(|bound| {
1091 if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
1092 let trait_ = trait_ref.hir_trait_id();
1093 fn_traits(db, trait_).any(|it| it == trait_)
1094 } else {
1095 false
1096 }
1097 })
1098 };
1099 let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
1100 TyKind::Dyn(dyn_ty) => {
1101 let bounds = dyn_ty.bounds.skip_binders().interned();
1102 let render_lifetime = f.render_lifetime(&dyn_ty.lifetime);
1103 (bounds.len() + render_lifetime as usize, contains_impl_fn(bounds))
1104 }
1105 TyKind::Alias(AliasTy::Opaque(OpaqueTy {
1106 opaque_ty_id,
1107 substitution: parameters,
1108 }))
1109 | TyKind::OpaqueType(opaque_ty_id, parameters) => {
1110 let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
1111 if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
1112 let datas = db
1113 .return_type_impl_traits(func)
1114 .expect("impl trait id without data");
1115 let data =
1116 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1117 let bounds = data.substitute(Interner, parameters);
1118 let mut len = bounds.skip_binders().len();
1119
1120 let default_sized = SizedByDefault::Sized { anchor: func.krate(db) };
1123 let sized_bounds = bounds
1124 .skip_binders()
1125 .iter()
1126 .filter(|b| {
1127 matches!(
1128 b.skip_binders(),
1129 WhereClause::Implemented(trait_ref)
1130 if default_sized.is_sized_trait(
1131 trait_ref.hir_trait_id(),
1132 db,
1133 ),
1134 )
1135 })
1136 .count();
1137 match sized_bounds {
1138 0 => len += 1,
1139 _ => {
1140 len = len.saturating_sub(sized_bounds);
1141 }
1142 }
1143
1144 (len, contains_impl_fn(bounds.skip_binders()))
1145 } else {
1146 (0, false)
1147 }
1148 }
1149 _ => (0, false),
1150 };
1151
1152 if has_impl_fn_pred && preds_to_print <= 2 {
1153 return t.hir_fmt(f);
1154 }
1155
1156 if preds_to_print > 1 {
1157 write!(f, "(")?;
1158 t.hir_fmt(f)?;
1159 write!(f, ")")?;
1160 } else {
1161 t.hir_fmt(f)?;
1162 }
1163 }
1164 TyKind::Tuple(_, substs) => {
1165 if substs.len(Interner) == 1 {
1166 write!(f, "(")?;
1167 substs.at(Interner, 0).hir_fmt(f)?;
1168 write!(f, ",)")?;
1169 } else {
1170 write!(f, "(")?;
1171 f.write_joined(substs.as_slice(Interner), ", ")?;
1172 write!(f, ")")?;
1173 }
1174 }
1175 TyKind::Function(fn_ptr) => {
1176 let sig = CallableSig::from_fn_ptr(fn_ptr);
1177 sig.hir_fmt(f)?;
1178 }
1179 TyKind::FnDef(def, parameters) => {
1180 let def = from_chalk(db, *def);
1181 let sig = db.callable_item_signature(def).substitute(Interner, parameters);
1182
1183 if f.display_kind.is_source_code() {
1184 return sig.hir_fmt(f);
1187 }
1188 if let Safety::Unsafe = sig.safety {
1189 write!(f, "unsafe ")?;
1190 }
1191 if !matches!(sig.abi, FnAbi::Rust | FnAbi::RustCall) {
1192 f.write_str("extern \"")?;
1193 f.write_str(sig.abi.as_str())?;
1194 f.write_str("\" ")?;
1195 }
1196
1197 write!(f, "fn ")?;
1198 f.start_location_link(def.into());
1199 match def {
1200 CallableDefId::FunctionId(ff) => {
1201 write!(f, "{}", db.function_signature(ff).name.display(f.db, f.edition()))?
1202 }
1203 CallableDefId::StructId(s) => {
1204 write!(f, "{}", db.struct_signature(s).name.display(f.db, f.edition()))?
1205 }
1206 CallableDefId::EnumVariantId(e) => {
1207 let loc = e.lookup(db);
1208 write!(
1209 f,
1210 "{}",
1211 loc.parent.enum_variants(db).variants[loc.index as usize]
1212 .1
1213 .display(db, f.edition())
1214 )?
1215 }
1216 };
1217 f.end_location_link();
1218
1219 if parameters.len(Interner) > 0 {
1220 let generic_def_id = GenericDefId::from_callable(db, def);
1221 let generics = generics(db, generic_def_id);
1222 let (parent_len, self_param, type_, const_, impl_, lifetime) =
1223 generics.provenance_split();
1224 let parameters = parameters.as_slice(Interner);
1225 debug_assert_eq!(
1226 parameters.len(),
1227 parent_len + self_param as usize + type_ + const_ + impl_ + lifetime
1228 );
1229 if parameters.len() - impl_ > 0 {
1231 let params_len = parameters.len();
1232 let parameters =
1234 generic_args_sans_defaults(f, Some(generic_def_id), parameters);
1235 assert!(params_len >= parameters.len());
1236 let defaults = params_len - parameters.len();
1237
1238 let parent_end = if parent_len > 0 {
1246 parent_len - defaults
1249 } else {
1250 parent_len
1251 };
1252 let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;
1253 let (parent_params, fn_params) = parameters.split_at(parent_end);
1254
1255 write!(f, "<")?;
1256 hir_fmt_generic_arguments(f, parent_params, None)?;
1257 if !parent_params.is_empty() && !fn_params.is_empty() {
1258 write!(f, ", ")?;
1259 }
1260 hir_fmt_generic_arguments(
1261 f,
1262 &fn_params[..fn_params_no_impl_or_defaults],
1263 None,
1264 )?;
1265 write!(f, ">")?;
1266 }
1267 }
1268 write!(f, "(")?;
1269 f.write_joined(sig.params(), ", ")?;
1270 write!(f, ")")?;
1271 let ret = sig.ret();
1272 if !ret.is_unit() {
1273 write!(f, " -> ")?;
1274 ret.hir_fmt(f)?;
1275 }
1276 }
1277 TyKind::Adt(AdtId(def_id), parameters) => {
1278 f.start_location_link((*def_id).into());
1279 match f.display_kind {
1280 DisplayKind::Diagnostics | DisplayKind::Test => {
1281 let name = match *def_id {
1282 hir_def::AdtId::StructId(it) => db.struct_signature(it).name.clone(),
1283 hir_def::AdtId::UnionId(it) => db.union_signature(it).name.clone(),
1284 hir_def::AdtId::EnumId(it) => db.enum_signature(it).name.clone(),
1285 };
1286 write!(f, "{}", name.display(f.db, f.edition()))?;
1287 }
1288 DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => {
1289 if let Some(path) = find_path::find_path(
1290 db,
1291 ItemInNs::Types((*def_id).into()),
1292 module_id,
1293 PrefixKind::Plain,
1294 false,
1295 ImportPathConfig {
1297 prefer_no_std: false,
1298 prefer_prelude: true,
1299 prefer_absolute: false,
1300 allow_unstable: true,
1301 },
1302 ) {
1303 write!(f, "{}", path.display(f.db, f.edition()))?;
1304 } else {
1305 return Err(HirDisplayError::DisplaySourceCodeError(
1306 DisplaySourceCodeError::PathNotFound,
1307 ));
1308 }
1309 }
1310 }
1311 f.end_location_link();
1312
1313 let generic_def = self.as_generic_def(db);
1314
1315 hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?;
1316 }
1317 TyKind::AssociatedType(assoc_type_id, parameters) => {
1318 let type_alias = from_assoc_type_id(*assoc_type_id);
1319 let trait_ = match type_alias.lookup(db).container {
1320 ItemContainerId::TraitId(it) => it,
1321 _ => panic!("not an associated type"),
1322 };
1323 let trait_data = db.trait_signature(trait_);
1324 let type_alias_data = db.type_alias_signature(type_alias);
1325
1326 if f.display_kind.is_test() {
1328 f.start_location_link(trait_.into());
1329 write!(f, "{}", trait_data.name.display(f.db, f.edition()))?;
1330 f.end_location_link();
1331 write!(f, "::")?;
1332
1333 f.start_location_link(type_alias.into());
1334 write!(f, "{}", type_alias_data.name.display(f.db, f.edition()))?;
1335 f.end_location_link();
1336 hir_fmt_generics(f, parameters.as_slice(Interner), None, None)
1339 } else {
1340 let projection_ty = ProjectionTy {
1341 associated_ty_id: to_assoc_type_id(type_alias),
1342 substitution: parameters.clone(),
1343 };
1344
1345 projection_ty.hir_fmt(f)
1346 }?;
1347 }
1348 TyKind::Foreign(type_alias) => {
1349 let alias = from_foreign_def_id(*type_alias);
1350 let type_alias = db.type_alias_signature(alias);
1351 f.start_location_link(alias.into());
1352 write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
1353 f.end_location_link();
1354 }
1355 TyKind::OpaqueType(opaque_ty_id, parameters) => {
1356 if !f.display_kind.allows_opaque() {
1357 return Err(HirDisplayError::DisplaySourceCodeError(
1358 DisplaySourceCodeError::OpaqueType,
1359 ));
1360 }
1361 let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
1362 match impl_trait_id {
1363 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1364 let datas =
1365 db.return_type_impl_traits(func).expect("impl trait id without data");
1366 let data =
1367 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1368 let bounds = data.substitute(Interner, ¶meters);
1369 let krate = func.krate(db);
1370 write_bounds_like_dyn_trait_with_prefix(
1371 f,
1372 "impl",
1373 Either::Left(self),
1374 bounds.skip_binders(),
1375 SizedByDefault::Sized { anchor: krate },
1376 )?;
1377 }
1379 ImplTraitId::TypeAliasImplTrait(alias, idx) => {
1380 let datas =
1381 db.type_alias_impl_traits(alias).expect("impl trait id without data");
1382 let data = (*datas).as_ref().map(|it| it.impl_traits[idx].bounds.clone());
1383 let bounds = data.substitute(Interner, ¶meters);
1384 let krate = alias.krate(db);
1385 write_bounds_like_dyn_trait_with_prefix(
1386 f,
1387 "impl",
1388 Either::Left(self),
1389 bounds.skip_binders(),
1390 SizedByDefault::Sized { anchor: krate },
1391 )?;
1392 }
1393 ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
1394 let future_trait =
1395 LangItem::Future.resolve_trait(db, body.module(db).krate());
1396 let output = future_trait.and_then(|t| {
1397 db.trait_items(t)
1398 .associated_type_by_name(&Name::new_symbol_root(sym::Output))
1399 });
1400 write!(f, "impl ")?;
1401 if let Some(t) = future_trait {
1402 f.start_location_link(t.into());
1403 }
1404 write!(f, "Future")?;
1405 if future_trait.is_some() {
1406 f.end_location_link();
1407 }
1408 write!(f, "<")?;
1409 if let Some(t) = output {
1410 f.start_location_link(t.into());
1411 }
1412 write!(f, "Output")?;
1413 if output.is_some() {
1414 f.end_location_link();
1415 }
1416 write!(f, " = ")?;
1417 parameters.at(Interner, 0).hir_fmt(f)?;
1418 write!(f, ">")?;
1419 }
1420 }
1421 }
1422 TyKind::Closure(id, substs) => {
1423 if f.display_kind.is_source_code() {
1424 if !f.display_kind.allows_opaque() {
1425 return Err(HirDisplayError::DisplaySourceCodeError(
1426 DisplaySourceCodeError::OpaqueType,
1427 ));
1428 } else if f.closure_style != ClosureStyle::ImplFn {
1429 never!("Only `impl Fn` is valid for displaying closures in source code");
1430 }
1431 }
1432 match f.closure_style {
1433 ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
1434 ClosureStyle::ClosureWithId => {
1435 return write!(f, "{{closure#{:?}}}", id.0.as_u32());
1436 }
1437 ClosureStyle::ClosureWithSubst => {
1438 write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
1439 return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
1440 }
1441 _ => (),
1442 }
1443 let sig = ClosureSubst(substs).sig_ty().callable_sig(db);
1444 if let Some(sig) = sig {
1445 let InternedClosure(def, _) = db.lookup_intern_closure((*id).into());
1446 let infer = db.infer(def);
1447 let (_, kind) = infer.closure_info(id);
1448 match f.closure_style {
1449 ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
1450 ClosureStyle::RANotation => write!(f, "|")?,
1451 _ => unreachable!(),
1452 }
1453 if sig.params().is_empty() {
1454 } else if f.should_truncate() {
1455 write!(f, "{TYPE_HINT_TRUNCATION}")?;
1456 } else {
1457 f.write_joined(sig.params(), ", ")?;
1458 };
1459 match f.closure_style {
1460 ClosureStyle::ImplFn => write!(f, ")")?,
1461 ClosureStyle::RANotation => write!(f, "|")?,
1462 _ => unreachable!(),
1463 }
1464 if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() {
1465 write!(f, " -> ")?;
1466 sig.ret().hir_fmt(f)?;
1469 }
1470 } else {
1471 write!(f, "{{closure}}")?;
1472 }
1473 }
1474 TyKind::Placeholder(idx) => {
1475 let id = from_placeholder_idx(db, *idx);
1476 let generics = generics(db, id.parent);
1477 let param_data = &generics[id.local_id];
1478 match param_data {
1479 TypeOrConstParamData::TypeParamData(p) => match p.provenance {
1480 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
1481 write!(
1482 f,
1483 "{}",
1484 p.name
1485 .clone()
1486 .unwrap_or_else(Name::missing)
1487 .display(f.db, f.edition())
1488 )?
1489 }
1490 TypeParamProvenance::ArgumentImplTrait => {
1491 let substs = generics.placeholder_subst(db);
1492 let bounds = db
1493 .generic_predicates(id.parent)
1494 .iter()
1495 .map(|pred| pred.clone().substitute(Interner, &substs))
1496 .filter(|wc| match wc.skip_binders() {
1497 WhereClause::Implemented(tr) => {
1498 tr.self_type_parameter(Interner) == *self
1499 }
1500 WhereClause::AliasEq(AliasEq {
1501 alias: AliasTy::Projection(proj),
1502 ty: _,
1503 }) => proj.self_type_parameter(db) == *self,
1504 WhereClause::AliasEq(_) => false,
1505 WhereClause::TypeOutlives(to) => to.ty == *self,
1506 WhereClause::LifetimeOutlives(_) => false,
1507 })
1508 .collect::<Vec<_>>();
1509 let krate = id.parent.module(db).krate();
1510 write_bounds_like_dyn_trait_with_prefix(
1511 f,
1512 "impl",
1513 Either::Left(self),
1514 &bounds,
1515 SizedByDefault::Sized { anchor: krate },
1516 )?;
1517 }
1518 },
1519 TypeOrConstParamData::ConstParamData(p) => {
1520 write!(f, "{}", p.name.display(f.db, f.edition()))?;
1521 }
1522 }
1523 }
1524 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
1525 TyKind::Dyn(dyn_ty) => {
1526 let mut bounds: SmallVec<[_; 4]> =
1530 dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
1531 let (auto_traits, others): (SmallVec<[_; 4]>, _) =
1532 bounds.drain(1..).partition(|b| b.skip_binders().trait_id().is_some());
1533 bounds.extend(others);
1534 bounds.extend(auto_traits);
1535
1536 if f.render_lifetime(&dyn_ty.lifetime) {
1537 bounds.push(Binders::empty(
1539 Interner,
1540 chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
1541 ty: self.clone(),
1542 lifetime: dyn_ty.lifetime.clone(),
1543 }),
1544 ));
1545 }
1546
1547 write_bounds_like_dyn_trait_with_prefix(
1548 f,
1549 "dyn",
1550 Either::Left(self),
1551 &bounds,
1552 SizedByDefault::NotSized,
1553 )?;
1554 }
1555 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
1556 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
1557 if !f.display_kind.allows_opaque() {
1558 return Err(HirDisplayError::DisplaySourceCodeError(
1559 DisplaySourceCodeError::OpaqueType,
1560 ));
1561 }
1562 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
1563 match impl_trait_id {
1564 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1565 let datas =
1566 db.return_type_impl_traits(func).expect("impl trait id without data");
1567 let data =
1568 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1569 let bounds = data.substitute(Interner, &opaque_ty.substitution);
1570 let krate = func.krate(db);
1571 write_bounds_like_dyn_trait_with_prefix(
1572 f,
1573 "impl",
1574 Either::Left(self),
1575 bounds.skip_binders(),
1576 SizedByDefault::Sized { anchor: krate },
1577 )?;
1578 }
1579 ImplTraitId::TypeAliasImplTrait(alias, idx) => {
1580 let datas =
1581 db.type_alias_impl_traits(alias).expect("impl trait id without data");
1582 let data =
1583 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1584 let bounds = data.substitute(Interner, &opaque_ty.substitution);
1585 let krate = alias.krate(db);
1586 write_bounds_like_dyn_trait_with_prefix(
1587 f,
1588 "impl",
1589 Either::Left(self),
1590 bounds.skip_binders(),
1591 SizedByDefault::Sized { anchor: krate },
1592 )?;
1593 }
1594 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
1595 write!(f, "{{async block}}")?;
1596 }
1597 };
1598 }
1599 TyKind::Error => {
1600 if f.display_kind.is_source_code() {
1601 f.write_char('_')?;
1602 } else {
1603 write!(f, "{{unknown}}")?;
1604 }
1605 }
1606 TyKind::InferenceVar(..) => write!(f, "_")?,
1607 TyKind::Coroutine(_, subst) => {
1608 if f.display_kind.is_source_code() {
1609 return Err(HirDisplayError::DisplaySourceCodeError(
1610 DisplaySourceCodeError::Coroutine,
1611 ));
1612 }
1613 let subst = subst.as_slice(Interner);
1614 let a: Option<SmallVec<[&Ty; 3]>> = subst
1615 .get(subst.len() - 3..)
1616 .and_then(|args| args.iter().map(|arg| arg.ty(Interner)).collect());
1617
1618 if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
1619 write!(f, "|")?;
1620 resume_ty.hir_fmt(f)?;
1621 write!(f, "|")?;
1622
1623 write!(f, " yields ")?;
1624 yield_ty.hir_fmt(f)?;
1625
1626 write!(f, " -> ")?;
1627 ret_ty.hir_fmt(f)?;
1628 } else {
1629 write!(f, "{{coroutine}}")?;
1631 }
1632 }
1633 TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
1634 }
1635 Ok(())
1636 }
1637}
1638
1639fn hir_fmt_generics(
1640 f: &mut HirFormatter<'_>,
1641 parameters: &[GenericArg],
1642 generic_def: Option<hir_def::GenericDefId>,
1643 self_: Option<&Ty>,
1644) -> Result<(), HirDisplayError> {
1645 if parameters.is_empty() {
1646 return Ok(());
1647 }
1648
1649 let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);
1650
1651 if !parameters_to_write.is_empty() {
1652 write!(f, "<")?;
1653 hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
1654 write!(f, ">")?;
1655 }
1656
1657 Ok(())
1658}
1659
1660fn generic_args_sans_defaults<'ga>(
1661 f: &mut HirFormatter<'_>,
1662 generic_def: Option<hir_def::GenericDefId>,
1663 parameters: &'ga [GenericArg],
1664) -> &'ga [GenericArg] {
1665 if f.display_kind.is_source_code() || f.omit_verbose_types() {
1666 match generic_def
1667 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
1668 .filter(|it| !it.is_empty())
1669 {
1670 None => parameters,
1671 Some(default_parameters) => {
1672 let should_show = |arg: &GenericArg, i: usize| {
1673 let is_err = |arg: &GenericArg| match arg.data(Interner) {
1674 chalk_ir::GenericArgData::Lifetime(it) => {
1675 *it.data(Interner) == LifetimeData::Error
1676 }
1677 chalk_ir::GenericArgData::Ty(it) => *it.kind(Interner) == TyKind::Error,
1678 chalk_ir::GenericArgData::Const(it) => matches!(
1679 it.data(Interner).value,
1680 ConstValue::Concrete(ConcreteConst {
1681 interned: ConstScalar::Unknown,
1682 ..
1683 })
1684 ),
1685 };
1686 if is_err(arg) {
1688 return true;
1689 }
1690 match default_parameters.get(i) {
1693 None => true,
1694 Some(default_parameter) => {
1695 arg != &default_parameter.clone().substitute(Interner, ¶meters[..i])
1698 }
1699 }
1700 };
1701 let mut default_from = 0;
1702 for (i, parameter) in parameters.iter().enumerate() {
1703 if should_show(parameter, i) {
1704 default_from = i + 1;
1705 }
1706 }
1707 ¶meters[0..default_from]
1708 }
1709 }
1710 } else {
1711 parameters
1712 }
1713}
1714
1715fn hir_fmt_generic_arguments(
1716 f: &mut HirFormatter<'_>,
1717 parameters: &[GenericArg],
1718 self_: Option<&Ty>,
1719) -> Result<(), HirDisplayError> {
1720 let mut first = true;
1721 let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
1722
1723 let (ty_or_const, lifetimes) = match lifetime_offset {
1724 Some(offset) => parameters.split_at(offset),
1725 None => (parameters, &[][..]),
1726 };
1727 for generic_arg in lifetimes.iter().chain(ty_or_const) {
1728 if !mem::take(&mut first) {
1729 write!(f, ", ")?;
1730 }
1731 match self_ {
1732 self_ @ Some(_) if generic_arg.ty(Interner) == self_ => write!(f, "Self")?,
1733 _ => generic_arg.hir_fmt(f)?,
1734 }
1735 }
1736 Ok(())
1737}
1738
1739impl HirDisplay for CallableSig {
1740 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1741 let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self;
1742 if let Safety::Unsafe = safety {
1743 write!(f, "unsafe ")?;
1744 }
1745 write!(f, "fn(")?;
1752 f.write_joined(self.params(), ", ")?;
1753 if is_varargs {
1754 if self.params().is_empty() {
1755 write!(f, "...")?;
1756 } else {
1757 write!(f, ", ...")?;
1758 }
1759 }
1760 write!(f, ")")?;
1761 let ret = self.ret();
1762 if !ret.is_unit() {
1763 write!(f, " -> ")?;
1764 ret.hir_fmt(f)?;
1765 }
1766 Ok(())
1767 }
1768}
1769
1770fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
1771 let krate = trait_.lookup(db).container.krate();
1772 utils::fn_traits(db, krate)
1773}
1774
1775#[derive(Clone, Copy, PartialEq, Eq)]
1776pub enum SizedByDefault {
1777 NotSized,
1778 Sized { anchor: Crate },
1779}
1780
1781impl SizedByDefault {
1782 fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
1783 match self {
1784 Self::NotSized => false,
1785 Self::Sized { anchor } => {
1786 let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
1787 Some(trait_) == sized_trait
1788 }
1789 }
1790 }
1791}
1792
1793pub fn write_bounds_like_dyn_trait_with_prefix(
1794 f: &mut HirFormatter<'_>,
1795 prefix: &str,
1796 this: Either<&Ty, &Lifetime>,
1797 predicates: &[QuantifiedWhereClause],
1798 default_sized: SizedByDefault,
1799) -> Result<(), HirDisplayError> {
1800 write!(f, "{prefix}")?;
1801 if !predicates.is_empty()
1802 || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
1803 {
1804 write!(f, " ")?;
1805 write_bounds_like_dyn_trait(f, this, predicates, default_sized)
1806 } else {
1807 Ok(())
1808 }
1809}
1810
1811fn write_bounds_like_dyn_trait(
1812 f: &mut HirFormatter<'_>,
1813 this: Either<&Ty, &Lifetime>,
1814 predicates: &[QuantifiedWhereClause],
1815 default_sized: SizedByDefault,
1816) -> Result<(), HirDisplayError> {
1817 let mut first = true;
1824 let mut angle_open = false;
1825 let mut is_fn_trait = false;
1826 let mut is_sized = false;
1827 for p in predicates.iter() {
1828 match p.skip_binders() {
1829 WhereClause::Implemented(trait_ref) => {
1830 let trait_ = trait_ref.hir_trait_id();
1831 if default_sized.is_sized_trait(trait_, f.db) {
1832 is_sized = true;
1833 if matches!(default_sized, SizedByDefault::Sized { .. }) {
1834 continue;
1836 }
1837 }
1838 if !is_fn_trait {
1839 is_fn_trait = fn_traits(f.db, trait_).any(|it| it == trait_);
1840 }
1841 if !is_fn_trait && angle_open {
1842 write!(f, ">")?;
1843 angle_open = false;
1844 }
1845 if !first {
1846 write!(f, " + ")?;
1847 }
1848 f.start_location_link(trait_.into());
1852 write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
1853 f.end_location_link();
1854 if is_fn_trait {
1855 if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
1856 if let Some(args) =
1857 params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
1858 {
1859 write!(f, "(")?;
1860 hir_fmt_generic_arguments(
1861 f,
1862 args.as_slice(Interner),
1863 self_.ty(Interner),
1864 )?;
1865 write!(f, ")")?;
1866 }
1867 }
1868 } else {
1869 let params = generic_args_sans_defaults(
1870 f,
1871 Some(trait_.into()),
1872 trait_ref.substitution.as_slice(Interner),
1873 );
1874 if let [self_, params @ ..] = params {
1875 if !params.is_empty() {
1876 write!(f, "<")?;
1877 hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
1878 angle_open = true;
1880 }
1881 }
1882 }
1883 }
1884 WhereClause::TypeOutlives(to) if Either::Left(&to.ty) == this => {
1885 if !is_fn_trait && angle_open {
1886 write!(f, ">")?;
1887 angle_open = false;
1888 }
1889 if !first {
1890 write!(f, " + ")?;
1891 }
1892 to.lifetime.hir_fmt(f)?;
1893 }
1894 WhereClause::TypeOutlives(_) => {}
1895 WhereClause::LifetimeOutlives(lo) if Either::Right(&lo.a) == this => {
1896 if !is_fn_trait && angle_open {
1897 write!(f, ">")?;
1898 angle_open = false;
1899 }
1900 if !first {
1901 write!(f, " + ")?;
1902 }
1903 lo.b.hir_fmt(f)?;
1904 }
1905 WhereClause::LifetimeOutlives(_) => {}
1906 WhereClause::AliasEq(alias_eq) if is_fn_trait => {
1907 is_fn_trait = false;
1908 if !alias_eq.ty.is_unit() {
1909 write!(f, " -> ")?;
1910 alias_eq.ty.hir_fmt(f)?;
1911 }
1912 }
1913 WhereClause::AliasEq(AliasEq { ty, alias }) => {
1914 if angle_open {
1917 write!(f, ", ")?;
1918 } else {
1919 write!(f, "<")?;
1920 angle_open = true;
1921 }
1922 if let AliasTy::Projection(proj) = alias {
1923 let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
1924 let type_alias = f.db.type_alias_signature(assoc_ty_id);
1925 f.start_location_link(assoc_ty_id.into());
1926 write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
1927 f.end_location_link();
1928
1929 let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self();
1930 let parent_len = proj.substitution.len(Interner) - proj_arg_count;
1931 if proj_arg_count > 0 {
1932 write!(f, "<")?;
1933 hir_fmt_generic_arguments(
1934 f,
1935 &proj.substitution.as_slice(Interner)[parent_len..],
1936 None,
1937 )?;
1938 write!(f, ">")?;
1939 }
1940 write!(f, " = ")?;
1941 }
1942 ty.hir_fmt(f)?;
1943 }
1944 }
1945 first = false;
1946 }
1947 if angle_open {
1948 write!(f, ">")?;
1949 }
1950 if let SizedByDefault::Sized { anchor } = default_sized {
1951 let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
1952 if !is_sized {
1953 if !first {
1954 write!(f, " + ")?;
1955 }
1956 if let Some(sized_trait) = sized_trait {
1957 f.start_location_link(sized_trait.into());
1958 }
1959 write!(f, "?Sized")?;
1960 } else if first {
1961 if let Some(sized_trait) = sized_trait {
1962 f.start_location_link(sized_trait.into());
1963 }
1964 write!(f, "Sized")?;
1965 }
1966 if sized_trait.is_some() {
1967 f.end_location_link();
1968 }
1969 }
1970 Ok(())
1971}
1972
1973impl HirDisplay for TraitRef {
1974 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1975 let trait_ = self.hir_trait_id();
1976 f.start_location_link(trait_.into());
1977 write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
1978 f.end_location_link();
1979 let substs = self.substitution.as_slice(Interner);
1980 hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
1981 }
1982}
1983
1984impl HirDisplay for WhereClause {
1985 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1986 if f.should_truncate() {
1987 return write!(f, "{TYPE_HINT_TRUNCATION}");
1988 }
1989
1990 match self {
1991 WhereClause::Implemented(trait_ref) => {
1992 trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
1993 write!(f, ": ")?;
1994 trait_ref.hir_fmt(f)?;
1995 }
1996 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
1997 write!(f, "<")?;
1998 let trait_ref = &projection_ty.trait_ref(f.db);
1999 trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
2000 write!(f, " as ")?;
2001 trait_ref.hir_fmt(f)?;
2002 write!(f, ">::",)?;
2003 let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
2004 f.start_location_link(type_alias.into());
2005 write!(
2006 f,
2007 "{}",
2008 f.db.type_alias_signature(type_alias).name.display(f.db, f.edition()),
2009 )?;
2010 f.end_location_link();
2011 write!(f, " = ")?;
2012 ty.hir_fmt(f)?;
2013 }
2014 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
2015
2016 WhereClause::TypeOutlives(..) => {}
2018 WhereClause::LifetimeOutlives(..) => {}
2019 }
2020 Ok(())
2021 }
2022}
2023
2024impl HirDisplay for LifetimeOutlives {
2025 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2026 self.a.hir_fmt(f)?;
2027 write!(f, ": ")?;
2028 self.b.hir_fmt(f)
2029 }
2030}
2031
2032impl HirDisplay for Lifetime {
2033 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2034 self.interned().hir_fmt(f)
2035 }
2036}
2037
2038impl HirDisplay for LifetimeData {
2039 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2040 match self {
2041 LifetimeData::Placeholder(idx) => {
2042 let id = lt_from_placeholder_idx(f.db, *idx);
2043 let generics = generics(f.db, id.parent);
2044 let param_data = &generics[id.local_id];
2045 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
2046 Ok(())
2047 }
2048 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
2049 LifetimeData::InferenceVar(_) => write!(f, "_"),
2050 LifetimeData::Static => write!(f, "'static"),
2051 LifetimeData::Error => {
2052 if cfg!(test) {
2053 write!(f, "'?")
2054 } else {
2055 write!(f, "'_")
2056 }
2057 }
2058 LifetimeData::Erased => write!(f, "'<erased>"),
2059 LifetimeData::Phantom(void, _) => match *void {},
2060 }
2061 }
2062}
2063
2064impl HirDisplay for DomainGoal {
2065 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2066 match self {
2067 DomainGoal::Holds(wc) => {
2068 write!(f, "Holds(")?;
2069 wc.hir_fmt(f)?;
2070 write!(f, ")")?;
2071 }
2072 _ => write!(f, "_")?,
2073 }
2074 Ok(())
2075 }
2076}
2077
2078pub fn write_visibility(
2079 module_id: ModuleId,
2080 vis: Visibility,
2081 f: &mut HirFormatter<'_>,
2082) -> Result<(), HirDisplayError> {
2083 match vis {
2084 Visibility::Public => write!(f, "pub "),
2085 Visibility::PubCrate(_) => write!(f, "pub(crate) "),
2086 Visibility::Module(vis_id, _) => {
2087 let def_map = module_id.def_map(f.db);
2088 let root_module_id = def_map.module_id(DefMap::ROOT);
2089 if vis_id == module_id {
2090 Ok(())
2092 } else if root_module_id == vis_id {
2093 write!(f, "pub(crate) ")
2094 } else if module_id.containing_module(f.db) == Some(vis_id) {
2095 write!(f, "pub(super) ")
2096 } else {
2097 write!(f, "pub(in ...) ")
2098 }
2099 }
2100 }
2101}
2102
2103pub trait HirDisplayWithExpressionStore {
2104 fn hir_fmt(
2105 &self,
2106 f: &mut HirFormatter<'_>,
2107 store: &ExpressionStore,
2108 ) -> Result<(), HirDisplayError>;
2109}
2110
2111impl<T: ?Sized + HirDisplayWithExpressionStore> HirDisplayWithExpressionStore for &'_ T {
2112 fn hir_fmt(
2113 &self,
2114 f: &mut HirFormatter<'_>,
2115 store: &ExpressionStore,
2116 ) -> Result<(), HirDisplayError> {
2117 T::hir_fmt(&**self, f, store)
2118 }
2119}
2120
2121pub fn hir_display_with_store<'a, T: HirDisplayWithExpressionStore + 'a>(
2122 value: T,
2123 store: &'a ExpressionStore,
2124) -> impl HirDisplay + 'a {
2125 ExpressionStoreAdapter(value, store)
2126}
2127
2128struct ExpressionStoreAdapter<'a, T>(T, &'a ExpressionStore);
2129
2130impl<'a, T> ExpressionStoreAdapter<'a, T> {
2131 fn wrap(store: &'a ExpressionStore) -> impl Fn(T) -> ExpressionStoreAdapter<'a, T> {
2132 move |value| ExpressionStoreAdapter(value, store)
2133 }
2134}
2135
2136impl<T: HirDisplayWithExpressionStore> HirDisplay for ExpressionStoreAdapter<'_, T> {
2137 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2138 T::hir_fmt(&self.0, f, self.1)
2139 }
2140}
2141impl HirDisplayWithExpressionStore for LifetimeRefId {
2142 fn hir_fmt(
2143 &self,
2144 f: &mut HirFormatter<'_>,
2145 store: &ExpressionStore,
2146 ) -> Result<(), HirDisplayError> {
2147 match &store[*self] {
2148 LifetimeRef::Named(name) => write!(f, "{}", name.display(f.db, f.edition())),
2149 LifetimeRef::Static => write!(f, "'static"),
2150 LifetimeRef::Placeholder => write!(f, "'_"),
2151 LifetimeRef::Error => write!(f, "'{{error}}"),
2152 &LifetimeRef::Param(lifetime_param_id) => {
2153 let generic_params = f.db.generic_params(lifetime_param_id.parent);
2154 write!(
2155 f,
2156 "{}",
2157 generic_params[lifetime_param_id.local_id].name.display(f.db, f.edition())
2158 )
2159 }
2160 }
2161 }
2162}
2163
2164impl HirDisplayWithExpressionStore for TypeRefId {
2165 fn hir_fmt(
2166 &self,
2167 f: &mut HirFormatter<'_>,
2168 store: &ExpressionStore,
2169 ) -> Result<(), HirDisplayError> {
2170 match &store[*self] {
2171 TypeRef::Never => write!(f, "!")?,
2172 TypeRef::TypeParam(param) => {
2173 let generic_params = f.db.generic_params(param.parent());
2174 match generic_params[param.local_id()].name() {
2175 Some(name) => write!(f, "{}", name.display(f.db, f.edition()))?,
2176 None => {
2177 write!(f, "impl ")?;
2178 f.write_joined(
2179 generic_params
2180 .where_predicates()
2181 .filter_map(|it| match it {
2182 WherePredicate::TypeBound { target, bound }
2183 | WherePredicate::ForLifetime { lifetimes: _, target, bound }
2184 if matches!(
2185 store[*target],
2186 TypeRef::TypeParam(t) if t == *param
2187 ) =>
2188 {
2189 Some(bound)
2190 }
2191 _ => None,
2192 })
2193 .map(ExpressionStoreAdapter::wrap(store)),
2194 " + ",
2195 )?;
2196 }
2197 }
2198 }
2199 TypeRef::Placeholder => write!(f, "_")?,
2200 TypeRef::Tuple(elems) => {
2201 write!(f, "(")?;
2202 f.write_joined(elems.iter().map(ExpressionStoreAdapter::wrap(store)), ", ")?;
2203 if elems.len() == 1 {
2204 write!(f, ",")?;
2205 }
2206 write!(f, ")")?;
2207 }
2208 TypeRef::Path(path) => path.hir_fmt(f, store)?,
2209 TypeRef::RawPtr(inner, mutability) => {
2210 let mutability = match mutability {
2211 hir_def::type_ref::Mutability::Shared => "*const ",
2212 hir_def::type_ref::Mutability::Mut => "*mut ",
2213 };
2214 write!(f, "{mutability}")?;
2215 inner.hir_fmt(f, store)?;
2216 }
2217 TypeRef::Reference(ref_) => {
2218 let mutability = match ref_.mutability {
2219 hir_def::type_ref::Mutability::Shared => "",
2220 hir_def::type_ref::Mutability::Mut => "mut ",
2221 };
2222 write!(f, "&")?;
2223 if let Some(lifetime) = &ref_.lifetime {
2224 lifetime.hir_fmt(f, store)?;
2225 write!(f, " ")?;
2226 }
2227 write!(f, "{mutability}")?;
2228 ref_.ty.hir_fmt(f, store)?;
2229 }
2230 TypeRef::Array(array) => {
2231 write!(f, "[")?;
2232 array.ty.hir_fmt(f, store)?;
2233 write!(f, "; ")?;
2234 array.len.hir_fmt(f, store)?;
2235 write!(f, "]")?;
2236 }
2237 TypeRef::Slice(inner) => {
2238 write!(f, "[")?;
2239 inner.hir_fmt(f, store)?;
2240 write!(f, "]")?;
2241 }
2242 TypeRef::Fn(fn_) => {
2243 if fn_.is_unsafe {
2244 write!(f, "unsafe ")?;
2245 }
2246 if let Some(abi) = &fn_.abi {
2247 f.write_str("extern \"")?;
2248 f.write_str(abi.as_str())?;
2249 f.write_str("\" ")?;
2250 }
2251 write!(f, "fn(")?;
2252 if let Some(((_, return_type), function_parameters)) = fn_.params.split_last() {
2253 for index in 0..function_parameters.len() {
2254 let (param_name, param_type) = &function_parameters[index];
2255 if let Some(name) = param_name {
2256 write!(f, "{}: ", name.display(f.db, f.edition()))?;
2257 }
2258
2259 param_type.hir_fmt(f, store)?;
2260
2261 if index != function_parameters.len() - 1 {
2262 write!(f, ", ")?;
2263 }
2264 }
2265 if fn_.is_varargs {
2266 write!(f, "{}...", if fn_.params.len() == 1 { "" } else { ", " })?;
2267 }
2268 write!(f, ")")?;
2269 match &store[*return_type] {
2270 TypeRef::Tuple(tup) if tup.is_empty() => {}
2271 _ => {
2272 write!(f, " -> ")?;
2273 return_type.hir_fmt(f, store)?;
2274 }
2275 }
2276 }
2277 }
2278 TypeRef::ImplTrait(bounds) => {
2279 write!(f, "impl ")?;
2280 f.write_joined(bounds.iter().map(ExpressionStoreAdapter::wrap(store)), " + ")?;
2281 }
2282 TypeRef::DynTrait(bounds) => {
2283 write!(f, "dyn ")?;
2284 f.write_joined(bounds.iter().map(ExpressionStoreAdapter::wrap(store)), " + ")?;
2285 }
2286 TypeRef::Error => write!(f, "{{error}}")?,
2287 }
2288 Ok(())
2289 }
2290}
2291
2292impl HirDisplayWithExpressionStore for ConstRef {
2293 fn hir_fmt(
2294 &self,
2295 f: &mut HirFormatter<'_>,
2296 _store: &ExpressionStore,
2297 ) -> Result<(), HirDisplayError> {
2298 write!(f, "{{const}}")?;
2300
2301 Ok(())
2302 }
2303}
2304
2305impl HirDisplayWithExpressionStore for TypeBound {
2306 fn hir_fmt(
2307 &self,
2308 f: &mut HirFormatter<'_>,
2309 store: &ExpressionStore,
2310 ) -> Result<(), HirDisplayError> {
2311 match self {
2312 &TypeBound::Path(path, modifier) => {
2313 match modifier {
2314 TraitBoundModifier::None => (),
2315 TraitBoundModifier::Maybe => write!(f, "?")?,
2316 }
2317 store[path].hir_fmt(f, store)
2318 }
2319 TypeBound::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
2320 TypeBound::ForLifetime(lifetimes, path) => {
2321 let edition = f.edition();
2322 write!(
2323 f,
2324 "for<{}> ",
2325 lifetimes.iter().map(|it| it.display(f.db, edition)).format(", ")
2326 )?;
2327 store[*path].hir_fmt(f, store)
2328 }
2329 TypeBound::Use(args) => {
2330 let edition = f.edition();
2331 let last = args.len().saturating_sub(1);
2332 for (idx, arg) in args.iter().enumerate() {
2333 match arg {
2334 UseArgRef::Lifetime(lt) => lt.hir_fmt(f, store)?,
2335 UseArgRef::Name(n) => write!(f, "{}", n.display(f.db, edition))?,
2336 }
2337 if idx != last {
2338 write!(f, ", ")?;
2339 }
2340 }
2341 write!(f, "> ")
2342 }
2343 TypeBound::Error => write!(f, "{{error}}"),
2344 }
2345 }
2346}
2347
2348impl HirDisplayWithExpressionStore for Path {
2349 fn hir_fmt(
2350 &self,
2351 f: &mut HirFormatter<'_>,
2352 store: &ExpressionStore,
2353 ) -> Result<(), HirDisplayError> {
2354 match (self.type_anchor(), self.kind()) {
2355 (Some(anchor), _) => {
2356 write!(f, "<")?;
2357 anchor.hir_fmt(f, store)?;
2358 write!(f, ">")?;
2359 }
2360 (_, PathKind::Plain) => {}
2361 (_, PathKind::Abs) => {}
2362 (_, PathKind::Crate) => write!(f, "crate")?,
2363 (_, &PathKind::SELF) => write!(f, "self")?,
2364 (_, PathKind::Super(n)) => {
2365 for i in 0..*n {
2366 if i > 0 {
2367 write!(f, "::")?;
2368 }
2369 write!(f, "super")?;
2370 }
2371 }
2372 (_, PathKind::DollarCrate(id)) => {
2373 let crate_data = id.extra_data(f.db);
2377 let name = crate_data
2378 .display_name
2379 .as_ref()
2380 .map(|name| (*name.canonical_name()).clone())
2381 .unwrap_or(sym::dollar_crate);
2382 write!(f, "{name}")?
2383 }
2384 }
2385
2386 let trait_self_ty = self.segments().iter().find_map(|seg| {
2395 let generic_args = seg.args_and_bindings?;
2396 generic_args.has_self_type.then(|| &generic_args.args[0])
2397 });
2398 if let Some(ty) = trait_self_ty {
2399 write!(f, "<")?;
2400 ty.hir_fmt(f, store)?;
2401 write!(f, " as ")?;
2402 }
2404
2405 for (seg_idx, segment) in self.segments().iter().enumerate() {
2406 if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
2407 write!(f, "::")?;
2408 }
2409 write!(f, "{}", segment.name.display(f.db, f.edition()))?;
2410 if let Some(generic_args) = segment.args_and_bindings {
2411 match generic_args.parenthesized {
2414 hir_def::expr_store::path::GenericArgsParentheses::ReturnTypeNotation => {
2415 write!(f, "(..)")?;
2416 }
2417 hir_def::expr_store::path::GenericArgsParentheses::ParenSugar => {
2418 let tuple = match generic_args.args[0] {
2421 hir_def::expr_store::path::GenericArg::Type(ty) => match &store[ty] {
2422 TypeRef::Tuple(it) => Some(it),
2423 _ => None,
2424 },
2425 _ => None,
2426 };
2427 if let Some(v) = tuple {
2428 if v.len() == 1 {
2429 write!(f, "(")?;
2430 v[0].hir_fmt(f, store)?;
2431 write!(f, ")")?;
2432 } else {
2433 generic_args.args[0].hir_fmt(f, store)?;
2434 }
2435 }
2436 if let Some(ret) = generic_args.bindings[0].type_ref {
2437 if !matches!(&store[ret], TypeRef::Tuple(v) if v.is_empty()) {
2438 write!(f, " -> ")?;
2439 ret.hir_fmt(f, store)?;
2440 }
2441 }
2442 }
2443 hir_def::expr_store::path::GenericArgsParentheses::No => {
2444 let mut first = true;
2445 for arg in &generic_args.args[generic_args.has_self_type as usize..] {
2447 if first {
2448 first = false;
2449 write!(f, "<")?;
2450 } else {
2451 write!(f, ", ")?;
2452 }
2453 arg.hir_fmt(f, store)?;
2454 }
2455 for binding in generic_args.bindings.iter() {
2456 if first {
2457 first = false;
2458 write!(f, "<")?;
2459 } else {
2460 write!(f, ", ")?;
2461 }
2462 write!(f, "{}", binding.name.display(f.db, f.edition()))?;
2463 match &binding.type_ref {
2464 Some(ty) => {
2465 write!(f, " = ")?;
2466 ty.hir_fmt(f, store)?
2467 }
2468 None => {
2469 write!(f, ": ")?;
2470 f.write_joined(
2471 binding
2472 .bounds
2473 .iter()
2474 .map(ExpressionStoreAdapter::wrap(store)),
2475 " + ",
2476 )?;
2477 }
2478 }
2479 }
2480
2481 if !first {
2484 write!(f, ">")?;
2485 }
2486
2487 if generic_args.has_self_type {
2489 write!(f, ">")?;
2490 }
2491 }
2492 }
2493 }
2494 }
2495
2496 Ok(())
2497 }
2498}
2499
2500impl HirDisplayWithExpressionStore for hir_def::expr_store::path::GenericArg {
2501 fn hir_fmt(
2502 &self,
2503 f: &mut HirFormatter<'_>,
2504 store: &ExpressionStore,
2505 ) -> Result<(), HirDisplayError> {
2506 match self {
2507 hir_def::expr_store::path::GenericArg::Type(ty) => ty.hir_fmt(f, store),
2508 hir_def::expr_store::path::GenericArg::Const(_c) => {
2509 write!(f, "<expr>")
2511 }
2512 hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
2513 }
2514 }
2515}