]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/hir-ty/src/display.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / src / tools / rust-analyzer / crates / hir-ty / src / display.rs
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::fmt::{self, Debug};
6
7 use base_db::CrateId;
8 use chalk_ir::BoundVar;
9 use hir_def::{
10     body,
11     db::DefDatabase,
12     find_path,
13     generics::{TypeOrConstParamData, TypeParamProvenance},
14     intern::{Internable, Interned},
15     item_scope::ItemInNs,
16     path::{Path, PathKind},
17     type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
18     visibility::Visibility,
19     HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
20 };
21 use hir_expand::{hygiene::Hygiene, name::Name};
22 use itertools::Itertools;
23 use smallvec::SmallVec;
24 use syntax::SmolStr;
25
26 use crate::{
27     db::HirDatabase,
28     from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
29     mapping::from_chalk,
30     primitive, to_assoc_type_id,
31     utils::{self, generics},
32     AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstValue, DomainGoal,
33     GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability,
34     OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, Substitution, TraitRef,
35     TraitRefExt, Ty, TyExt, TyKind, WhereClause,
36 };
37
38 pub trait HirWrite: fmt::Write {
39     fn start_location_link(&mut self, location: ModuleDefId);
40     fn end_location_link(&mut self);
41 }
42
43 // String will ignore link metadata
44 impl HirWrite for String {
45     fn start_location_link(&mut self, _: ModuleDefId) {}
46
47     fn end_location_link(&mut self) {}
48 }
49
50 // `core::Formatter` will ignore metadata
51 impl HirWrite for fmt::Formatter<'_> {
52     fn start_location_link(&mut self, _: ModuleDefId) {}
53     fn end_location_link(&mut self) {}
54 }
55
56 pub struct HirFormatter<'a> {
57     pub db: &'a dyn HirDatabase,
58     fmt: &'a mut dyn HirWrite,
59     buf: String,
60     curr_size: usize,
61     pub(crate) max_size: Option<usize>,
62     omit_verbose_types: bool,
63     display_target: DisplayTarget,
64 }
65
66 impl HirFormatter<'_> {
67     fn start_location_link(&mut self, location: ModuleDefId) {
68         self.fmt.start_location_link(location);
69     }
70
71     fn end_location_link(&mut self) {
72         self.fmt.end_location_link();
73     }
74 }
75
76 pub trait HirDisplay {
77     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
78
79     /// Returns a `Display`able type that is human-readable.
80     fn into_displayable<'a>(
81         &'a self,
82         db: &'a dyn HirDatabase,
83         max_size: Option<usize>,
84         omit_verbose_types: bool,
85         display_target: DisplayTarget,
86     ) -> HirDisplayWrapper<'a, Self>
87     where
88         Self: Sized,
89     {
90         assert!(
91             !matches!(display_target, DisplayTarget::SourceCode { .. }),
92             "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
93         );
94         HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
95     }
96
97     /// Returns a `Display`able type that is human-readable.
98     /// Use this for showing types to the user (e.g. diagnostics)
99     fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
100     where
101         Self: Sized,
102     {
103         HirDisplayWrapper {
104             db,
105             t: self,
106             max_size: None,
107             omit_verbose_types: false,
108             display_target: DisplayTarget::Diagnostics,
109         }
110     }
111
112     /// Returns a `Display`able type that is human-readable and tries to be succinct.
113     /// Use this for showing types to the user where space is constrained (e.g. doc popups)
114     fn display_truncated<'a>(
115         &'a self,
116         db: &'a dyn HirDatabase,
117         max_size: Option<usize>,
118     ) -> HirDisplayWrapper<'a, Self>
119     where
120         Self: Sized,
121     {
122         HirDisplayWrapper {
123             db,
124             t: self,
125             max_size,
126             omit_verbose_types: true,
127             display_target: DisplayTarget::Diagnostics,
128         }
129     }
130
131     /// Returns a String representation of `self` that can be inserted into the given module.
132     /// Use this when generating code (e.g. assists)
133     fn display_source_code<'a>(
134         &'a self,
135         db: &'a dyn HirDatabase,
136         module_id: ModuleId,
137     ) -> Result<String, DisplaySourceCodeError> {
138         let mut result = String::new();
139         match self.hir_fmt(&mut HirFormatter {
140             db,
141             fmt: &mut result,
142             buf: String::with_capacity(20),
143             curr_size: 0,
144             max_size: None,
145             omit_verbose_types: false,
146             display_target: DisplayTarget::SourceCode { module_id },
147         }) {
148             Ok(()) => {}
149             Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
150             Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
151         };
152         Ok(result)
153     }
154
155     /// Returns a String representation of `self` for test purposes
156     fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
157     where
158         Self: Sized,
159     {
160         HirDisplayWrapper {
161             db,
162             t: self,
163             max_size: None,
164             omit_verbose_types: false,
165             display_target: DisplayTarget::Test,
166         }
167     }
168 }
169
170 impl<'a> HirFormatter<'a> {
171     pub fn write_joined<T: HirDisplay>(
172         &mut self,
173         iter: impl IntoIterator<Item = T>,
174         sep: &str,
175     ) -> Result<(), HirDisplayError> {
176         let mut first = true;
177         for e in iter {
178             if !first {
179                 write!(self, "{sep}")?;
180             }
181             first = false;
182
183             // Abbreviate multiple omitted types with a single ellipsis.
184             if self.should_truncate() {
185                 return write!(self, "{TYPE_HINT_TRUNCATION}");
186             }
187
188             e.hir_fmt(self)?;
189         }
190         Ok(())
191     }
192
193     /// This allows using the `write!` macro directly with a `HirFormatter`.
194     pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> {
195         // We write to a buffer first to track output size
196         self.buf.clear();
197         fmt::write(&mut self.buf, args)?;
198         self.curr_size += self.buf.len();
199
200         // Then we write to the internal formatter from the buffer
201         self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
202     }
203
204     pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> {
205         self.fmt.write_str(s)?;
206         Ok(())
207     }
208
209     pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> {
210         self.fmt.write_char(c)?;
211         Ok(())
212     }
213
214     pub fn should_truncate(&self) -> bool {
215         match self.max_size {
216             Some(max_size) => self.curr_size >= max_size,
217             None => false,
218         }
219     }
220
221     pub fn omit_verbose_types(&self) -> bool {
222         self.omit_verbose_types
223     }
224 }
225
226 #[derive(Clone, Copy)]
227 pub enum DisplayTarget {
228     /// Display types for inlays, doc popups, autocompletion, etc...
229     /// Showing `{unknown}` or not qualifying paths is fine here.
230     /// There's no reason for this to fail.
231     Diagnostics,
232     /// Display types for inserting them in source files.
233     /// The generated code should compile, so paths need to be qualified.
234     SourceCode { module_id: ModuleId },
235     /// Only for test purpose to keep real types
236     Test,
237 }
238
239 impl DisplayTarget {
240     fn is_source_code(&self) -> bool {
241         matches!(self, Self::SourceCode { .. })
242     }
243     fn is_test(&self) -> bool {
244         matches!(self, Self::Test)
245     }
246 }
247
248 #[derive(Debug)]
249 pub enum DisplaySourceCodeError {
250     PathNotFound,
251     UnknownType,
252     Closure,
253     Generator,
254 }
255
256 pub enum HirDisplayError {
257     /// Errors that can occur when generating source code
258     DisplaySourceCodeError(DisplaySourceCodeError),
259     /// `FmtError` is required to be compatible with std::fmt::Display
260     FmtError,
261 }
262 impl From<fmt::Error> for HirDisplayError {
263     fn from(_: fmt::Error) -> Self {
264         Self::FmtError
265     }
266 }
267
268 pub struct HirDisplayWrapper<'a, T> {
269     db: &'a dyn HirDatabase,
270     t: &'a T,
271     max_size: Option<usize>,
272     omit_verbose_types: bool,
273     display_target: DisplayTarget,
274 }
275
276 impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
277     pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
278         self.t.hir_fmt(&mut HirFormatter {
279             db: self.db,
280             fmt: f,
281             buf: String::with_capacity(20),
282             curr_size: 0,
283             max_size: self.max_size,
284             omit_verbose_types: self.omit_verbose_types,
285             display_target: self.display_target,
286         })
287     }
288 }
289
290 impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
291 where
292     T: HirDisplay,
293 {
294     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295         match self.write_to(f) {
296             Ok(()) => Ok(()),
297             Err(HirDisplayError::FmtError) => Err(fmt::Error),
298             Err(HirDisplayError::DisplaySourceCodeError(_)) => {
299                 // This should never happen
300                 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
301             }
302         }
303     }
304 }
305
306 const TYPE_HINT_TRUNCATION: &str = "…";
307
308 impl<T: HirDisplay> HirDisplay for &'_ T {
309     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
310         HirDisplay::hir_fmt(*self, f)
311     }
312 }
313
314 impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
315     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
316         HirDisplay::hir_fmt(self.as_ref(), f)
317     }
318 }
319
320 impl HirDisplay for ProjectionTy {
321     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
322         if f.should_truncate() {
323             return write!(f, "{TYPE_HINT_TRUNCATION}");
324         }
325
326         let trait_ref = self.trait_ref(f.db);
327         write!(f, "<")?;
328         fmt_trait_ref(&trait_ref, f, true)?;
329         write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
330         let proj_params_count =
331             self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
332         let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
333         if !proj_params.is_empty() {
334             write!(f, "<")?;
335             f.write_joined(proj_params, ", ")?;
336             write!(f, ">")?;
337         }
338         Ok(())
339     }
340 }
341
342 impl HirDisplay for OpaqueTy {
343     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
344         if f.should_truncate() {
345             return write!(f, "{TYPE_HINT_TRUNCATION}");
346         }
347
348         self.substitution.at(Interner, 0).hir_fmt(f)
349     }
350 }
351
352 impl HirDisplay for GenericArg {
353     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
354         match self.interned() {
355             crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
356             crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
357             crate::GenericArgData::Const(c) => c.hir_fmt(f),
358         }
359     }
360 }
361
362 impl HirDisplay for Const {
363     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
364         let data = self.interned();
365         match data.value {
366             ConstValue::BoundVar(idx) => idx.hir_fmt(f),
367             ConstValue::InferenceVar(..) => write!(f, "#c#"),
368             ConstValue::Placeholder(idx) => {
369                 let id = from_placeholder_idx(f.db, idx);
370                 let generics = generics(f.db.upcast(), id.parent);
371                 let param_data = &generics.params.type_or_consts[id.local_id];
372                 write!(f, "{}", param_data.name().unwrap())
373             }
374             ConstValue::Concrete(c) => write!(f, "{}", c.interned),
375         }
376     }
377 }
378
379 impl HirDisplay for BoundVar {
380     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
381         write!(f, "?{}.{}", self.debruijn.depth(), self.index)
382     }
383 }
384
385 impl HirDisplay for Ty {
386     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
387         if f.should_truncate() {
388             return write!(f, "{TYPE_HINT_TRUNCATION}");
389         }
390
391         match self.kind(Interner) {
392             TyKind::Never => write!(f, "!")?,
393             TyKind::Str => write!(f, "str")?,
394             TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
395             TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
396             &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
397             &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
398             &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
399             TyKind::Slice(t) => {
400                 write!(f, "[")?;
401                 t.hir_fmt(f)?;
402                 write!(f, "]")?;
403             }
404             TyKind::Array(t, c) => {
405                 write!(f, "[")?;
406                 t.hir_fmt(f)?;
407                 write!(f, "; ")?;
408                 c.hir_fmt(f)?;
409                 write!(f, "]")?;
410             }
411             TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
412                 if matches!(self.kind(Interner), TyKind::Raw(..)) {
413                     write!(
414                         f,
415                         "*{}",
416                         match m {
417                             Mutability::Not => "const ",
418                             Mutability::Mut => "mut ",
419                         }
420                     )?;
421                 } else {
422                     write!(
423                         f,
424                         "&{}",
425                         match m {
426                             Mutability::Not => "",
427                             Mutability::Mut => "mut ",
428                         }
429                     )?;
430                 }
431
432                 // FIXME: all this just to decide whether to use parentheses...
433                 let contains_impl_fn = |bounds: &[QuantifiedWhereClause]| {
434                     bounds.iter().any(|bound| {
435                         if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
436                             let trait_ = trait_ref.hir_trait_id();
437                             fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
438                         } else {
439                             false
440                         }
441                     })
442                 };
443                 let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
444                     TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
445                         let bounds = dyn_ty.bounds.skip_binders().interned();
446                         (bounds.len(), contains_impl_fn(bounds))
447                     }
448                     TyKind::Alias(AliasTy::Opaque(OpaqueTy {
449                         opaque_ty_id,
450                         substitution: parameters,
451                     }))
452                     | TyKind::OpaqueType(opaque_ty_id, parameters) => {
453                         let impl_trait_id =
454                             f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
455                         if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
456                             let datas =
457                                 f.db.return_type_impl_traits(func)
458                                     .expect("impl trait id without data");
459                             let data = (*datas)
460                                 .as_ref()
461                                 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
462                             let bounds = data.substitute(Interner, parameters);
463                             let mut len = bounds.skip_binders().len();
464
465                             // Don't count Sized but count when it absent
466                             // (i.e. when explicit ?Sized bound is set).
467                             let default_sized = SizedByDefault::Sized {
468                                 anchor: func.lookup(f.db.upcast()).module(f.db.upcast()).krate(),
469                             };
470                             let sized_bounds = bounds
471                                 .skip_binders()
472                                 .iter()
473                                 .filter(|b| {
474                                     matches!(
475                                         b.skip_binders(),
476                                         WhereClause::Implemented(trait_ref)
477                                             if default_sized.is_sized_trait(
478                                                 trait_ref.hir_trait_id(),
479                                                 f.db.upcast(),
480                                             ),
481                                     )
482                                 })
483                                 .count();
484                             match sized_bounds {
485                                 0 => len += 1,
486                                 _ => {
487                                     len = len.saturating_sub(sized_bounds);
488                                 }
489                             }
490
491                             (len, contains_impl_fn(bounds.skip_binders()))
492                         } else {
493                             (0, false)
494                         }
495                     }
496                     _ => (0, false),
497                 };
498
499                 if has_impl_fn_pred && preds_to_print <= 2 {
500                     return t.hir_fmt(f);
501                 }
502
503                 if preds_to_print > 1 {
504                     write!(f, "(")?;
505                     t.hir_fmt(f)?;
506                     write!(f, ")")?;
507                 } else {
508                     t.hir_fmt(f)?;
509                 }
510             }
511             TyKind::Tuple(_, substs) => {
512                 if substs.len(Interner) == 1 {
513                     write!(f, "(")?;
514                     substs.at(Interner, 0).hir_fmt(f)?;
515                     write!(f, ",)")?;
516                 } else {
517                     write!(f, "(")?;
518                     f.write_joined(&*substs.as_slice(Interner), ", ")?;
519                     write!(f, ")")?;
520                 }
521             }
522             TyKind::Function(fn_ptr) => {
523                 let sig = CallableSig::from_fn_ptr(fn_ptr);
524                 sig.hir_fmt(f)?;
525             }
526             TyKind::FnDef(def, parameters) => {
527                 let def = from_chalk(f.db, *def);
528                 let sig = f.db.callable_item_signature(def).substitute(Interner, parameters);
529                 match def {
530                     CallableDefId::FunctionId(ff) => {
531                         write!(f, "fn {}", f.db.function_data(ff).name)?
532                     }
533                     CallableDefId::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?,
534                     CallableDefId::EnumVariantId(e) => {
535                         write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
536                     }
537                 };
538                 if parameters.len(Interner) > 0 {
539                     let generics = generics(f.db.upcast(), def.into());
540                     let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
541                         generics.provenance_split();
542                     let total_len = parent_params + self_param + type_params + const_params;
543                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
544                     if total_len > 0 {
545                         // `parameters` are in the order of fn's params (including impl traits),
546                         // parent's params (those from enclosing impl or trait, if any).
547                         let parameters = parameters.as_slice(Interner);
548                         let fn_params_len = self_param + type_params + const_params;
549                         let fn_params = parameters.get(..fn_params_len);
550                         let parent_params = parameters.get(parameters.len() - parent_params..);
551                         let params = parent_params.into_iter().chain(fn_params).flatten();
552                         write!(f, "<")?;
553                         f.write_joined(params, ", ")?;
554                         write!(f, ">")?;
555                     }
556                 }
557                 write!(f, "(")?;
558                 f.write_joined(sig.params(), ", ")?;
559                 write!(f, ")")?;
560                 let ret = sig.ret();
561                 if !ret.is_unit() {
562                     write!(f, " -> ")?;
563                     ret.hir_fmt(f)?;
564                 }
565             }
566             TyKind::Adt(AdtId(def_id), parameters) => {
567                 f.start_location_link((*def_id).into());
568                 match f.display_target {
569                     DisplayTarget::Diagnostics | DisplayTarget::Test => {
570                         let name = match *def_id {
571                             hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
572                             hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
573                             hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
574                         };
575                         write!(f, "{name}")?;
576                     }
577                     DisplayTarget::SourceCode { module_id } => {
578                         if let Some(path) = find_path::find_path(
579                             f.db.upcast(),
580                             ItemInNs::Types((*def_id).into()),
581                             module_id,
582                             false,
583                         ) {
584                             write!(f, "{path}")?;
585                         } else {
586                             return Err(HirDisplayError::DisplaySourceCodeError(
587                                 DisplaySourceCodeError::PathNotFound,
588                             ));
589                         }
590                     }
591                 }
592                 f.end_location_link();
593
594                 if parameters.len(Interner) > 0 {
595                     let parameters_to_write = if f.display_target.is_source_code()
596                         || f.omit_verbose_types()
597                     {
598                         match self
599                             .as_generic_def(f.db)
600                             .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
601                             .filter(|defaults| !defaults.is_empty())
602                         {
603                             None => parameters.as_slice(Interner),
604                             Some(default_parameters) => {
605                                 fn should_show(
606                                     parameter: &GenericArg,
607                                     default_parameters: &[Binders<GenericArg>],
608                                     i: usize,
609                                     parameters: &Substitution,
610                                 ) -> bool {
611                                     if parameter.ty(Interner).map(|x| x.kind(Interner))
612                                         == Some(&TyKind::Error)
613                                     {
614                                         return true;
615                                     }
616                                     if let Some(ConstValue::Concrete(c)) =
617                                         parameter.constant(Interner).map(|x| x.data(Interner).value)
618                                     {
619                                         if c.interned == ConstScalar::Unknown {
620                                             return true;
621                                         }
622                                     }
623                                     let default_parameter = match default_parameters.get(i) {
624                                         Some(x) => x,
625                                         None => return true,
626                                     };
627                                     let actual_default =
628                                         default_parameter.clone().substitute(Interner, &parameters);
629                                     parameter != &actual_default
630                                 }
631                                 let mut default_from = 0;
632                                 for (i, parameter) in parameters.iter(Interner).enumerate() {
633                                     if should_show(parameter, &default_parameters, i, parameters) {
634                                         default_from = i + 1;
635                                     }
636                                 }
637                                 &parameters.as_slice(Interner)[0..default_from]
638                             }
639                         }
640                     } else {
641                         parameters.as_slice(Interner)
642                     };
643                     if !parameters_to_write.is_empty() {
644                         write!(f, "<")?;
645
646                         if f.display_target.is_source_code() {
647                             let mut first = true;
648                             for generic_arg in parameters_to_write {
649                                 if !first {
650                                     write!(f, ", ")?;
651                                 }
652                                 first = false;
653
654                                 if generic_arg.ty(Interner).map(|ty| ty.kind(Interner))
655                                     == Some(&TyKind::Error)
656                                 {
657                                     write!(f, "_")?;
658                                 } else {
659                                     generic_arg.hir_fmt(f)?;
660                                 }
661                             }
662                         } else {
663                             f.write_joined(parameters_to_write, ", ")?;
664                         }
665
666                         write!(f, ">")?;
667                     }
668                 }
669             }
670             TyKind::AssociatedType(assoc_type_id, parameters) => {
671                 let type_alias = from_assoc_type_id(*assoc_type_id);
672                 let trait_ = match type_alias.lookup(f.db.upcast()).container {
673                     ItemContainerId::TraitId(it) => it,
674                     _ => panic!("not an associated type"),
675                 };
676                 let trait_ = f.db.trait_data(trait_);
677                 let type_alias_data = f.db.type_alias_data(type_alias);
678
679                 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
680                 if f.display_target.is_test() {
681                     write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
682                     // Note that the generic args for the associated type come before those for the
683                     // trait (including the self type).
684                     // FIXME: reconsider the generic args order upon formatting?
685                     if parameters.len(Interner) > 0 {
686                         write!(f, "<")?;
687                         f.write_joined(parameters.as_slice(Interner), ", ")?;
688                         write!(f, ">")?;
689                     }
690                 } else {
691                     let projection_ty = ProjectionTy {
692                         associated_ty_id: to_assoc_type_id(type_alias),
693                         substitution: parameters.clone(),
694                     };
695
696                     projection_ty.hir_fmt(f)?;
697                 }
698             }
699             TyKind::Foreign(type_alias) => {
700                 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
701                 write!(f, "{}", type_alias.name)?;
702             }
703             TyKind::OpaqueType(opaque_ty_id, parameters) => {
704                 let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
705                 match impl_trait_id {
706                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
707                         let datas =
708                             f.db.return_type_impl_traits(func).expect("impl trait id without data");
709                         let data = (*datas)
710                             .as_ref()
711                             .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
712                         let bounds = data.substitute(Interner, &parameters);
713                         let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
714                         write_bounds_like_dyn_trait_with_prefix(
715                             "impl",
716                             bounds.skip_binders(),
717                             SizedByDefault::Sized { anchor: krate },
718                             f,
719                         )?;
720                         // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
721                     }
722                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
723                         write!(f, "impl Future<Output = ")?;
724                         parameters.at(Interner, 0).hir_fmt(f)?;
725                         write!(f, ">")?;
726                     }
727                 }
728             }
729             TyKind::Closure(.., substs) => {
730                 if f.display_target.is_source_code() {
731                     return Err(HirDisplayError::DisplaySourceCodeError(
732                         DisplaySourceCodeError::Closure,
733                     ));
734                 }
735                 let sig = substs.at(Interner, 0).assert_ty_ref(Interner).callable_sig(f.db);
736                 if let Some(sig) = sig {
737                     if sig.params().is_empty() {
738                         write!(f, "||")?;
739                     } else if f.should_truncate() {
740                         write!(f, "|{TYPE_HINT_TRUNCATION}|")?;
741                     } else {
742                         write!(f, "|")?;
743                         f.write_joined(sig.params(), ", ")?;
744                         write!(f, "|")?;
745                     };
746
747                     write!(f, " -> ")?;
748                     sig.ret().hir_fmt(f)?;
749                 } else {
750                     write!(f, "{{closure}}")?;
751                 }
752             }
753             TyKind::Placeholder(idx) => {
754                 let id = from_placeholder_idx(f.db, *idx);
755                 let generics = generics(f.db.upcast(), id.parent);
756                 let param_data = &generics.params.type_or_consts[id.local_id];
757                 match param_data {
758                     TypeOrConstParamData::TypeParamData(p) => match p.provenance {
759                         TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
760                             write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))?
761                         }
762                         TypeParamProvenance::ArgumentImplTrait => {
763                             let substs = generics.placeholder_subst(f.db);
764                             let bounds =
765                                 f.db.generic_predicates(id.parent)
766                                     .iter()
767                                     .map(|pred| pred.clone().substitute(Interner, &substs))
768                                     .filter(|wc| match &wc.skip_binders() {
769                                         WhereClause::Implemented(tr) => {
770                                             &tr.self_type_parameter(Interner) == self
771                                         }
772                                         WhereClause::AliasEq(AliasEq {
773                                             alias: AliasTy::Projection(proj),
774                                             ty: _,
775                                         }) => &proj.self_type_parameter(f.db) == self,
776                                         _ => false,
777                                     })
778                                     .collect::<Vec<_>>();
779                             let krate = id.parent.module(f.db.upcast()).krate();
780                             write_bounds_like_dyn_trait_with_prefix(
781                                 "impl",
782                                 &bounds,
783                                 SizedByDefault::Sized { anchor: krate },
784                                 f,
785                             )?;
786                         }
787                     },
788                     TypeOrConstParamData::ConstParamData(p) => {
789                         write!(f, "{}", p.name)?;
790                     }
791                 }
792             }
793             TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
794             TyKind::Dyn(dyn_ty) => {
795                 // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
796                 // FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it
797                 // more efficient when either of them hits stable.
798                 let mut bounds: SmallVec<[_; 4]> =
799                     dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
800                 let (auto_traits, others): (SmallVec<[_; 4]>, _) =
801                     bounds.drain(1..).partition(|b| b.skip_binders().trait_id().is_some());
802                 bounds.extend(others);
803                 bounds.extend(auto_traits);
804
805                 write_bounds_like_dyn_trait_with_prefix(
806                     "dyn",
807                     &bounds,
808                     SizedByDefault::NotSized,
809                     f,
810                 )?;
811             }
812             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
813             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
814                 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
815                 match impl_trait_id {
816                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
817                         let datas =
818                             f.db.return_type_impl_traits(func).expect("impl trait id without data");
819                         let data = (*datas)
820                             .as_ref()
821                             .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
822                         let bounds = data.substitute(Interner, &opaque_ty.substitution);
823                         let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
824                         write_bounds_like_dyn_trait_with_prefix(
825                             "impl",
826                             bounds.skip_binders(),
827                             SizedByDefault::Sized { anchor: krate },
828                             f,
829                         )?;
830                     }
831                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
832                         write!(f, "{{async block}}")?;
833                     }
834                 };
835             }
836             TyKind::Error => {
837                 if f.display_target.is_source_code() {
838                     return Err(HirDisplayError::DisplaySourceCodeError(
839                         DisplaySourceCodeError::UnknownType,
840                     ));
841                 }
842                 write!(f, "{{unknown}}")?;
843             }
844             TyKind::InferenceVar(..) => write!(f, "_")?,
845             TyKind::Generator(_, subst) => {
846                 if f.display_target.is_source_code() {
847                     return Err(HirDisplayError::DisplaySourceCodeError(
848                         DisplaySourceCodeError::Generator,
849                     ));
850                 }
851
852                 let subst = subst.as_slice(Interner);
853                 let a: Option<SmallVec<[&Ty; 3]>> = subst
854                     .get(subst.len() - 3..)
855                     .map(|args| args.iter().map(|arg| arg.ty(Interner)).collect())
856                     .flatten();
857
858                 if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
859                     write!(f, "|")?;
860                     resume_ty.hir_fmt(f)?;
861                     write!(f, "|")?;
862
863                     write!(f, " yields ")?;
864                     yield_ty.hir_fmt(f)?;
865
866                     write!(f, " -> ")?;
867                     ret_ty.hir_fmt(f)?;
868                 } else {
869                     // This *should* be unreachable, but fallback just in case.
870                     write!(f, "{{generator}}")?;
871                 }
872             }
873             TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
874         }
875         Ok(())
876     }
877 }
878
879 impl HirDisplay for CallableSig {
880     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
881         write!(f, "fn(")?;
882         f.write_joined(self.params(), ", ")?;
883         if self.is_varargs {
884             if self.params().is_empty() {
885                 write!(f, "...")?;
886             } else {
887                 write!(f, ", ...")?;
888             }
889         }
890         write!(f, ")")?;
891         let ret = self.ret();
892         if !ret.is_unit() {
893             write!(f, " -> ")?;
894             ret.hir_fmt(f)?;
895         }
896         Ok(())
897     }
898 }
899
900 fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
901     let krate = trait_.lookup(db).container.krate();
902     utils::fn_traits(db, krate)
903 }
904
905 #[derive(Clone, Copy, PartialEq, Eq)]
906 pub enum SizedByDefault {
907     NotSized,
908     Sized { anchor: CrateId },
909 }
910
911 impl SizedByDefault {
912     fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
913         match self {
914             Self::NotSized => false,
915             Self::Sized { anchor } => {
916                 let sized_trait = db
917                     .lang_item(anchor, SmolStr::new_inline("sized"))
918                     .and_then(|lang_item| lang_item.as_trait());
919                 Some(trait_) == sized_trait
920             }
921         }
922     }
923 }
924
925 pub fn write_bounds_like_dyn_trait_with_prefix(
926     prefix: &str,
927     predicates: &[QuantifiedWhereClause],
928     default_sized: SizedByDefault,
929     f: &mut HirFormatter<'_>,
930 ) -> Result<(), HirDisplayError> {
931     write!(f, "{prefix}")?;
932     if !predicates.is_empty()
933         || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
934     {
935         write!(f, " ")?;
936         write_bounds_like_dyn_trait(predicates, default_sized, f)
937     } else {
938         Ok(())
939     }
940 }
941
942 fn write_bounds_like_dyn_trait(
943     predicates: &[QuantifiedWhereClause],
944     default_sized: SizedByDefault,
945     f: &mut HirFormatter<'_>,
946 ) -> Result<(), HirDisplayError> {
947     // Note: This code is written to produce nice results (i.e.
948     // corresponding to surface Rust) for types that can occur in
949     // actual Rust. It will have weird results if the predicates
950     // aren't as expected (i.e. self types = $0, projection
951     // predicates for a certain trait come after the Implemented
952     // predicate for that trait).
953     let mut first = true;
954     let mut angle_open = false;
955     let mut is_fn_trait = false;
956     let mut is_sized = false;
957     for p in predicates.iter() {
958         match p.skip_binders() {
959             WhereClause::Implemented(trait_ref) => {
960                 let trait_ = trait_ref.hir_trait_id();
961                 if default_sized.is_sized_trait(trait_, f.db.upcast()) {
962                     is_sized = true;
963                     if matches!(default_sized, SizedByDefault::Sized { .. }) {
964                         // Don't print +Sized, but rather +?Sized if absent.
965                         continue;
966                     }
967                 }
968                 if !is_fn_trait {
969                     is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
970                 }
971                 if !is_fn_trait && angle_open {
972                     write!(f, ">")?;
973                     angle_open = false;
974                 }
975                 if !first {
976                     write!(f, " + ")?;
977                 }
978                 // We assume that the self type is ^0.0 (i.e. the
979                 // existential) here, which is the only thing that's
980                 // possible in actual Rust, and hence don't print it
981                 write!(f, "{}", f.db.trait_data(trait_).name)?;
982                 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(Interner) {
983                     if is_fn_trait {
984                         if let Some(args) =
985                             params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
986                         {
987                             write!(f, "(")?;
988                             f.write_joined(args.as_slice(Interner), ", ")?;
989                             write!(f, ")")?;
990                         }
991                     } else if !params.is_empty() {
992                         write!(f, "<")?;
993                         f.write_joined(params, ", ")?;
994                         // there might be assoc type bindings, so we leave the angle brackets open
995                         angle_open = true;
996                     }
997                 }
998             }
999             WhereClause::AliasEq(alias_eq) if is_fn_trait => {
1000                 is_fn_trait = false;
1001                 if !alias_eq.ty.is_unit() {
1002                     write!(f, " -> ")?;
1003                     alias_eq.ty.hir_fmt(f)?;
1004                 }
1005             }
1006             WhereClause::AliasEq(AliasEq { ty, alias }) => {
1007                 // in types in actual Rust, these will always come
1008                 // after the corresponding Implemented predicate
1009                 if angle_open {
1010                     write!(f, ", ")?;
1011                 } else {
1012                     write!(f, "<")?;
1013                     angle_open = true;
1014                 }
1015                 if let AliasTy::Projection(proj) = alias {
1016                     let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
1017                     let type_alias = f.db.type_alias_data(assoc_ty_id);
1018                     write!(f, "{}", type_alias.name)?;
1019
1020                     let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
1021                     if proj_arg_count > 0 {
1022                         write!(f, "<")?;
1023                         f.write_joined(
1024                             &proj.substitution.as_slice(Interner)[..proj_arg_count],
1025                             ", ",
1026                         )?;
1027                         write!(f, ">")?;
1028                     }
1029                     write!(f, " = ")?;
1030                 }
1031                 ty.hir_fmt(f)?;
1032             }
1033
1034             // FIXME implement these
1035             WhereClause::LifetimeOutlives(_) => {}
1036             WhereClause::TypeOutlives(_) => {}
1037         }
1038         first = false;
1039     }
1040     if angle_open {
1041         write!(f, ">")?;
1042     }
1043     if matches!(default_sized, SizedByDefault::Sized { .. }) {
1044         if !is_sized {
1045             write!(f, "{}?Sized", if first { "" } else { " + " })?;
1046         } else if first {
1047             write!(f, "Sized")?;
1048         }
1049     }
1050     Ok(())
1051 }
1052
1053 fn fmt_trait_ref(
1054     tr: &TraitRef,
1055     f: &mut HirFormatter<'_>,
1056     use_as: bool,
1057 ) -> Result<(), HirDisplayError> {
1058     if f.should_truncate() {
1059         return write!(f, "{TYPE_HINT_TRUNCATION}");
1060     }
1061
1062     tr.self_type_parameter(Interner).hir_fmt(f)?;
1063     if use_as {
1064         write!(f, " as ")?;
1065     } else {
1066         write!(f, ": ")?;
1067     }
1068     write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
1069     if tr.substitution.len(Interner) > 1 {
1070         write!(f, "<")?;
1071         f.write_joined(&tr.substitution.as_slice(Interner)[1..], ", ")?;
1072         write!(f, ">")?;
1073     }
1074     Ok(())
1075 }
1076
1077 impl HirDisplay for TraitRef {
1078     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1079         fmt_trait_ref(self, f, false)
1080     }
1081 }
1082
1083 impl HirDisplay for WhereClause {
1084     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1085         if f.should_truncate() {
1086             return write!(f, "{TYPE_HINT_TRUNCATION}");
1087         }
1088
1089         match self {
1090             WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
1091             WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
1092                 write!(f, "<")?;
1093                 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
1094                 write!(
1095                     f,
1096                     ">::{} = ",
1097                     f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
1098                 )?;
1099                 ty.hir_fmt(f)?;
1100             }
1101             WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
1102
1103             // FIXME implement these
1104             WhereClause::TypeOutlives(..) => {}
1105             WhereClause::LifetimeOutlives(..) => {}
1106         }
1107         Ok(())
1108     }
1109 }
1110
1111 impl HirDisplay for LifetimeOutlives {
1112     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1113         self.a.hir_fmt(f)?;
1114         write!(f, ": ")?;
1115         self.b.hir_fmt(f)
1116     }
1117 }
1118
1119 impl HirDisplay for Lifetime {
1120     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1121         self.interned().hir_fmt(f)
1122     }
1123 }
1124
1125 impl HirDisplay for LifetimeData {
1126     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1127         match self {
1128             LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
1129             LifetimeData::InferenceVar(_) => write!(f, "_"),
1130             LifetimeData::Placeholder(idx) => {
1131                 let id = lt_from_placeholder_idx(f.db, *idx);
1132                 let generics = generics(f.db.upcast(), id.parent);
1133                 let param_data = &generics.params.lifetimes[id.local_id];
1134                 write!(f, "{}", param_data.name)
1135             }
1136             LifetimeData::Static => write!(f, "'static"),
1137             LifetimeData::Erased => Ok(()),
1138             LifetimeData::Phantom(_, _) => Ok(()),
1139         }
1140     }
1141 }
1142
1143 impl HirDisplay for DomainGoal {
1144     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1145         match self {
1146             DomainGoal::Holds(wc) => {
1147                 write!(f, "Holds(")?;
1148                 wc.hir_fmt(f)?;
1149                 write!(f, ")")?;
1150             }
1151             _ => write!(f, "?")?,
1152         }
1153         Ok(())
1154     }
1155 }
1156
1157 pub fn write_visibility(
1158     module_id: ModuleId,
1159     vis: Visibility,
1160     f: &mut HirFormatter<'_>,
1161 ) -> Result<(), HirDisplayError> {
1162     match vis {
1163         Visibility::Public => write!(f, "pub "),
1164         Visibility::Module(vis_id) => {
1165             let def_map = module_id.def_map(f.db.upcast());
1166             let root_module_id = def_map.module_id(def_map.root());
1167             if vis_id == module_id {
1168                 // pub(self) or omitted
1169                 Ok(())
1170             } else if root_module_id == vis_id {
1171                 write!(f, "pub(crate) ")
1172             } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) {
1173                 write!(f, "pub(super) ")
1174             } else {
1175                 write!(f, "pub(in ...) ")
1176             }
1177         }
1178     }
1179 }
1180
1181 impl HirDisplay for TypeRef {
1182     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1183         match self {
1184             TypeRef::Never => write!(f, "!")?,
1185             TypeRef::Placeholder => write!(f, "_")?,
1186             TypeRef::Tuple(elems) => {
1187                 write!(f, "(")?;
1188                 f.write_joined(elems, ", ")?;
1189                 if elems.len() == 1 {
1190                     write!(f, ",")?;
1191                 }
1192                 write!(f, ")")?;
1193             }
1194             TypeRef::Path(path) => path.hir_fmt(f)?,
1195             TypeRef::RawPtr(inner, mutability) => {
1196                 let mutability = match mutability {
1197                     hir_def::type_ref::Mutability::Shared => "*const ",
1198                     hir_def::type_ref::Mutability::Mut => "*mut ",
1199                 };
1200                 write!(f, "{mutability}")?;
1201                 inner.hir_fmt(f)?;
1202             }
1203             TypeRef::Reference(inner, lifetime, mutability) => {
1204                 let mutability = match mutability {
1205                     hir_def::type_ref::Mutability::Shared => "",
1206                     hir_def::type_ref::Mutability::Mut => "mut ",
1207                 };
1208                 write!(f, "&")?;
1209                 if let Some(lifetime) = lifetime {
1210                     write!(f, "{} ", lifetime.name)?;
1211                 }
1212                 write!(f, "{mutability}")?;
1213                 inner.hir_fmt(f)?;
1214             }
1215             TypeRef::Array(inner, len) => {
1216                 write!(f, "[")?;
1217                 inner.hir_fmt(f)?;
1218                 write!(f, "; {len}]")?;
1219             }
1220             TypeRef::Slice(inner) => {
1221                 write!(f, "[")?;
1222                 inner.hir_fmt(f)?;
1223                 write!(f, "]")?;
1224             }
1225             &TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
1226                 // FIXME: Function pointer qualifiers.
1227                 if is_unsafe {
1228                     write!(f, "unsafe ")?;
1229                 }
1230                 write!(f, "fn(")?;
1231                 if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
1232                     for index in 0..function_parameters.len() {
1233                         let (param_name, param_type) = &function_parameters[index];
1234                         if let Some(name) = param_name {
1235                             write!(f, "{name}: ")?;
1236                         }
1237
1238                         param_type.hir_fmt(f)?;
1239
1240                         if index != function_parameters.len() - 1 {
1241                             write!(f, ", ")?;
1242                         }
1243                     }
1244                     if is_varargs {
1245                         write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
1246                     }
1247                     write!(f, ")")?;
1248                     match &return_type {
1249                         TypeRef::Tuple(tup) if tup.is_empty() => {}
1250                         _ => {
1251                             write!(f, " -> ")?;
1252                             return_type.hir_fmt(f)?;
1253                         }
1254                     }
1255                 }
1256             }
1257             TypeRef::ImplTrait(bounds) => {
1258                 write!(f, "impl ")?;
1259                 f.write_joined(bounds, " + ")?;
1260             }
1261             TypeRef::DynTrait(bounds) => {
1262                 write!(f, "dyn ")?;
1263                 f.write_joined(bounds, " + ")?;
1264             }
1265             TypeRef::Macro(macro_call) => {
1266                 let macro_call = macro_call.to_node(f.db.upcast());
1267                 let ctx = body::LowerCtx::with_hygiene(f.db.upcast(), &Hygiene::new_unhygienic());
1268                 match macro_call.path() {
1269                     Some(path) => match Path::from_src(path, &ctx) {
1270                         Some(path) => path.hir_fmt(f)?,
1271                         None => write!(f, "{{macro}}")?,
1272                     },
1273                     None => write!(f, "{{macro}}")?,
1274                 }
1275                 write!(f, "!(..)")?;
1276             }
1277             TypeRef::Error => write!(f, "{{error}}")?,
1278         }
1279         Ok(())
1280     }
1281 }
1282
1283 impl HirDisplay for TypeBound {
1284     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1285         match self {
1286             TypeBound::Path(path, modifier) => {
1287                 match modifier {
1288                     TraitBoundModifier::None => (),
1289                     TraitBoundModifier::Maybe => write!(f, "?")?,
1290                 }
1291                 path.hir_fmt(f)
1292             }
1293             TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1294             TypeBound::ForLifetime(lifetimes, path) => {
1295                 write!(f, "for<{}> ", lifetimes.iter().format(", "))?;
1296                 path.hir_fmt(f)
1297             }
1298             TypeBound::Error => write!(f, "{{error}}"),
1299         }
1300     }
1301 }
1302
1303 impl HirDisplay for Path {
1304     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1305         match (self.type_anchor(), self.kind()) {
1306             (Some(anchor), _) => {
1307                 write!(f, "<")?;
1308                 anchor.hir_fmt(f)?;
1309                 write!(f, ">")?;
1310             }
1311             (_, PathKind::Plain) => {}
1312             (_, PathKind::Abs) => {}
1313             (_, PathKind::Crate) => write!(f, "crate")?,
1314             (_, PathKind::Super(0)) => write!(f, "self")?,
1315             (_, PathKind::Super(n)) => {
1316                 for i in 0..*n {
1317                     if i > 0 {
1318                         write!(f, "::")?;
1319                     }
1320                     write!(f, "super")?;
1321                 }
1322             }
1323             (_, PathKind::DollarCrate(id)) => {
1324                 // Resolve `$crate` to the crate's display name.
1325                 // FIXME: should use the dependency name instead if available, but that depends on
1326                 // the crate invoking `HirDisplay`
1327                 let crate_graph = f.db.crate_graph();
1328                 let name = crate_graph[*id]
1329                     .display_name
1330                     .as_ref()
1331                     .map(|name| name.canonical_name())
1332                     .unwrap_or("$crate");
1333                 write!(f, "{name}")?
1334             }
1335         }
1336
1337         for (seg_idx, segment) in self.segments().iter().enumerate() {
1338             if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
1339                 write!(f, "::")?;
1340             }
1341             write!(f, "{}", segment.name)?;
1342             if let Some(generic_args) = segment.args_and_bindings {
1343                 // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
1344                 // Do we actually format expressions?
1345                 if generic_args.desugared_from_fn {
1346                     // First argument will be a tuple, which already includes the parentheses.
1347                     // If the tuple only contains 1 item, write it manually to avoid the trailing `,`.
1348                     if let hir_def::path::GenericArg::Type(TypeRef::Tuple(v)) =
1349                         &generic_args.args[0]
1350                     {
1351                         if v.len() == 1 {
1352                             write!(f, "(")?;
1353                             v[0].hir_fmt(f)?;
1354                             write!(f, ")")?;
1355                         } else {
1356                             generic_args.args[0].hir_fmt(f)?;
1357                         }
1358                     }
1359                     if let Some(ret) = &generic_args.bindings[0].type_ref {
1360                         if !matches!(ret, TypeRef::Tuple(v) if v.is_empty()) {
1361                             write!(f, " -> ")?;
1362                             ret.hir_fmt(f)?;
1363                         }
1364                     }
1365                     return Ok(());
1366                 }
1367
1368                 write!(f, "<")?;
1369                 let mut first = true;
1370                 for arg in &generic_args.args {
1371                     if first {
1372                         first = false;
1373                         if generic_args.has_self_type {
1374                             // FIXME: Convert to `<Ty as Trait>` form.
1375                             write!(f, "Self = ")?;
1376                         }
1377                     } else {
1378                         write!(f, ", ")?;
1379                     }
1380                     arg.hir_fmt(f)?;
1381                 }
1382                 for binding in &generic_args.bindings {
1383                     if first {
1384                         first = false;
1385                     } else {
1386                         write!(f, ", ")?;
1387                     }
1388                     write!(f, "{}", binding.name)?;
1389                     match &binding.type_ref {
1390                         Some(ty) => {
1391                             write!(f, " = ")?;
1392                             ty.hir_fmt(f)?
1393                         }
1394                         None => {
1395                             write!(f, ": ")?;
1396                             f.write_joined(&binding.bounds, " + ")?;
1397                         }
1398                     }
1399                 }
1400                 write!(f, ">")?;
1401             }
1402         }
1403         Ok(())
1404     }
1405 }
1406
1407 impl HirDisplay for hir_def::path::GenericArg {
1408     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1409         match self {
1410             hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1411             hir_def::path::GenericArg::Const(c) => write!(f, "{c}"),
1412             hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1413         }
1414     }
1415 }