• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! The `HirDisplay` trait, which serves two purposes: Turning various bits from
2 //! HIR back into source code, and just displaying them for debugging/testing
3 //! purposes.
4 
5 use std::{
6     fmt::{self, Debug},
7     mem::size_of,
8 };
9 
10 use base_db::CrateId;
11 use chalk_ir::{BoundVar, TyKind};
12 use hir_def::{
13     data::adt::VariantData,
14     db::DefDatabase,
15     find_path,
16     generics::{TypeOrConstParamData, TypeParamProvenance},
17     item_scope::ItemInNs,
18     lang_item::{LangItem, LangItemTarget},
19     nameres::DefMap,
20     path::{Path, PathKind},
21     type_ref::{TraitBoundModifier, TypeBound, TypeRef},
22     visibility::Visibility,
23     EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId,
24     TraitId,
25 };
26 use hir_expand::{hygiene::Hygiene, name::Name};
27 use intern::{Internable, Interned};
28 use itertools::Itertools;
29 use la_arena::ArenaMap;
30 use smallvec::SmallVec;
31 use stdx::never;
32 
33 use crate::{
34     consteval::try_const_usize,
35     db::HirDatabase,
36     from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
37     layout::Layout,
38     lt_from_placeholder_idx,
39     mapping::from_chalk,
40     mir::pad16,
41     primitive, to_assoc_type_id,
42     utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
43     AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
44     DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
45     MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
46     Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
47 };
48 
49 pub trait HirWrite: fmt::Write {
start_location_link(&mut self, location: ModuleDefId)50     fn start_location_link(&mut self, location: ModuleDefId);
end_location_link(&mut self)51     fn end_location_link(&mut self);
52 }
53 
54 // String will ignore link metadata
55 impl HirWrite for String {
start_location_link(&mut self, _: ModuleDefId)56     fn start_location_link(&mut self, _: ModuleDefId) {}
57 
end_location_link(&mut self)58     fn end_location_link(&mut self) {}
59 }
60 
61 // `core::Formatter` will ignore metadata
62 impl HirWrite for fmt::Formatter<'_> {
start_location_link(&mut self, _: ModuleDefId)63     fn start_location_link(&mut self, _: ModuleDefId) {}
end_location_link(&mut self)64     fn end_location_link(&mut self) {}
65 }
66 
67 pub struct HirFormatter<'a> {
68     pub db: &'a dyn HirDatabase,
69     fmt: &'a mut dyn HirWrite,
70     buf: String,
71     curr_size: usize,
72     pub(crate) max_size: Option<usize>,
73     omit_verbose_types: bool,
74     closure_style: ClosureStyle,
75     display_target: DisplayTarget,
76 }
77 
78 impl HirFormatter<'_> {
start_location_link(&mut self, location: ModuleDefId)79     fn start_location_link(&mut self, location: ModuleDefId) {
80         self.fmt.start_location_link(location);
81     }
82 
end_location_link(&mut self)83     fn end_location_link(&mut self) {
84         self.fmt.end_location_link();
85     }
86 }
87 
88 pub trait HirDisplay {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>89     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
90 
91     /// Returns a `Display`able type that is human-readable.
into_displayable<'a>( &'a self, db: &'a dyn HirDatabase, max_size: Option<usize>, omit_verbose_types: bool, display_target: DisplayTarget, closure_style: ClosureStyle, ) -> HirDisplayWrapper<'a, Self> where Self: Sized,92     fn into_displayable<'a>(
93         &'a self,
94         db: &'a dyn HirDatabase,
95         max_size: Option<usize>,
96         omit_verbose_types: bool,
97         display_target: DisplayTarget,
98         closure_style: ClosureStyle,
99     ) -> HirDisplayWrapper<'a, Self>
100     where
101         Self: Sized,
102     {
103         assert!(
104             !matches!(display_target, DisplayTarget::SourceCode { .. }),
105             "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
106         );
107         HirDisplayWrapper {
108             db,
109             t: self,
110             max_size,
111             omit_verbose_types,
112             display_target,
113             closure_style,
114         }
115     }
116 
117     /// Returns a `Display`able type that is human-readable.
118     /// Use this for showing types to the user (e.g. diagnostics)
display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> where Self: Sized,119     fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
120     where
121         Self: Sized,
122     {
123         HirDisplayWrapper {
124             db,
125             t: self,
126             max_size: None,
127             omit_verbose_types: false,
128             closure_style: ClosureStyle::ImplFn,
129             display_target: DisplayTarget::Diagnostics,
130         }
131     }
132 
133     /// Returns a `Display`able type that is human-readable and tries to be succinct.
134     /// Use this for showing types to the user where space is constrained (e.g. doc popups)
display_truncated<'a>( &'a self, db: &'a dyn HirDatabase, max_size: Option<usize>, ) -> HirDisplayWrapper<'a, Self> where Self: Sized,135     fn display_truncated<'a>(
136         &'a self,
137         db: &'a dyn HirDatabase,
138         max_size: Option<usize>,
139     ) -> HirDisplayWrapper<'a, Self>
140     where
141         Self: Sized,
142     {
143         HirDisplayWrapper {
144             db,
145             t: self,
146             max_size,
147             omit_verbose_types: true,
148             closure_style: ClosureStyle::ImplFn,
149             display_target: DisplayTarget::Diagnostics,
150         }
151     }
152 
153     /// Returns a String representation of `self` that can be inserted into the given module.
154     /// Use this when generating code (e.g. assists)
display_source_code<'a>( &'a self, db: &'a dyn HirDatabase, module_id: ModuleId, allow_opaque: bool, ) -> Result<String, DisplaySourceCodeError>155     fn display_source_code<'a>(
156         &'a self,
157         db: &'a dyn HirDatabase,
158         module_id: ModuleId,
159         allow_opaque: bool,
160     ) -> Result<String, DisplaySourceCodeError> {
161         let mut result = String::new();
162         match self.hir_fmt(&mut HirFormatter {
163             db,
164             fmt: &mut result,
165             buf: String::with_capacity(20),
166             curr_size: 0,
167             max_size: None,
168             omit_verbose_types: false,
169             closure_style: ClosureStyle::ImplFn,
170             display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
171         }) {
172             Ok(()) => {}
173             Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
174             Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
175         };
176         Ok(result)
177     }
178 
179     /// Returns a String representation of `self` for test purposes
display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> where Self: Sized,180     fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
181     where
182         Self: Sized,
183     {
184         HirDisplayWrapper {
185             db,
186             t: self,
187             max_size: None,
188             omit_verbose_types: false,
189             closure_style: ClosureStyle::ImplFn,
190             display_target: DisplayTarget::Test,
191         }
192     }
193 }
194 
195 impl<'a> HirFormatter<'a> {
write_joined<T: HirDisplay>( &mut self, iter: impl IntoIterator<Item = T>, sep: &str, ) -> Result<(), HirDisplayError>196     pub fn write_joined<T: HirDisplay>(
197         &mut self,
198         iter: impl IntoIterator<Item = T>,
199         sep: &str,
200     ) -> Result<(), HirDisplayError> {
201         let mut first = true;
202         for e in iter {
203             if !first {
204                 write!(self, "{sep}")?;
205             }
206             first = false;
207 
208             // Abbreviate multiple omitted types with a single ellipsis.
209             if self.should_truncate() {
210                 return write!(self, "{TYPE_HINT_TRUNCATION}");
211             }
212 
213             e.hir_fmt(self)?;
214         }
215         Ok(())
216     }
217 
218     /// This allows using the `write!` macro directly with a `HirFormatter`.
write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError>219     pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> {
220         // We write to a buffer first to track output size
221         self.buf.clear();
222         fmt::write(&mut self.buf, args)?;
223         self.curr_size += self.buf.len();
224 
225         // Then we write to the internal formatter from the buffer
226         self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
227     }
228 
write_str(&mut self, s: &str) -> Result<(), HirDisplayError>229     pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> {
230         self.fmt.write_str(s)?;
231         Ok(())
232     }
233 
write_char(&mut self, c: char) -> Result<(), HirDisplayError>234     pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> {
235         self.fmt.write_char(c)?;
236         Ok(())
237     }
238 
should_truncate(&self) -> bool239     pub fn should_truncate(&self) -> bool {
240         match self.max_size {
241             Some(max_size) => self.curr_size >= max_size,
242             None => false,
243         }
244     }
245 
omit_verbose_types(&self) -> bool246     pub fn omit_verbose_types(&self) -> bool {
247         self.omit_verbose_types
248     }
249 }
250 
251 #[derive(Clone, Copy)]
252 pub enum DisplayTarget {
253     /// Display types for inlays, doc popups, autocompletion, etc...
254     /// Showing `{unknown}` or not qualifying paths is fine here.
255     /// There's no reason for this to fail.
256     Diagnostics,
257     /// Display types for inserting them in source files.
258     /// The generated code should compile, so paths need to be qualified.
259     SourceCode { module_id: ModuleId, allow_opaque: bool },
260     /// Only for test purpose to keep real types
261     Test,
262 }
263 
264 impl DisplayTarget {
is_source_code(self) -> bool265     fn is_source_code(self) -> bool {
266         matches!(self, Self::SourceCode { .. })
267     }
268 
is_test(self) -> bool269     fn is_test(self) -> bool {
270         matches!(self, Self::Test)
271     }
272 
allows_opaque(self) -> bool273     fn allows_opaque(self) -> bool {
274         match self {
275             Self::SourceCode { allow_opaque, .. } => allow_opaque,
276             _ => true,
277         }
278     }
279 }
280 
281 #[derive(Debug)]
282 pub enum DisplaySourceCodeError {
283     PathNotFound,
284     UnknownType,
285     Generator,
286     OpaqueType,
287 }
288 
289 pub enum HirDisplayError {
290     /// Errors that can occur when generating source code
291     DisplaySourceCodeError(DisplaySourceCodeError),
292     /// `FmtError` is required to be compatible with std::fmt::Display
293     FmtError,
294 }
295 impl From<fmt::Error> for HirDisplayError {
from(_: fmt::Error) -> Self296     fn from(_: fmt::Error) -> Self {
297         Self::FmtError
298     }
299 }
300 
301 pub struct HirDisplayWrapper<'a, T> {
302     db: &'a dyn HirDatabase,
303     t: &'a T,
304     max_size: Option<usize>,
305     omit_verbose_types: bool,
306     closure_style: ClosureStyle,
307     display_target: DisplayTarget,
308 }
309 
310 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
311 pub enum ClosureStyle {
312     /// `impl FnX(i32, i32) -> i32`, where `FnX` is the most special trait between `Fn`, `FnMut`, `FnOnce` that the
313     /// closure implements. This is the default.
314     ImplFn,
315     /// `|i32, i32| -> i32`
316     RANotation,
317     /// `{closure#14825}`, useful for some diagnostics (like type mismatch) and internal usage.
318     ClosureWithId,
319     /// `{closure#14825}<i32, ()>`, useful for internal usage.
320     ClosureWithSubst,
321     /// `…`, which is the `TYPE_HINT_TRUNCATION`
322     Hide,
323 }
324 
325 impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError>326     pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
327         self.t.hir_fmt(&mut HirFormatter {
328             db: self.db,
329             fmt: f,
330             buf: String::with_capacity(20),
331             curr_size: 0,
332             max_size: self.max_size,
333             omit_verbose_types: self.omit_verbose_types,
334             display_target: self.display_target,
335             closure_style: self.closure_style,
336         })
337     }
338 
with_closure_style(mut self, c: ClosureStyle) -> Self339     pub fn with_closure_style(mut self, c: ClosureStyle) -> Self {
340         self.closure_style = c;
341         self
342     }
343 }
344 
345 impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
346 where
347     T: HirDisplay,
348 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result349     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350         match self.write_to(f) {
351             Ok(()) => Ok(()),
352             Err(HirDisplayError::FmtError) => Err(fmt::Error),
353             Err(HirDisplayError::DisplaySourceCodeError(_)) => {
354                 // This should never happen
355                 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
356             }
357         }
358     }
359 }
360 
361 const TYPE_HINT_TRUNCATION: &str = "…";
362 
363 impl<T: HirDisplay> HirDisplay for &'_ T {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>364     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
365         HirDisplay::hir_fmt(*self, f)
366     }
367 }
368 
369 impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>370     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
371         HirDisplay::hir_fmt(self.as_ref(), f)
372     }
373 }
374 
375 impl HirDisplay for ProjectionTy {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>376     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
377         if f.should_truncate() {
378             return write!(f, "{TYPE_HINT_TRUNCATION}");
379         }
380 
381         let trait_ref = self.trait_ref(f.db);
382         write!(f, "<")?;
383         fmt_trait_ref(f, &trait_ref, true)?;
384         write!(
385             f,
386             ">::{}",
387             f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id))
388                 .name
389                 .display(f.db.upcast())
390         )?;
391         let proj_params_count =
392             self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
393         let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
394         if !proj_params.is_empty() {
395             write!(f, "<")?;
396             f.write_joined(proj_params, ", ")?;
397             write!(f, ">")?;
398         }
399         Ok(())
400     }
401 }
402 
403 impl HirDisplay for OpaqueTy {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>404     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
405         if f.should_truncate() {
406             return write!(f, "{TYPE_HINT_TRUNCATION}");
407         }
408 
409         self.substitution.at(Interner, 0).hir_fmt(f)
410     }
411 }
412 
413 impl HirDisplay for GenericArg {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>414     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
415         match self.interned() {
416             crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
417             crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
418             crate::GenericArgData::Const(c) => c.hir_fmt(f),
419         }
420     }
421 }
422 
423 impl HirDisplay for Const {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>424     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
425         let data = self.interned();
426         match &data.value {
427             ConstValue::BoundVar(idx) => idx.hir_fmt(f),
428             ConstValue::InferenceVar(..) => write!(f, "#c#"),
429             ConstValue::Placeholder(idx) => {
430                 let id = from_placeholder_idx(f.db, *idx);
431                 let generics = generics(f.db.upcast(), id.parent);
432                 let param_data = &generics.params.type_or_consts[id.local_id];
433                 write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?;
434                 Ok(())
435             }
436             ConstValue::Concrete(c) => match &c.interned {
437                 ConstScalar::Bytes(b, m) => render_const_scalar(f, &b, m, &data.ty),
438                 ConstScalar::UnevaluatedConst(c, parameters) => {
439                     write!(f, "{}", c.name(f.db.upcast()))?;
440                     hir_fmt_generics(f, parameters, c.generic_def(f.db.upcast()))?;
441                     Ok(())
442                 }
443                 ConstScalar::Unknown => f.write_char('_'),
444             },
445         }
446     }
447 }
448 
449 pub struct HexifiedConst(pub Const);
450 
451 impl HirDisplay for HexifiedConst {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>452     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
453         let data = &self.0.data(Interner);
454         if let TyKind::Scalar(s) = data.ty.kind(Interner) {
455             if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
456                 if let ConstValue::Concrete(c) = &data.value {
457                     if let ConstScalar::Bytes(b, m) = &c.interned {
458                         let value = u128::from_le_bytes(pad16(b, false));
459                         if value >= 10 {
460                             render_const_scalar(f, &b, m, &data.ty)?;
461                             return write!(f, " ({:#X})", value);
462                         }
463                     }
464                 }
465             }
466         }
467         self.0.hir_fmt(f)
468     }
469 }
470 
render_const_scalar( f: &mut HirFormatter<'_>, b: &[u8], memory_map: &MemoryMap, ty: &Ty, ) -> Result<(), HirDisplayError>471 fn render_const_scalar(
472     f: &mut HirFormatter<'_>,
473     b: &[u8],
474     memory_map: &MemoryMap,
475     ty: &Ty,
476 ) -> Result<(), HirDisplayError> {
477     // FIXME: We need to get krate from the final callers of the hir display
478     // infrastructure and have it here as a field on `f`.
479     let krate = *f.db.crate_graph().crates_in_topological_order().last().unwrap();
480     match ty.kind(Interner) {
481         TyKind::Scalar(s) => match s {
482             Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
483             Scalar::Char => {
484                 let x = u128::from_le_bytes(pad16(b, false)) as u32;
485                 let Ok(c) = char::try_from(x) else {
486                     return f.write_str("<unicode-error>");
487                 };
488                 write!(f, "{c:?}")
489             }
490             Scalar::Int(_) => {
491                 let x = i128::from_le_bytes(pad16(b, true));
492                 write!(f, "{x}")
493             }
494             Scalar::Uint(_) => {
495                 let x = u128::from_le_bytes(pad16(b, false));
496                 write!(f, "{x}")
497             }
498             Scalar::Float(fl) => match fl {
499                 chalk_ir::FloatTy::F32 => {
500                     let x = f32::from_le_bytes(b.try_into().unwrap());
501                     write!(f, "{x:?}")
502                 }
503                 chalk_ir::FloatTy::F64 => {
504                     let x = f64::from_le_bytes(b.try_into().unwrap());
505                     write!(f, "{x:?}")
506                 }
507             },
508         },
509         TyKind::Ref(_, _, t) => match t.kind(Interner) {
510             TyKind::Str => {
511                 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
512                 let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
513                 let Some(bytes) = memory_map.get(addr, size) else {
514                     return f.write_str("<ref-data-not-available>");
515                 };
516                 let s = std::str::from_utf8(&bytes).unwrap_or("<utf8-error>");
517                 write!(f, "{s:?}")
518             }
519             TyKind::Slice(ty) => {
520                 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
521                 let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
522                 let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
523                     return f.write_str("<layout-error>");
524                 };
525                 let size_one = layout.size.bytes_usize();
526                 let Some(bytes) = memory_map.get(addr, size_one * count) else {
527                     return f.write_str("<ref-data-not-available>");
528                 };
529                 f.write_str("&[")?;
530                 let mut first = true;
531                 for i in 0..count {
532                     if first {
533                         first = false;
534                     } else {
535                         f.write_str(", ")?;
536                     }
537                     let offset = size_one * i;
538                     render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, &ty)?;
539                 }
540                 f.write_str("]")
541             }
542             TyKind::Dyn(_) => {
543                 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
544                 let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
545                 let Ok(t) = memory_map.vtable.ty(ty_id) else {
546                     return f.write_str("<ty-missing-in-vtable-map>");
547                 };
548                 let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
549                     return f.write_str("<layout-error>");
550                 };
551                 let size = layout.size.bytes_usize();
552                 let Some(bytes) = memory_map.get(addr, size) else {
553                     return f.write_str("<ref-data-not-available>");
554                 };
555                 f.write_str("&")?;
556                 render_const_scalar(f, bytes, memory_map, t)
557             }
558             TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.0 {
559                 hir_def::AdtId::StructId(s) => {
560                     let data = f.db.struct_data(s);
561                     write!(f, "&{}", data.name.display(f.db.upcast()))?;
562                     Ok(())
563                 }
564                 _ => {
565                     return f.write_str("<unsized-enum-or-union>");
566                 }
567             },
568             _ => {
569                 let addr = usize::from_le_bytes(match b.try_into() {
570                     Ok(b) => b,
571                     Err(_) => {
572                         never!(
573                             "tried rendering ty {:?} in const ref with incorrect byte count {}",
574                             t,
575                             b.len()
576                         );
577                         return f.write_str("<layout-error>");
578                     }
579                 });
580                 let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
581                     return f.write_str("<layout-error>");
582                 };
583                 let size = layout.size.bytes_usize();
584                 let Some(bytes) = memory_map.get(addr, size) else {
585                     return f.write_str("<ref-data-not-available>");
586                 };
587                 f.write_str("&")?;
588                 render_const_scalar(f, bytes, memory_map, t)
589             }
590         },
591         TyKind::Tuple(_, subst) => {
592             let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
593                 return f.write_str("<layout-error>");
594             };
595             f.write_str("(")?;
596             let mut first = true;
597             for (id, ty) in subst.iter(Interner).enumerate() {
598                 if first {
599                     first = false;
600                 } else {
601                     f.write_str(", ")?;
602                 }
603                 let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
604                 let offset = layout.fields.offset(id).bytes_usize();
605                 let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
606                     f.write_str("<layout-error>")?;
607                     continue;
608                 };
609                 let size = layout.size.bytes_usize();
610                 render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)?;
611             }
612             f.write_str(")")
613         }
614         TyKind::Adt(adt, subst) => {
615             let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), krate) else {
616                 return f.write_str("<layout-error>");
617             };
618             match adt.0 {
619                 hir_def::AdtId::StructId(s) => {
620                     let data = f.db.struct_data(s);
621                     write!(f, "{}", data.name.display(f.db.upcast()))?;
622                     let field_types = f.db.field_types(s.into());
623                     render_variant_after_name(
624                         &data.variant_data,
625                         f,
626                         &field_types,
627                         adt.0.module(f.db.upcast()).krate(),
628                         &layout,
629                         subst,
630                         b,
631                         memory_map,
632                     )
633                 }
634                 hir_def::AdtId::UnionId(u) => {
635                     write!(f, "{}", f.db.union_data(u).name.display(f.db.upcast()))
636                 }
637                 hir_def::AdtId::EnumId(e) => {
638                     let Some((var_id, var_layout)) =
639                             detect_variant_from_bytes(&layout, f.db, krate, b, e) else {
640                         return f.write_str("<failed-to-detect-variant>");
641                     };
642                     let data = &f.db.enum_data(e).variants[var_id];
643                     write!(f, "{}", data.name.display(f.db.upcast()))?;
644                     let field_types =
645                         f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into());
646                     render_variant_after_name(
647                         &data.variant_data,
648                         f,
649                         &field_types,
650                         adt.0.module(f.db.upcast()).krate(),
651                         &var_layout,
652                         subst,
653                         b,
654                         memory_map,
655                     )
656                 }
657             }
658         }
659         TyKind::FnDef(..) => ty.hir_fmt(f),
660         TyKind::Function(_) | TyKind::Raw(_, _) => {
661             let x = u128::from_le_bytes(pad16(b, false));
662             write!(f, "{:#X} as ", x)?;
663             ty.hir_fmt(f)
664         }
665         TyKind::Array(ty, len) => {
666             let Some(len) = try_const_usize(f.db, len) else {
667                 return f.write_str("<unknown-array-len>");
668             };
669             let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
670                 return f.write_str("<layout-error>");
671             };
672             let size_one = layout.size.bytes_usize();
673             f.write_str("[")?;
674             let mut first = true;
675             for i in 0..len as usize {
676                 if first {
677                     first = false;
678                 } else {
679                     f.write_str(", ")?;
680                 }
681                 let offset = size_one * i;
682                 render_const_scalar(f, &b[offset..offset + size_one], memory_map, &ty)?;
683             }
684             f.write_str("]")
685         }
686         TyKind::Never => f.write_str("!"),
687         TyKind::Closure(_, _) => f.write_str("<closure>"),
688         TyKind::Generator(_, _) => f.write_str("<generator>"),
689         TyKind::GeneratorWitness(_, _) => f.write_str("<generator-witness>"),
690         // The below arms are unreachable, since const eval will bail out before here.
691         TyKind::Foreign(_) => f.write_str("<extern-type>"),
692         TyKind::Error
693         | TyKind::Placeholder(_)
694         | TyKind::Alias(_)
695         | TyKind::AssociatedType(_, _)
696         | TyKind::OpaqueType(_, _)
697         | TyKind::BoundVar(_)
698         | TyKind::InferenceVar(_, _) => f.write_str("<placeholder-or-unknown-type>"),
699         // The below arms are unreachable, since we handled them in ref case.
700         TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => f.write_str("<unsized-value>"),
701     }
702 }
703 
render_variant_after_name( data: &VariantData, f: &mut HirFormatter<'_>, field_types: &ArenaMap<LocalFieldId, Binders<Ty>>, krate: CrateId, layout: &Layout, subst: &Substitution, b: &[u8], memory_map: &MemoryMap, ) -> Result<(), HirDisplayError>704 fn render_variant_after_name(
705     data: &VariantData,
706     f: &mut HirFormatter<'_>,
707     field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
708     krate: CrateId,
709     layout: &Layout,
710     subst: &Substitution,
711     b: &[u8],
712     memory_map: &MemoryMap,
713 ) -> Result<(), HirDisplayError> {
714     match data {
715         VariantData::Record(fields) | VariantData::Tuple(fields) => {
716             let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
717                 let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
718                 let ty = field_types[id].clone().substitute(Interner, subst);
719                 let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
720                     return f.write_str("<layout-error>");
721                 };
722                 let size = layout.size.bytes_usize();
723                 render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)
724             };
725             let mut it = fields.iter();
726             if matches!(data, VariantData::Record(_)) {
727                 write!(f, " {{")?;
728                 if let Some((id, data)) = it.next() {
729                     write!(f, " {}: ", data.name.display(f.db.upcast()))?;
730                     render_field(f, id)?;
731                 }
732                 for (id, data) in it {
733                     write!(f, ", {}: ", data.name.display(f.db.upcast()))?;
734                     render_field(f, id)?;
735                 }
736                 write!(f, " }}")?;
737             } else {
738                 let mut it = it.map(|x| x.0);
739                 write!(f, "(")?;
740                 if let Some(id) = it.next() {
741                     render_field(f, id)?;
742                 }
743                 for id in it {
744                     write!(f, ", ")?;
745                     render_field(f, id)?;
746                 }
747                 write!(f, ")")?;
748             }
749             return Ok(());
750         }
751         VariantData::Unit => Ok(()),
752     }
753 }
754 
755 impl HirDisplay for BoundVar {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>756     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
757         write!(f, "?{}.{}", self.debruijn.depth(), self.index)
758     }
759 }
760 
761 impl HirDisplay for Ty {
762     fn hir_fmt(
763         &self,
764         f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
765     ) -> Result<(), HirDisplayError> {
766         if f.should_truncate() {
767             return write!(f, "{TYPE_HINT_TRUNCATION}");
768         }
769 
770         match self.kind(Interner) {
771             TyKind::Never => write!(f, "!")?,
772             TyKind::Str => write!(f, "str")?,
773             TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
774             TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
775             &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
776             &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
777             &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
778             TyKind::Slice(t) => {
779                 write!(f, "[")?;
780                 t.hir_fmt(f)?;
781                 write!(f, "]")?;
782             }
783             TyKind::Array(t, c) => {
784                 write!(f, "[")?;
785                 t.hir_fmt(f)?;
786                 write!(f, "; ")?;
787                 c.hir_fmt(f)?;
788                 write!(f, "]")?;
789             }
790             TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
791                 if matches!(self.kind(Interner), TyKind::Raw(..)) {
792                     write!(
793                         f,
794                         "*{}",
795                         match m {
796                             Mutability::Not => "const ",
797                             Mutability::Mut => "mut ",
798                         }
799                     )?;
800                 } else {
801                     write!(
802                         f,
803                         "&{}",
804                         match m {
805                             Mutability::Not => "",
806                             Mutability::Mut => "mut ",
807                         }
808                     )?;
809                 }
810 
811                 // FIXME: all this just to decide whether to use parentheses...
812                 let contains_impl_fn = |bounds: &[QuantifiedWhereClause]| {
813                     bounds.iter().any(|bound| {
814                         if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
815                             let trait_ = trait_ref.hir_trait_id();
816                             fn_traits(db.upcast(), trait_).any(|it| it == trait_)
817                         } else {
818                             false
819                         }
820                     })
821                 };
822                 let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
823                     TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
824                         let bounds = dyn_ty.bounds.skip_binders().interned();
825                         (bounds.len(), contains_impl_fn(bounds))
826                     }
827                     TyKind::Alias(AliasTy::Opaque(OpaqueTy {
828                         opaque_ty_id,
829                         substitution: parameters,
830                     }))
831                     | TyKind::OpaqueType(opaque_ty_id, parameters) => {
832                         let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
833                         if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
834                             let datas = db
835                                 .return_type_impl_traits(func)
836                                 .expect("impl trait id without data");
837                             let data =
838                                 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
839                             let bounds = data.substitute(Interner, parameters);
840                             let mut len = bounds.skip_binders().len();
841 
842                             // Don't count Sized but count when it absent
843                             // (i.e. when explicit ?Sized bound is set).
844                             let default_sized = SizedByDefault::Sized {
845                                 anchor: func.lookup(db.upcast()).module(db.upcast()).krate(),
846                             };
847                             let sized_bounds = bounds
848                                 .skip_binders()
849                                 .iter()
850                                 .filter(|b| {
851                                     matches!(
852                                         b.skip_binders(),
853                                         WhereClause::Implemented(trait_ref)
854                                             if default_sized.is_sized_trait(
855                                                 trait_ref.hir_trait_id(),
856                                                 db.upcast(),
857                                             ),
858                                     )
859                                 })
860                                 .count();
861                             match sized_bounds {
862                                 0 => len += 1,
863                                 _ => {
864                                     len = len.saturating_sub(sized_bounds);
865                                 }
866                             }
867 
868                             (len, contains_impl_fn(bounds.skip_binders()))
869                         } else {
870                             (0, false)
871                         }
872                     }
873                     _ => (0, false),
874                 };
875 
876                 if has_impl_fn_pred && preds_to_print <= 2 {
877                     return t.hir_fmt(f);
878                 }
879 
880                 if preds_to_print > 1 {
881                     write!(f, "(")?;
882                     t.hir_fmt(f)?;
883                     write!(f, ")")?;
884                 } else {
885                     t.hir_fmt(f)?;
886                 }
887             }
888             TyKind::Tuple(_, substs) => {
889                 if substs.len(Interner) == 1 {
890                     write!(f, "(")?;
891                     substs.at(Interner, 0).hir_fmt(f)?;
892                     write!(f, ",)")?;
893                 } else {
894                     write!(f, "(")?;
895                     f.write_joined(&*substs.as_slice(Interner), ", ")?;
896                     write!(f, ")")?;
897                 }
898             }
899             TyKind::Function(fn_ptr) => {
900                 let sig = CallableSig::from_fn_ptr(fn_ptr);
901                 sig.hir_fmt(f)?;
902             }
903             TyKind::FnDef(def, parameters) => {
904                 let def = from_chalk(db, *def);
905                 let sig = db.callable_item_signature(def).substitute(Interner, parameters);
906                 f.start_location_link(def.into());
907                 match def {
908                     CallableDefId::FunctionId(ff) => {
909                         write!(f, "fn {}", db.function_data(ff).name.display(f.db.upcast()))?
910                     }
911                     CallableDefId::StructId(s) => {
912                         write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
913                     }
914                     CallableDefId::EnumVariantId(e) => write!(
915                         f,
916                         "{}",
917                         db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast())
918                     )?,
919                 };
920                 f.end_location_link();
921                 if parameters.len(Interner) > 0 {
922                     let generics = generics(db.upcast(), def.into());
923                     let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
924                         generics.provenance_split();
925                     let total_len = parent_params + self_param + type_params + const_params;
926                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
927                     if total_len > 0 {
928                         // `parameters` are in the order of fn's params (including impl traits),
929                         // parent's params (those from enclosing impl or trait, if any).
930                         let parameters = parameters.as_slice(Interner);
931                         let fn_params_len = self_param + type_params + const_params;
932                         let fn_params = parameters.get(..fn_params_len);
933                         let parent_params = parameters.get(parameters.len() - parent_params..);
934                         let params = parent_params.into_iter().chain(fn_params).flatten();
935                         write!(f, "<")?;
936                         f.write_joined(params, ", ")?;
937                         write!(f, ">")?;
938                     }
939                 }
940                 write!(f, "(")?;
941                 f.write_joined(sig.params(), ", ")?;
942                 write!(f, ")")?;
943                 let ret = sig.ret();
944                 if !ret.is_unit() {
945                     write!(f, " -> ")?;
946                     ret.hir_fmt(f)?;
947                 }
948             }
949             TyKind::Adt(AdtId(def_id), parameters) => {
950                 f.start_location_link((*def_id).into());
951                 match f.display_target {
952                     DisplayTarget::Diagnostics | DisplayTarget::Test => {
953                         let name = match *def_id {
954                             hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(),
955                             hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(),
956                             hir_def::AdtId::EnumId(it) => db.enum_data(it).name.clone(),
957                         };
958                         write!(f, "{}", name.display(f.db.upcast()))?;
959                     }
960                     DisplayTarget::SourceCode { module_id, allow_opaque: _ } => {
961                         if let Some(path) = find_path::find_path(
962                             db.upcast(),
963                             ItemInNs::Types((*def_id).into()),
964                             module_id,
965                             false,
966                         ) {
967                             write!(f, "{}", path.display(f.db.upcast()))?;
968                         } else {
969                             return Err(HirDisplayError::DisplaySourceCodeError(
970                                 DisplaySourceCodeError::PathNotFound,
971                             ));
972                         }
973                     }
974                 }
975                 f.end_location_link();
976 
977                 let generic_def = self.as_generic_def(db);
978 
979                 hir_fmt_generics(f, parameters, generic_def)?;
980             }
981             TyKind::AssociatedType(assoc_type_id, parameters) => {
982                 let type_alias = from_assoc_type_id(*assoc_type_id);
983                 let trait_ = match type_alias.lookup(db.upcast()).container {
984                     ItemContainerId::TraitId(it) => it,
985                     _ => panic!("not an associated type"),
986                 };
987                 let trait_data = db.trait_data(trait_);
988                 let type_alias_data = db.type_alias_data(type_alias);
989 
990                 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
991                 if f.display_target.is_test() {
992                     f.start_location_link(trait_.into());
993                     write!(f, "{}", trait_data.name.display(f.db.upcast()))?;
994                     f.end_location_link();
995                     write!(f, "::")?;
996 
997                     f.start_location_link(type_alias.into());
998                     write!(f, "{}", type_alias_data.name.display(f.db.upcast()))?;
999                     f.end_location_link();
1000                     // Note that the generic args for the associated type come before those for the
1001                     // trait (including the self type).
1002                     // FIXME: reconsider the generic args order upon formatting?
1003                     if parameters.len(Interner) > 0 {
1004                         write!(f, "<")?;
1005                         f.write_joined(parameters.as_slice(Interner), ", ")?;
1006                         write!(f, ">")?;
1007                     }
1008                 } else {
1009                     let projection_ty = ProjectionTy {
1010                         associated_ty_id: to_assoc_type_id(type_alias),
1011                         substitution: parameters.clone(),
1012                     };
1013 
1014                     projection_ty.hir_fmt(f)?;
1015                 }
1016             }
1017             TyKind::Foreign(type_alias) => {
1018                 let alias = from_foreign_def_id(*type_alias);
1019                 let type_alias = db.type_alias_data(alias);
1020                 f.start_location_link(alias.into());
1021                 write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
1022                 f.end_location_link();
1023             }
1024             TyKind::OpaqueType(opaque_ty_id, parameters) => {
1025                 if !f.display_target.allows_opaque() {
1026                     return Err(HirDisplayError::DisplaySourceCodeError(
1027                         DisplaySourceCodeError::OpaqueType,
1028                     ));
1029                 }
1030                 let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
1031                 match impl_trait_id {
1032                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1033                         let datas =
1034                             db.return_type_impl_traits(func).expect("impl trait id without data");
1035                         let data =
1036                             (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1037                         let bounds = data.substitute(Interner, &parameters);
1038                         let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
1039                         write_bounds_like_dyn_trait_with_prefix(
1040                             f,
1041                             "impl",
1042                             bounds.skip_binders(),
1043                             SizedByDefault::Sized { anchor: krate },
1044                         )?;
1045                         // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
1046                     }
1047                     ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
1048                         let future_trait = db
1049                             .lang_item(body.module(db.upcast()).krate(), LangItem::Future)
1050                             .and_then(LangItemTarget::as_trait);
1051                         let output = future_trait.and_then(|t| {
1052                             db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output))
1053                         });
1054                         write!(f, "impl ")?;
1055                         if let Some(t) = future_trait {
1056                             f.start_location_link(t.into());
1057                         }
1058                         write!(f, "Future")?;
1059                         if let Some(_) = future_trait {
1060                             f.end_location_link();
1061                         }
1062                         write!(f, "<")?;
1063                         if let Some(t) = output {
1064                             f.start_location_link(t.into());
1065                         }
1066                         write!(f, "Output")?;
1067                         if let Some(_) = output {
1068                             f.end_location_link();
1069                         }
1070                         write!(f, " = ")?;
1071                         parameters.at(Interner, 0).hir_fmt(f)?;
1072                         write!(f, ">")?;
1073                     }
1074                 }
1075             }
1076             TyKind::Closure(id, substs) => {
1077                 if f.display_target.is_source_code() {
1078                     if !f.display_target.allows_opaque() {
1079                         return Err(HirDisplayError::DisplaySourceCodeError(
1080                             DisplaySourceCodeError::OpaqueType,
1081                         ));
1082                     } else if f.closure_style != ClosureStyle::ImplFn {
1083                         never!("Only `impl Fn` is valid for displaying closures in source code");
1084                     }
1085                 }
1086                 match f.closure_style {
1087                     ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
1088                     ClosureStyle::ClosureWithId => {
1089                         return write!(f, "{{closure#{:?}}}", id.0.as_u32())
1090                     }
1091                     ClosureStyle::ClosureWithSubst => {
1092                         write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
1093                         return hir_fmt_generics(f, substs, None);
1094                     }
1095                     _ => (),
1096                 }
1097                 let sig = ClosureSubst(substs).sig_ty().callable_sig(db);
1098                 if let Some(sig) = sig {
1099                     let (def, _) = db.lookup_intern_closure((*id).into());
1100                     let infer = db.infer(def);
1101                     let (_, kind) = infer.closure_info(id);
1102                     match f.closure_style {
1103                         ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
1104                         ClosureStyle::RANotation => write!(f, "|")?,
1105                         _ => unreachable!(),
1106                     }
1107                     if sig.params().is_empty() {
1108                     } else if f.should_truncate() {
1109                         write!(f, "{TYPE_HINT_TRUNCATION}")?;
1110                     } else {
1111                         f.write_joined(sig.params(), ", ")?;
1112                     };
1113                     match f.closure_style {
1114                         ClosureStyle::ImplFn => write!(f, ")")?,
1115                         ClosureStyle::RANotation => write!(f, "|")?,
1116                         _ => unreachable!(),
1117                     }
1118                     if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() {
1119                         write!(f, " -> ")?;
1120                         sig.ret().hir_fmt(f)?;
1121                     }
1122                 } else {
1123                     write!(f, "{{closure}}")?;
1124                 }
1125             }
1126             TyKind::Placeholder(idx) => {
1127                 let id = from_placeholder_idx(db, *idx);
1128                 let generics = generics(db.upcast(), id.parent);
1129                 let param_data = &generics.params.type_or_consts[id.local_id];
1130                 match param_data {
1131                     TypeOrConstParamData::TypeParamData(p) => match p.provenance {
1132                         TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
1133                             write!(
1134                                 f,
1135                                 "{}",
1136                                 p.name.clone().unwrap_or_else(Name::missing).display(f.db.upcast())
1137                             )?
1138                         }
1139                         TypeParamProvenance::ArgumentImplTrait => {
1140                             let substs = generics.placeholder_subst(db);
1141                             let bounds = db
1142                                 .generic_predicates(id.parent)
1143                                 .iter()
1144                                 .map(|pred| pred.clone().substitute(Interner, &substs))
1145                                 .filter(|wc| match &wc.skip_binders() {
1146                                     WhereClause::Implemented(tr) => {
1147                                         &tr.self_type_parameter(Interner) == self
1148                                     }
1149                                     WhereClause::AliasEq(AliasEq {
1150                                         alias: AliasTy::Projection(proj),
1151                                         ty: _,
1152                                     }) => &proj.self_type_parameter(db) == self,
1153                                     _ => false,
1154                                 })
1155                                 .collect::<Vec<_>>();
1156                             let krate = id.parent.module(db.upcast()).krate();
1157                             write_bounds_like_dyn_trait_with_prefix(
1158                                 f,
1159                                 "impl",
1160                                 &bounds,
1161                                 SizedByDefault::Sized { anchor: krate },
1162                             )?;
1163                         }
1164                     },
1165                     TypeOrConstParamData::ConstParamData(p) => {
1166                         write!(f, "{}", p.name.display(f.db.upcast()))?;
1167                     }
1168                 }
1169             }
1170             TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
1171             TyKind::Dyn(dyn_ty) => {
1172                 // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
1173                 // FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it
1174                 // more efficient when either of them hits stable.
1175                 let mut bounds: SmallVec<[_; 4]> =
1176                     dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
1177                 let (auto_traits, others): (SmallVec<[_; 4]>, _) =
1178                     bounds.drain(1..).partition(|b| b.skip_binders().trait_id().is_some());
1179                 bounds.extend(others);
1180                 bounds.extend(auto_traits);
1181 
1182                 write_bounds_like_dyn_trait_with_prefix(
1183                     f,
1184                     "dyn",
1185                     &bounds,
1186                     SizedByDefault::NotSized,
1187                 )?;
1188             }
1189             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
1190             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
1191                 if !f.display_target.allows_opaque() {
1192                     return Err(HirDisplayError::DisplaySourceCodeError(
1193                         DisplaySourceCodeError::OpaqueType,
1194                     ));
1195                 }
1196                 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
1197                 match impl_trait_id {
1198                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1199                         let datas =
1200                             db.return_type_impl_traits(func).expect("impl trait id without data");
1201                         let data =
1202                             (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1203                         let bounds = data.substitute(Interner, &opaque_ty.substitution);
1204                         let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
1205                         write_bounds_like_dyn_trait_with_prefix(
1206                             f,
1207                             "impl",
1208                             bounds.skip_binders(),
1209                             SizedByDefault::Sized { anchor: krate },
1210                         )?;
1211                     }
1212                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
1213                         write!(f, "{{async block}}")?;
1214                     }
1215                 };
1216             }
1217             TyKind::Error => {
1218                 if f.display_target.is_source_code() {
1219                     return Err(HirDisplayError::DisplaySourceCodeError(
1220                         DisplaySourceCodeError::UnknownType,
1221                     ));
1222                 }
1223                 write!(f, "{{unknown}}")?;
1224             }
1225             TyKind::InferenceVar(..) => write!(f, "_")?,
1226             TyKind::Generator(_, subst) => {
1227                 if f.display_target.is_source_code() {
1228                     return Err(HirDisplayError::DisplaySourceCodeError(
1229                         DisplaySourceCodeError::Generator,
1230                     ));
1231                 }
1232                 let subst = subst.as_slice(Interner);
1233                 let a: Option<SmallVec<[&Ty; 3]>> = subst
1234                     .get(subst.len() - 3..)
1235                     .map(|args| args.iter().map(|arg| arg.ty(Interner)).collect())
1236                     .flatten();
1237 
1238                 if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
1239                     write!(f, "|")?;
1240                     resume_ty.hir_fmt(f)?;
1241                     write!(f, "|")?;
1242 
1243                     write!(f, " yields ")?;
1244                     yield_ty.hir_fmt(f)?;
1245 
1246                     write!(f, " -> ")?;
1247                     ret_ty.hir_fmt(f)?;
1248                 } else {
1249                     // This *should* be unreachable, but fallback just in case.
1250                     write!(f, "{{generator}}")?;
1251                 }
1252             }
1253             TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
1254         }
1255         Ok(())
1256     }
1257 }
1258 
hir_fmt_generics( f: &mut HirFormatter<'_>, parameters: &Substitution, generic_def: Option<hir_def::GenericDefId>, ) -> Result<(), HirDisplayError>1259 fn hir_fmt_generics(
1260     f: &mut HirFormatter<'_>,
1261     parameters: &Substitution,
1262     generic_def: Option<hir_def::GenericDefId>,
1263 ) -> Result<(), HirDisplayError> {
1264     let db = f.db;
1265     let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
1266     if parameters.len(Interner) + lifetime_args_count > 0 {
1267         let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
1268             match generic_def
1269                 .map(|generic_def_id| db.generic_defaults(generic_def_id))
1270                 .filter(|defaults| !defaults.is_empty())
1271             {
1272                 None => parameters.as_slice(Interner),
1273                 Some(default_parameters) => {
1274                     fn should_show(
1275                         parameter: &GenericArg,
1276                         default_parameters: &[Binders<GenericArg>],
1277                         i: usize,
1278                         parameters: &Substitution,
1279                     ) -> bool {
1280                         if parameter.ty(Interner).map(|x| x.kind(Interner)) == Some(&TyKind::Error)
1281                         {
1282                             return true;
1283                         }
1284                         if let Some(ConstValue::Concrete(c)) =
1285                             parameter.constant(Interner).map(|x| &x.data(Interner).value)
1286                         {
1287                             if c.interned == ConstScalar::Unknown {
1288                                 return true;
1289                             }
1290                         }
1291                         let default_parameter = match default_parameters.get(i) {
1292                             Some(x) => x,
1293                             None => return true,
1294                         };
1295                         let actual_default =
1296                             default_parameter.clone().substitute(Interner, &parameters);
1297                         parameter != &actual_default
1298                     }
1299                     let mut default_from = 0;
1300                     for (i, parameter) in parameters.iter(Interner).enumerate() {
1301                         if should_show(parameter, &default_parameters, i, parameters) {
1302                             default_from = i + 1;
1303                         }
1304                     }
1305                     &parameters.as_slice(Interner)[0..default_from]
1306                 }
1307             }
1308         } else {
1309             parameters.as_slice(Interner)
1310         };
1311         if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
1312             write!(f, "<")?;
1313             let mut first = true;
1314             for _ in 0..lifetime_args_count {
1315                 if !first {
1316                     write!(f, ", ")?;
1317                 }
1318                 first = false;
1319                 write!(f, "'_")?;
1320             }
1321             for generic_arg in parameters_to_write {
1322                 if !first {
1323                     write!(f, ", ")?;
1324                 }
1325                 first = false;
1326                 if f.display_target.is_source_code()
1327                     && generic_arg.ty(Interner).map(|ty| ty.kind(Interner)) == Some(&TyKind::Error)
1328                 {
1329                     write!(f, "_")?;
1330                 } else {
1331                     generic_arg.hir_fmt(f)?;
1332                 }
1333             }
1334 
1335             write!(f, ">")?;
1336         }
1337     }
1338     Ok(())
1339 }
1340 
1341 impl HirDisplay for CallableSig {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1342     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1343         write!(f, "fn(")?;
1344         f.write_joined(self.params(), ", ")?;
1345         if self.is_varargs {
1346             if self.params().is_empty() {
1347                 write!(f, "...")?;
1348             } else {
1349                 write!(f, ", ...")?;
1350             }
1351         }
1352         write!(f, ")")?;
1353         let ret = self.ret();
1354         if !ret.is_unit() {
1355             write!(f, " -> ")?;
1356             ret.hir_fmt(f)?;
1357         }
1358         Ok(())
1359     }
1360 }
1361 
fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_1362 fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
1363     let krate = trait_.lookup(db).container.krate();
1364     utils::fn_traits(db, krate)
1365 }
1366 
1367 #[derive(Clone, Copy, PartialEq, Eq)]
1368 pub enum SizedByDefault {
1369     NotSized,
1370     Sized { anchor: CrateId },
1371 }
1372 
1373 impl SizedByDefault {
is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool1374     fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
1375         match self {
1376             Self::NotSized => false,
1377             Self::Sized { anchor } => {
1378                 let sized_trait = db
1379                     .lang_item(anchor, LangItem::Sized)
1380                     .and_then(|lang_item| lang_item.as_trait());
1381                 Some(trait_) == sized_trait
1382             }
1383         }
1384     }
1385 }
1386 
write_bounds_like_dyn_trait_with_prefix( f: &mut HirFormatter<'_>, prefix: &str, predicates: &[QuantifiedWhereClause], default_sized: SizedByDefault, ) -> Result<(), HirDisplayError>1387 pub fn write_bounds_like_dyn_trait_with_prefix(
1388     f: &mut HirFormatter<'_>,
1389     prefix: &str,
1390     predicates: &[QuantifiedWhereClause],
1391     default_sized: SizedByDefault,
1392 ) -> Result<(), HirDisplayError> {
1393     write!(f, "{prefix}")?;
1394     if !predicates.is_empty()
1395         || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
1396     {
1397         write!(f, " ")?;
1398         write_bounds_like_dyn_trait(f, predicates, default_sized)
1399     } else {
1400         Ok(())
1401     }
1402 }
1403 
write_bounds_like_dyn_trait( f: &mut HirFormatter<'_>, predicates: &[QuantifiedWhereClause], default_sized: SizedByDefault, ) -> Result<(), HirDisplayError>1404 fn write_bounds_like_dyn_trait(
1405     f: &mut HirFormatter<'_>,
1406     predicates: &[QuantifiedWhereClause],
1407     default_sized: SizedByDefault,
1408 ) -> Result<(), HirDisplayError> {
1409     // Note: This code is written to produce nice results (i.e.
1410     // corresponding to surface Rust) for types that can occur in
1411     // actual Rust. It will have weird results if the predicates
1412     // aren't as expected (i.e. self types = $0, projection
1413     // predicates for a certain trait come after the Implemented
1414     // predicate for that trait).
1415     let mut first = true;
1416     let mut angle_open = false;
1417     let mut is_fn_trait = false;
1418     let mut is_sized = false;
1419     for p in predicates.iter() {
1420         match p.skip_binders() {
1421             WhereClause::Implemented(trait_ref) => {
1422                 let trait_ = trait_ref.hir_trait_id();
1423                 if default_sized.is_sized_trait(trait_, f.db.upcast()) {
1424                     is_sized = true;
1425                     if matches!(default_sized, SizedByDefault::Sized { .. }) {
1426                         // Don't print +Sized, but rather +?Sized if absent.
1427                         continue;
1428                     }
1429                 }
1430                 if !is_fn_trait {
1431                     is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
1432                 }
1433                 if !is_fn_trait && angle_open {
1434                     write!(f, ">")?;
1435                     angle_open = false;
1436                 }
1437                 if !first {
1438                     write!(f, " + ")?;
1439                 }
1440                 // We assume that the self type is ^0.0 (i.e. the
1441                 // existential) here, which is the only thing that's
1442                 // possible in actual Rust, and hence don't print it
1443                 f.start_location_link(trait_.into());
1444                 write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
1445                 f.end_location_link();
1446                 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(Interner) {
1447                     if is_fn_trait {
1448                         if let Some(args) =
1449                             params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
1450                         {
1451                             write!(f, "(")?;
1452                             f.write_joined(args.as_slice(Interner), ", ")?;
1453                             write!(f, ")")?;
1454                         }
1455                     } else if !params.is_empty() {
1456                         write!(f, "<")?;
1457                         f.write_joined(params, ", ")?;
1458                         // there might be assoc type bindings, so we leave the angle brackets open
1459                         angle_open = true;
1460                     }
1461                 }
1462             }
1463             WhereClause::AliasEq(alias_eq) if is_fn_trait => {
1464                 is_fn_trait = false;
1465                 if !alias_eq.ty.is_unit() {
1466                     write!(f, " -> ")?;
1467                     alias_eq.ty.hir_fmt(f)?;
1468                 }
1469             }
1470             WhereClause::AliasEq(AliasEq { ty, alias }) => {
1471                 // in types in actual Rust, these will always come
1472                 // after the corresponding Implemented predicate
1473                 if angle_open {
1474                     write!(f, ", ")?;
1475                 } else {
1476                     write!(f, "<")?;
1477                     angle_open = true;
1478                 }
1479                 if let AliasTy::Projection(proj) = alias {
1480                     let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
1481                     let type_alias = f.db.type_alias_data(assoc_ty_id);
1482                     f.start_location_link(assoc_ty_id.into());
1483                     write!(f, "{}", type_alias.name.display(f.db.upcast()))?;
1484                     f.end_location_link();
1485 
1486                     let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
1487                     if proj_arg_count > 0 {
1488                         write!(f, "<")?;
1489                         f.write_joined(
1490                             &proj.substitution.as_slice(Interner)[..proj_arg_count],
1491                             ", ",
1492                         )?;
1493                         write!(f, ">")?;
1494                     }
1495                     write!(f, " = ")?;
1496                 }
1497                 ty.hir_fmt(f)?;
1498             }
1499 
1500             // FIXME implement these
1501             WhereClause::LifetimeOutlives(_) => {}
1502             WhereClause::TypeOutlives(_) => {}
1503         }
1504         first = false;
1505     }
1506     if angle_open {
1507         write!(f, ">")?;
1508     }
1509     if let SizedByDefault::Sized { anchor } = default_sized {
1510         let sized_trait =
1511             f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
1512         if !is_sized {
1513             if !first {
1514                 write!(f, " + ")?;
1515             }
1516             if let Some(sized_trait) = sized_trait {
1517                 f.start_location_link(sized_trait.into());
1518             }
1519             write!(f, "?Sized")?;
1520         } else if first {
1521             if let Some(sized_trait) = sized_trait {
1522                 f.start_location_link(sized_trait.into());
1523             }
1524             write!(f, "Sized")?;
1525         }
1526         if let Some(_) = sized_trait {
1527             f.end_location_link();
1528         }
1529     }
1530     Ok(())
1531 }
1532 
fmt_trait_ref( f: &mut HirFormatter<'_>, tr: &TraitRef, use_as: bool, ) -> Result<(), HirDisplayError>1533 fn fmt_trait_ref(
1534     f: &mut HirFormatter<'_>,
1535     tr: &TraitRef,
1536     use_as: bool,
1537 ) -> Result<(), HirDisplayError> {
1538     if f.should_truncate() {
1539         return write!(f, "{TYPE_HINT_TRUNCATION}");
1540     }
1541 
1542     tr.self_type_parameter(Interner).hir_fmt(f)?;
1543     if use_as {
1544         write!(f, " as ")?;
1545     } else {
1546         write!(f, ": ")?;
1547     }
1548     let trait_ = tr.hir_trait_id();
1549     f.start_location_link(trait_.into());
1550     write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
1551     f.end_location_link();
1552     if tr.substitution.len(Interner) > 1 {
1553         write!(f, "<")?;
1554         f.write_joined(&tr.substitution.as_slice(Interner)[1..], ", ")?;
1555         write!(f, ">")?;
1556     }
1557     Ok(())
1558 }
1559 
1560 impl HirDisplay for TraitRef {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1561     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1562         fmt_trait_ref(f, self, false)
1563     }
1564 }
1565 
1566 impl HirDisplay for WhereClause {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1567     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1568         if f.should_truncate() {
1569             return write!(f, "{TYPE_HINT_TRUNCATION}");
1570         }
1571 
1572         match self {
1573             WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
1574             WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
1575                 write!(f, "<")?;
1576                 fmt_trait_ref(f, &projection_ty.trait_ref(f.db), true)?;
1577                 write!(f, ">::",)?;
1578                 let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
1579                 f.start_location_link(type_alias.into());
1580                 write!(f, "{}", f.db.type_alias_data(type_alias).name.display(f.db.upcast()),)?;
1581                 f.end_location_link();
1582                 write!(f, " = ")?;
1583                 ty.hir_fmt(f)?;
1584             }
1585             WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
1586 
1587             // FIXME implement these
1588             WhereClause::TypeOutlives(..) => {}
1589             WhereClause::LifetimeOutlives(..) => {}
1590         }
1591         Ok(())
1592     }
1593 }
1594 
1595 impl HirDisplay for LifetimeOutlives {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1596     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1597         self.a.hir_fmt(f)?;
1598         write!(f, ": ")?;
1599         self.b.hir_fmt(f)
1600     }
1601 }
1602 
1603 impl HirDisplay for Lifetime {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1604     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1605         self.interned().hir_fmt(f)
1606     }
1607 }
1608 
1609 impl HirDisplay for LifetimeData {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1610     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1611         match self {
1612             LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
1613             LifetimeData::InferenceVar(_) => write!(f, "_"),
1614             LifetimeData::Placeholder(idx) => {
1615                 let id = lt_from_placeholder_idx(f.db, *idx);
1616                 let generics = generics(f.db.upcast(), id.parent);
1617                 let param_data = &generics.params.lifetimes[id.local_id];
1618                 write!(f, "{}", param_data.name.display(f.db.upcast()))?;
1619                 Ok(())
1620             }
1621             LifetimeData::Static => write!(f, "'static"),
1622             LifetimeData::Erased => Ok(()),
1623             LifetimeData::Phantom(_, _) => Ok(()),
1624         }
1625     }
1626 }
1627 
1628 impl HirDisplay for DomainGoal {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1629     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1630         match self {
1631             DomainGoal::Holds(wc) => {
1632                 write!(f, "Holds(")?;
1633                 wc.hir_fmt(f)?;
1634                 write!(f, ")")?;
1635             }
1636             _ => write!(f, "?")?,
1637         }
1638         Ok(())
1639     }
1640 }
1641 
write_visibility( module_id: ModuleId, vis: Visibility, f: &mut HirFormatter<'_>, ) -> Result<(), HirDisplayError>1642 pub fn write_visibility(
1643     module_id: ModuleId,
1644     vis: Visibility,
1645     f: &mut HirFormatter<'_>,
1646 ) -> Result<(), HirDisplayError> {
1647     match vis {
1648         Visibility::Public => write!(f, "pub "),
1649         Visibility::Module(vis_id) => {
1650             let def_map = module_id.def_map(f.db.upcast());
1651             let root_module_id = def_map.module_id(DefMap::ROOT);
1652             if vis_id == module_id {
1653                 // pub(self) or omitted
1654                 Ok(())
1655             } else if root_module_id == vis_id {
1656                 write!(f, "pub(crate) ")
1657             } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) {
1658                 write!(f, "pub(super) ")
1659             } else {
1660                 write!(f, "pub(in ...) ")
1661             }
1662         }
1663     }
1664 }
1665 
1666 impl HirDisplay for TypeRef {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1667     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1668         match self {
1669             TypeRef::Never => write!(f, "!")?,
1670             TypeRef::Placeholder => write!(f, "_")?,
1671             TypeRef::Tuple(elems) => {
1672                 write!(f, "(")?;
1673                 f.write_joined(elems, ", ")?;
1674                 if elems.len() == 1 {
1675                     write!(f, ",")?;
1676                 }
1677                 write!(f, ")")?;
1678             }
1679             TypeRef::Path(path) => path.hir_fmt(f)?,
1680             TypeRef::RawPtr(inner, mutability) => {
1681                 let mutability = match mutability {
1682                     hir_def::type_ref::Mutability::Shared => "*const ",
1683                     hir_def::type_ref::Mutability::Mut => "*mut ",
1684                 };
1685                 write!(f, "{mutability}")?;
1686                 inner.hir_fmt(f)?;
1687             }
1688             TypeRef::Reference(inner, lifetime, mutability) => {
1689                 let mutability = match mutability {
1690                     hir_def::type_ref::Mutability::Shared => "",
1691                     hir_def::type_ref::Mutability::Mut => "mut ",
1692                 };
1693                 write!(f, "&")?;
1694                 if let Some(lifetime) = lifetime {
1695                     write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
1696                 }
1697                 write!(f, "{mutability}")?;
1698                 inner.hir_fmt(f)?;
1699             }
1700             TypeRef::Array(inner, len) => {
1701                 write!(f, "[")?;
1702                 inner.hir_fmt(f)?;
1703                 write!(f, "; {}]", len.display(f.db.upcast()))?;
1704             }
1705             TypeRef::Slice(inner) => {
1706                 write!(f, "[")?;
1707                 inner.hir_fmt(f)?;
1708                 write!(f, "]")?;
1709             }
1710             &TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
1711                 // FIXME: Function pointer qualifiers.
1712                 if is_unsafe {
1713                     write!(f, "unsafe ")?;
1714                 }
1715                 write!(f, "fn(")?;
1716                 if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
1717                     for index in 0..function_parameters.len() {
1718                         let (param_name, param_type) = &function_parameters[index];
1719                         if let Some(name) = param_name {
1720                             write!(f, "{}: ", name.display(f.db.upcast()))?;
1721                         }
1722 
1723                         param_type.hir_fmt(f)?;
1724 
1725                         if index != function_parameters.len() - 1 {
1726                             write!(f, ", ")?;
1727                         }
1728                     }
1729                     if is_varargs {
1730                         write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
1731                     }
1732                     write!(f, ")")?;
1733                     match &return_type {
1734                         TypeRef::Tuple(tup) if tup.is_empty() => {}
1735                         _ => {
1736                             write!(f, " -> ")?;
1737                             return_type.hir_fmt(f)?;
1738                         }
1739                     }
1740                 }
1741             }
1742             TypeRef::ImplTrait(bounds) => {
1743                 write!(f, "impl ")?;
1744                 f.write_joined(bounds, " + ")?;
1745             }
1746             TypeRef::DynTrait(bounds) => {
1747                 write!(f, "dyn ")?;
1748                 f.write_joined(bounds, " + ")?;
1749             }
1750             TypeRef::Macro(macro_call) => {
1751                 let macro_call = macro_call.to_node(f.db.upcast());
1752                 let ctx = hir_def::lower::LowerCtx::with_hygiene(
1753                     f.db.upcast(),
1754                     &Hygiene::new_unhygienic(),
1755                 );
1756                 match macro_call.path() {
1757                     Some(path) => match Path::from_src(path, &ctx) {
1758                         Some(path) => path.hir_fmt(f)?,
1759                         None => write!(f, "{{macro}}")?,
1760                     },
1761                     None => write!(f, "{{macro}}")?,
1762                 }
1763                 write!(f, "!(..)")?;
1764             }
1765             TypeRef::Error => write!(f, "{{error}}")?,
1766         }
1767         Ok(())
1768     }
1769 }
1770 
1771 impl HirDisplay for TypeBound {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1772     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1773         match self {
1774             TypeBound::Path(path, modifier) => {
1775                 match modifier {
1776                     TraitBoundModifier::None => (),
1777                     TraitBoundModifier::Maybe => write!(f, "?")?,
1778                 }
1779                 path.hir_fmt(f)
1780             }
1781             TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name.display(f.db.upcast())),
1782             TypeBound::ForLifetime(lifetimes, path) => {
1783                 write!(
1784                     f,
1785                     "for<{}> ",
1786                     lifetimes.iter().map(|it| it.display(f.db.upcast())).format(", ")
1787                 )?;
1788                 path.hir_fmt(f)
1789             }
1790             TypeBound::Error => write!(f, "{{error}}"),
1791         }
1792     }
1793 }
1794 
1795 impl HirDisplay for Path {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1796     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1797         match (self.type_anchor(), self.kind()) {
1798             (Some(anchor), _) => {
1799                 write!(f, "<")?;
1800                 anchor.hir_fmt(f)?;
1801                 write!(f, ">")?;
1802             }
1803             (_, PathKind::Plain) => {}
1804             (_, PathKind::Abs) => {}
1805             (_, PathKind::Crate) => write!(f, "crate")?,
1806             (_, PathKind::Super(0)) => write!(f, "self")?,
1807             (_, PathKind::Super(n)) => {
1808                 for i in 0..*n {
1809                     if i > 0 {
1810                         write!(f, "::")?;
1811                     }
1812                     write!(f, "super")?;
1813                 }
1814             }
1815             (_, PathKind::DollarCrate(id)) => {
1816                 // Resolve `$crate` to the crate's display name.
1817                 // FIXME: should use the dependency name instead if available, but that depends on
1818                 // the crate invoking `HirDisplay`
1819                 let crate_graph = f.db.crate_graph();
1820                 let name = crate_graph[*id]
1821                     .display_name
1822                     .as_ref()
1823                     .map(|name| name.canonical_name())
1824                     .unwrap_or("$crate");
1825                 write!(f, "{name}")?
1826             }
1827         }
1828 
1829         for (seg_idx, segment) in self.segments().iter().enumerate() {
1830             if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
1831                 write!(f, "::")?;
1832             }
1833             write!(f, "{}", segment.name.display(f.db.upcast()))?;
1834             if let Some(generic_args) = segment.args_and_bindings {
1835                 // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
1836                 // Do we actually format expressions?
1837                 if generic_args.desugared_from_fn {
1838                     // First argument will be a tuple, which already includes the parentheses.
1839                     // If the tuple only contains 1 item, write it manually to avoid the trailing `,`.
1840                     if let hir_def::path::GenericArg::Type(TypeRef::Tuple(v)) =
1841                         &generic_args.args[0]
1842                     {
1843                         if v.len() == 1 {
1844                             write!(f, "(")?;
1845                             v[0].hir_fmt(f)?;
1846                             write!(f, ")")?;
1847                         } else {
1848                             generic_args.args[0].hir_fmt(f)?;
1849                         }
1850                     }
1851                     if let Some(ret) = &generic_args.bindings[0].type_ref {
1852                         if !matches!(ret, TypeRef::Tuple(v) if v.is_empty()) {
1853                             write!(f, " -> ")?;
1854                             ret.hir_fmt(f)?;
1855                         }
1856                     }
1857                     return Ok(());
1858                 }
1859 
1860                 write!(f, "<")?;
1861                 let mut first = true;
1862                 for arg in generic_args.args.iter() {
1863                     if first {
1864                         first = false;
1865                         if generic_args.has_self_type {
1866                             // FIXME: Convert to `<Ty as Trait>` form.
1867                             write!(f, "Self = ")?;
1868                         }
1869                     } else {
1870                         write!(f, ", ")?;
1871                     }
1872                     arg.hir_fmt(f)?;
1873                 }
1874                 for binding in generic_args.bindings.iter() {
1875                     if first {
1876                         first = false;
1877                     } else {
1878                         write!(f, ", ")?;
1879                     }
1880                     write!(f, "{}", binding.name.display(f.db.upcast()))?;
1881                     match &binding.type_ref {
1882                         Some(ty) => {
1883                             write!(f, " = ")?;
1884                             ty.hir_fmt(f)?
1885                         }
1886                         None => {
1887                             write!(f, ": ")?;
1888                             f.write_joined(binding.bounds.iter(), " + ")?;
1889                         }
1890                     }
1891                 }
1892                 write!(f, ">")?;
1893             }
1894         }
1895         Ok(())
1896     }
1897 }
1898 
1899 impl HirDisplay for hir_def::path::GenericArg {
hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>1900     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1901         match self {
1902             hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1903             hir_def::path::GenericArg::Const(c) => write!(f, "{}", c.display(f.db.upcast())),
1904             hir_def::path::GenericArg::Lifetime(lifetime) => {
1905                 write!(f, "{}", lifetime.name.display(f.db.upcast()))
1906             }
1907         }
1908     }
1909 }
1910