]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/display.rs
Don't use HirDisplayWrapper when displaying SourceCode
[rust.git] / crates / hir_ty / src / display.rs
1 //! FIXME: write short doc here
2
3 use std::{
4     array,
5     fmt::{self, Debug},
6 };
7
8 use chalk_ir::BoundVar;
9 use hir_def::{
10     db::DefDatabase,
11     find_path,
12     generics::TypeParamProvenance,
13     item_scope::ItemInNs,
14     path::{Path, PathKind},
15     type_ref::{TypeBound, TypeRef},
16     visibility::Visibility,
17     AssocContainerId, Lookup, ModuleId, TraitId,
18 };
19 use hir_expand::name::Name;
20
21 use crate::{
22     const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
23     from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id,
24     traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId,
25     CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime,
26     LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
27     QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause,
28 };
29
30 pub struct HirFormatter<'a> {
31     pub db: &'a dyn HirDatabase,
32     fmt: &'a mut dyn fmt::Write,
33     buf: String,
34     curr_size: usize,
35     pub(crate) max_size: Option<usize>,
36     omit_verbose_types: bool,
37     display_target: DisplayTarget,
38 }
39
40 pub trait HirDisplay {
41     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>;
42
43     /// Returns a `Display`able type that is human-readable.
44     fn into_displayable<'a>(
45         &'a self,
46         db: &'a dyn HirDatabase,
47         max_size: Option<usize>,
48         omit_verbose_types: bool,
49         display_target: DisplayTarget,
50     ) -> HirDisplayWrapper<'a, Self>
51     where
52         Self: Sized,
53     {
54         HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
55     }
56
57     /// Returns a `Display`able type that is human-readable.
58     /// Use this for showing types to the user (e.g. diagnostics)
59     fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
60     where
61         Self: Sized,
62     {
63         HirDisplayWrapper {
64             db,
65             t: self,
66             max_size: None,
67             omit_verbose_types: false,
68             display_target: DisplayTarget::Diagnostics,
69         }
70     }
71
72     /// Returns a `Display`able type that is human-readable and tries to be succinct.
73     /// Use this for showing types to the user where space is constrained (e.g. doc popups)
74     fn display_truncated<'a>(
75         &'a self,
76         db: &'a dyn HirDatabase,
77         max_size: Option<usize>,
78     ) -> HirDisplayWrapper<'a, Self>
79     where
80         Self: Sized,
81     {
82         HirDisplayWrapper {
83             db,
84             t: self,
85             max_size,
86             omit_verbose_types: true,
87             display_target: DisplayTarget::Diagnostics,
88         }
89     }
90
91     /// Returns a String representation of `self` that can be inserted into the given module.
92     /// Use this when generating code (e.g. assists)
93     fn display_source_code<'a>(
94         &'a self,
95         db: &'a dyn HirDatabase,
96         module_id: ModuleId,
97     ) -> Result<String, DisplaySourceCodeError> {
98         let mut result = String::new();
99         match self.hir_fmt(&mut HirFormatter {
100             db,
101             fmt: &mut result,
102             buf: String::with_capacity(20),
103             curr_size: 0,
104             max_size: None,
105             omit_verbose_types: false,
106             display_target: DisplayTarget::SourceCode { module_id },
107         }) {
108             Ok(()) => {}
109             Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
110             Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
111         };
112         Ok(result)
113     }
114
115     /// Returns a String representation of `self` for test purposes
116     fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
117     where
118         Self: Sized,
119     {
120         HirDisplayWrapper {
121             db,
122             t: self,
123             max_size: None,
124             omit_verbose_types: false,
125             display_target: DisplayTarget::Test,
126         }
127     }
128 }
129
130 impl<'a> HirFormatter<'a> {
131     pub fn write_joined<T: HirDisplay>(
132         &mut self,
133         iter: impl IntoIterator<Item = T>,
134         sep: &str,
135     ) -> Result<(), HirDisplayError> {
136         let mut first = true;
137         for e in iter {
138             if !first {
139                 write!(self, "{}", sep)?;
140             }
141             first = false;
142             e.hir_fmt(self)?;
143         }
144         Ok(())
145     }
146
147     /// This allows using the `write!` macro directly with a `HirFormatter`.
148     pub fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), HirDisplayError> {
149         // We write to a buffer first to track output size
150         self.buf.clear();
151         fmt::write(&mut self.buf, args)?;
152         self.curr_size += self.buf.len();
153
154         // Then we write to the internal formatter from the buffer
155         self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
156     }
157
158     pub fn should_truncate(&self) -> bool {
159         if let Some(max_size) = self.max_size {
160             self.curr_size >= max_size
161         } else {
162             false
163         }
164     }
165
166     pub fn omit_verbose_types(&self) -> bool {
167         self.omit_verbose_types
168     }
169 }
170
171 #[derive(Clone, Copy)]
172 pub enum DisplayTarget {
173     /// Display types for inlays, doc popups, autocompletion, etc...
174     /// Showing `{unknown}` or not qualifying paths is fine here.
175     /// There's no reason for this to fail.
176     Diagnostics,
177     /// Display types for inserting them in source files.
178     /// The generated code should compile, so paths need to be qualified.
179     SourceCode { module_id: ModuleId },
180     /// Only for test purpose to keep real types
181     Test,
182 }
183
184 impl DisplayTarget {
185     fn is_source_code(&self) -> bool {
186         matches!(self, Self::SourceCode { .. })
187     }
188     fn is_test(&self) -> bool {
189         matches!(self, Self::Test)
190     }
191 }
192
193 #[derive(Debug)]
194 pub enum DisplaySourceCodeError {
195     PathNotFound,
196     UnknownType,
197     Closure,
198 }
199
200 pub enum HirDisplayError {
201     /// Errors that can occur when generating source code
202     DisplaySourceCodeError(DisplaySourceCodeError),
203     /// `FmtError` is required to be compatible with std::fmt::Display
204     FmtError,
205 }
206 impl From<fmt::Error> for HirDisplayError {
207     fn from(_: fmt::Error) -> Self {
208         Self::FmtError
209     }
210 }
211
212 pub struct HirDisplayWrapper<'a, T> {
213     db: &'a dyn HirDatabase,
214     t: &'a T,
215     max_size: Option<usize>,
216     omit_verbose_types: bool,
217     display_target: DisplayTarget,
218 }
219
220 impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
221 where
222     T: HirDisplay,
223 {
224     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225         match self.t.hir_fmt(&mut HirFormatter {
226             db: self.db,
227             fmt: f,
228             buf: String::with_capacity(20),
229             curr_size: 0,
230             max_size: self.max_size,
231             omit_verbose_types: self.omit_verbose_types,
232             display_target: self.display_target,
233         }) {
234             Ok(()) => Ok(()),
235             Err(HirDisplayError::FmtError) => Err(fmt::Error),
236             Err(HirDisplayError::DisplaySourceCodeError(_)) => {
237                 // This should never happen
238                 panic!("HirDisplay failed when calling Display::fmt!")
239             }
240         }
241     }
242 }
243
244 const TYPE_HINT_TRUNCATION: &str = "…";
245
246 impl<T: HirDisplay> HirDisplay for &'_ T {
247     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
248         HirDisplay::hir_fmt(*self, f)
249     }
250 }
251
252 impl HirDisplay for ProjectionTy {
253     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
254         if f.should_truncate() {
255             return write!(f, "{}", TYPE_HINT_TRUNCATION);
256         }
257
258         let trait_ = f.db.trait_data(self.trait_(f.db));
259         write!(f, "<")?;
260         self.self_type_parameter(&Interner).hir_fmt(f)?;
261         write!(f, " as {}", trait_.name)?;
262         if self.substitution.len(&Interner) > 1 {
263             write!(f, "<")?;
264             f.write_joined(&self.substitution.interned()[1..], ", ")?;
265             write!(f, ">")?;
266         }
267         write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
268         Ok(())
269     }
270 }
271
272 impl HirDisplay for OpaqueTy {
273     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
274         if f.should_truncate() {
275             return write!(f, "{}", TYPE_HINT_TRUNCATION);
276         }
277
278         self.substitution.at(&Interner, 0).hir_fmt(f)
279     }
280 }
281
282 impl HirDisplay for GenericArg {
283     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
284         match self.interned() {
285             crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
286         }
287     }
288 }
289
290 impl HirDisplay for Const {
291     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
292         let data = self.interned();
293         match data.value {
294             ConstValue::BoundVar(idx) => idx.hir_fmt(f),
295             ConstValue::InferenceVar(..) => write!(f, "_"),
296             ConstValue::Placeholder(idx) => {
297                 let id = const_from_placeholder_idx(f.db, idx);
298                 let generics = generics(f.db.upcast(), id.parent);
299                 let param_data = &generics.params.consts[id.local_id];
300                 write!(f, "{}", param_data.name)
301             }
302             ConstValue::Concrete(_) => write!(f, "_"),
303         }
304     }
305 }
306
307 impl HirDisplay for BoundVar {
308     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
309         write!(f, "?{}.{}", self.debruijn.depth(), self.index)
310     }
311 }
312
313 impl HirDisplay for Ty {
314     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
315         if f.should_truncate() {
316             return write!(f, "{}", TYPE_HINT_TRUNCATION);
317         }
318
319         match self.kind(&Interner) {
320             TyKind::Never => write!(f, "!")?,
321             TyKind::Str => write!(f, "str")?,
322             TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
323             TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
324             &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
325             &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
326             &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
327             TyKind::Slice(t) => {
328                 write!(f, "[")?;
329                 t.hir_fmt(f)?;
330                 write!(f, "]")?;
331             }
332             TyKind::Array(t, c) => {
333                 write!(f, "[")?;
334                 t.hir_fmt(f)?;
335                 write!(f, "; ")?;
336                 c.hir_fmt(f)?;
337                 write!(f, "]")?;
338             }
339             TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
340                 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
341                     write!(
342                         f,
343                         "*{}",
344                         match m {
345                             Mutability::Not => "const ",
346                             Mutability::Mut => "mut ",
347                         }
348                     )?;
349                 } else {
350                     write!(
351                         f,
352                         "&{}",
353                         match m {
354                             Mutability::Not => "",
355                             Mutability::Mut => "mut ",
356                         }
357                     )?;
358                 }
359
360                 // FIXME: all this just to decide whether to use parentheses...
361                 let datas;
362                 let predicates: Vec<_> = match t.kind(&Interner) {
363                     TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
364                         dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
365                     }
366                     &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
367                         opaque_ty_id,
368                         substitution: ref parameters,
369                     })) => {
370                         let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into());
371                         if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
372                             datas =
373                                 f.db.return_type_impl_traits(func)
374                                     .expect("impl trait id without data");
375                             let data = (*datas)
376                                 .as_ref()
377                                 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
378                             let bounds = data.substitute(&Interner, parameters);
379                             bounds.into_value_and_skipped_binders().0
380                         } else {
381                             Vec::new()
382                         }
383                     }
384                     _ => Vec::new(),
385                 };
386
387                 if let Some(WhereClause::Implemented(trait_ref)) =
388                     predicates.get(0).map(|b| b.skip_binders())
389                 {
390                     let trait_ = trait_ref.hir_trait_id();
391                     if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
392                         && predicates.len() <= 2
393                     {
394                         return t.hir_fmt(f);
395                     }
396                 }
397
398                 if predicates.len() > 1 {
399                     write!(f, "(")?;
400                     t.hir_fmt(f)?;
401                     write!(f, ")")?;
402                 } else {
403                     t.hir_fmt(f)?;
404                 }
405             }
406             TyKind::Tuple(_, substs) => {
407                 if substs.len(&Interner) == 1 {
408                     write!(f, "(")?;
409                     substs.at(&Interner, 0).hir_fmt(f)?;
410                     write!(f, ",)")?;
411                 } else {
412                     write!(f, "(")?;
413                     f.write_joined(&*substs.interned(), ", ")?;
414                     write!(f, ")")?;
415                 }
416             }
417             TyKind::Function(fn_ptr) => {
418                 let sig = CallableSig::from_fn_ptr(fn_ptr);
419                 sig.hir_fmt(f)?;
420             }
421             TyKind::FnDef(def, parameters) => {
422                 let def = from_chalk(f.db, *def);
423                 let sig = f.db.callable_item_signature(def).substitute(&Interner, parameters);
424                 match def {
425                     CallableDefId::FunctionId(ff) => {
426                         write!(f, "fn {}", f.db.function_data(ff).name)?
427                     }
428                     CallableDefId::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?,
429                     CallableDefId::EnumVariantId(e) => {
430                         write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
431                     }
432                 };
433                 if parameters.len(&Interner) > 0 {
434                     let generics = generics(f.db.upcast(), def.into());
435                     let (parent_params, self_param, type_params, _impl_trait_params) =
436                         generics.provenance_split();
437                     let total_len = parent_params + self_param + type_params;
438                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
439                     if total_len > 0 {
440                         write!(f, "<")?;
441                         f.write_joined(&parameters.interned()[..total_len], ", ")?;
442                         write!(f, ">")?;
443                     }
444                 }
445                 write!(f, "(")?;
446                 f.write_joined(sig.params(), ", ")?;
447                 write!(f, ")")?;
448                 let ret = sig.ret();
449                 if !ret.is_unit() {
450                     write!(f, " -> ")?;
451                     ret.hir_fmt(f)?;
452                 }
453             }
454             TyKind::Adt(AdtId(def_id), parameters) => {
455                 match f.display_target {
456                     DisplayTarget::Diagnostics | DisplayTarget::Test => {
457                         let name = match *def_id {
458                             hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
459                             hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
460                             hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
461                         };
462                         write!(f, "{}", name)?;
463                     }
464                     DisplayTarget::SourceCode { module_id } => {
465                         if let Some(path) = find_path::find_path(
466                             f.db.upcast(),
467                             ItemInNs::Types((*def_id).into()),
468                             module_id,
469                         ) {
470                             write!(f, "{}", path)?;
471                         } else {
472                             return Err(HirDisplayError::DisplaySourceCodeError(
473                                 DisplaySourceCodeError::PathNotFound,
474                             ));
475                         }
476                     }
477                 }
478
479                 if parameters.len(&Interner) > 0 {
480                     let parameters_to_write = if f.display_target.is_source_code()
481                         || f.omit_verbose_types()
482                     {
483                         match self
484                             .as_generic_def(f.db)
485                             .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
486                             .filter(|defaults| !defaults.is_empty())
487                         {
488                             None => parameters.interned().as_ref(),
489                             Some(default_parameters) => {
490                                 let mut default_from = 0;
491                                 for (i, parameter) in parameters.iter(&Interner).enumerate() {
492                                     match (
493                                         parameter.assert_ty_ref(&Interner).kind(&Interner),
494                                         default_parameters.get(i),
495                                     ) {
496                                         (&TyKind::Error, _) | (_, None) => {
497                                             default_from = i + 1;
498                                         }
499                                         (_, Some(default_parameter)) => {
500                                             let actual_default =
501                                                 default_parameter.clone().substitute(
502                                                     &Interner,
503                                                     &subst_prefix(parameters, i),
504                                                 );
505                                             if parameter.assert_ty_ref(&Interner) != &actual_default
506                                             {
507                                                 default_from = i + 1;
508                                             }
509                                         }
510                                     }
511                                 }
512                                 &parameters.interned()[0..default_from]
513                             }
514                         }
515                     } else {
516                         parameters.interned().as_ref()
517                     };
518                     if !parameters_to_write.is_empty() {
519                         write!(f, "<")?;
520                         f.write_joined(parameters_to_write, ", ")?;
521                         write!(f, ">")?;
522                     }
523                 }
524             }
525             TyKind::AssociatedType(assoc_type_id, parameters) => {
526                 let type_alias = from_assoc_type_id(*assoc_type_id);
527                 let trait_ = match type_alias.lookup(f.db.upcast()).container {
528                     AssocContainerId::TraitId(it) => it,
529                     _ => panic!("not an associated type"),
530                 };
531                 let trait_ = f.db.trait_data(trait_);
532                 let type_alias_data = f.db.type_alias_data(type_alias);
533
534                 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
535                 if f.display_target.is_test() {
536                     write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
537                     if parameters.len(&Interner) > 0 {
538                         write!(f, "<")?;
539                         f.write_joined(&*parameters.interned(), ", ")?;
540                         write!(f, ">")?;
541                     }
542                 } else {
543                     let projection_ty = ProjectionTy {
544                         associated_ty_id: to_assoc_type_id(type_alias),
545                         substitution: parameters.clone(),
546                     };
547
548                     projection_ty.hir_fmt(f)?;
549                 }
550             }
551             TyKind::Foreign(type_alias) => {
552                 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
553                 write!(f, "{}", type_alias.name)?;
554             }
555             TyKind::OpaqueType(opaque_ty_id, parameters) => {
556                 let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
557                 match impl_trait_id {
558                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
559                         let datas =
560                             f.db.return_type_impl_traits(func).expect("impl trait id without data");
561                         let data = (*datas)
562                             .as_ref()
563                             .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
564                         let bounds = data.substitute(&Interner, &parameters);
565                         write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
566                         // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
567                     }
568                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
569                         write!(f, "impl Future<Output = ")?;
570                         parameters.at(&Interner, 0).hir_fmt(f)?;
571                         write!(f, ">")?;
572                     }
573                 }
574             }
575             TyKind::Closure(.., substs) => {
576                 if f.display_target.is_source_code() {
577                     return Err(HirDisplayError::DisplaySourceCodeError(
578                         DisplaySourceCodeError::Closure,
579                     ));
580                 }
581                 let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db);
582                 if let Some(sig) = sig {
583                     if sig.params().is_empty() {
584                         write!(f, "||")?;
585                     } else if f.omit_verbose_types() {
586                         write!(f, "|{}|", TYPE_HINT_TRUNCATION)?;
587                     } else {
588                         write!(f, "|")?;
589                         f.write_joined(sig.params(), ", ")?;
590                         write!(f, "|")?;
591                     };
592
593                     write!(f, " -> ")?;
594                     sig.ret().hir_fmt(f)?;
595                 } else {
596                     write!(f, "{{closure}}")?;
597                 }
598             }
599             TyKind::Placeholder(idx) => {
600                 let id = from_placeholder_idx(f.db, *idx);
601                 let generics = generics(f.db.upcast(), id.parent);
602                 let param_data = &generics.params.types[id.local_id];
603                 match param_data.provenance {
604                     TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
605                         write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
606                     }
607                     TypeParamProvenance::ArgumentImplTrait => {
608                         let substs = generics.type_params_subst(f.db);
609                         let bounds =
610                             f.db.generic_predicates(id.parent)
611                                 .into_iter()
612                                 .map(|pred| pred.clone().substitute(&Interner, &substs))
613                                 .filter(|wc| match &wc.skip_binders() {
614                                     WhereClause::Implemented(tr) => {
615                                         tr.self_type_parameter(&Interner) == self
616                                     }
617                                     WhereClause::AliasEq(AliasEq {
618                                         alias: AliasTy::Projection(proj),
619                                         ty: _,
620                                     }) => proj.self_type_parameter(&Interner) == self,
621                                     _ => false,
622                                 })
623                                 .collect::<Vec<_>>();
624                         write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
625                     }
626                 }
627             }
628             TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
629             TyKind::Dyn(dyn_ty) => {
630                 write_bounds_like_dyn_trait_with_prefix(
631                     "dyn",
632                     dyn_ty.bounds.skip_binders().interned(),
633                     f,
634                 )?;
635             }
636             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
637             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
638                 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
639                 match impl_trait_id {
640                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
641                         let datas =
642                             f.db.return_type_impl_traits(func).expect("impl trait id without data");
643                         let data = (*datas)
644                             .as_ref()
645                             .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
646                         let bounds = data.substitute(&Interner, &opaque_ty.substitution);
647                         write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
648                     }
649                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
650                         write!(f, "{{async block}}")?;
651                     }
652                 };
653             }
654             TyKind::Error => {
655                 if f.display_target.is_source_code() {
656                     return Err(HirDisplayError::DisplaySourceCodeError(
657                         DisplaySourceCodeError::UnknownType,
658                     ));
659                 }
660                 write!(f, "{{unknown}}")?;
661             }
662             TyKind::InferenceVar(..) => write!(f, "_")?,
663         }
664         Ok(())
665     }
666 }
667
668 impl HirDisplay for CallableSig {
669     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
670         write!(f, "fn(")?;
671         f.write_joined(self.params(), ", ")?;
672         if self.is_varargs {
673             if self.params().is_empty() {
674                 write!(f, "...")?;
675             } else {
676                 write!(f, ", ...")?;
677             }
678         }
679         write!(f, ")")?;
680         let ret = self.ret();
681         if !ret.is_unit() {
682             write!(f, " -> ")?;
683             ret.hir_fmt(f)?;
684         }
685         Ok(())
686     }
687 }
688
689 fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
690     let krate = trait_.lookup(db).container.krate();
691     let fn_traits = [
692         db.lang_item(krate, "fn".into()),
693         db.lang_item(krate, "fn_mut".into()),
694         db.lang_item(krate, "fn_once".into()),
695     ];
696     array::IntoIter::new(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
697 }
698
699 pub fn write_bounds_like_dyn_trait_with_prefix(
700     prefix: &str,
701     predicates: &[QuantifiedWhereClause],
702     f: &mut HirFormatter,
703 ) -> Result<(), HirDisplayError> {
704     write!(f, "{}", prefix)?;
705     if !predicates.is_empty() {
706         write!(f, " ")?;
707         write_bounds_like_dyn_trait(predicates, f)
708     } else {
709         Ok(())
710     }
711 }
712
713 fn write_bounds_like_dyn_trait(
714     predicates: &[QuantifiedWhereClause],
715     f: &mut HirFormatter,
716 ) -> Result<(), HirDisplayError> {
717     // Note: This code is written to produce nice results (i.e.
718     // corresponding to surface Rust) for types that can occur in
719     // actual Rust. It will have weird results if the predicates
720     // aren't as expected (i.e. self types = $0, projection
721     // predicates for a certain trait come after the Implemented
722     // predicate for that trait).
723     let mut first = true;
724     let mut angle_open = false;
725     let mut is_fn_trait = false;
726     for p in predicates.iter() {
727         match p.skip_binders() {
728             WhereClause::Implemented(trait_ref) => {
729                 let trait_ = trait_ref.hir_trait_id();
730                 if !is_fn_trait {
731                     is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_);
732                 }
733                 if !is_fn_trait && angle_open {
734                     write!(f, ">")?;
735                     angle_open = false;
736                 }
737                 if !first {
738                     write!(f, " + ")?;
739                 }
740                 // We assume that the self type is $0 (i.e. the
741                 // existential) here, which is the only thing that's
742                 // possible in actual Rust, and hence don't print it
743                 write!(f, "{}", f.db.trait_data(trait_).name)?;
744                 if let [_, params @ ..] = &*trait_ref.substitution.interned() {
745                     if is_fn_trait {
746                         if let Some(args) =
747                             params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
748                         {
749                             write!(f, "(")?;
750                             f.write_joined(&*args.interned(), ", ")?;
751                             write!(f, ")")?;
752                         }
753                     } else if !params.is_empty() {
754                         write!(f, "<")?;
755                         f.write_joined(params, ", ")?;
756                         // there might be assoc type bindings, so we leave the angle brackets open
757                         angle_open = true;
758                     }
759                 }
760             }
761             WhereClause::AliasEq(alias_eq) if is_fn_trait => {
762                 is_fn_trait = false;
763                 write!(f, " -> ")?;
764                 alias_eq.ty.hir_fmt(f)?;
765             }
766             WhereClause::AliasEq(AliasEq { ty, alias }) => {
767                 // in types in actual Rust, these will always come
768                 // after the corresponding Implemented predicate
769                 if angle_open {
770                     write!(f, ", ")?;
771                 } else {
772                     write!(f, "<")?;
773                     angle_open = true;
774                 }
775                 if let AliasTy::Projection(proj) = alias {
776                     let type_alias =
777                         f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id));
778                     write!(f, "{} = ", type_alias.name)?;
779                 }
780                 ty.hir_fmt(f)?;
781             }
782         }
783         first = false;
784     }
785     if angle_open {
786         write!(f, ">")?;
787     }
788     Ok(())
789 }
790
791 impl TraitRef {
792     fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
793         if f.should_truncate() {
794             return write!(f, "{}", TYPE_HINT_TRUNCATION);
795         }
796
797         self.self_type_parameter(&Interner).hir_fmt(f)?;
798         if use_as {
799             write!(f, " as ")?;
800         } else {
801             write!(f, ": ")?;
802         }
803         write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
804         if self.substitution.len(&Interner) > 1 {
805             write!(f, "<")?;
806             f.write_joined(&self.substitution.interned()[1..], ", ")?;
807             write!(f, ">")?;
808         }
809         Ok(())
810     }
811 }
812
813 impl HirDisplay for TraitRef {
814     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
815         self.hir_fmt_ext(f, false)
816     }
817 }
818
819 impl HirDisplay for WhereClause {
820     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
821         if f.should_truncate() {
822             return write!(f, "{}", TYPE_HINT_TRUNCATION);
823         }
824
825         match self {
826             WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
827             WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
828                 write!(f, "<")?;
829                 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
830                 write!(
831                     f,
832                     ">::{} = ",
833                     f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
834                 )?;
835                 ty.hir_fmt(f)?;
836             }
837             WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
838         }
839         Ok(())
840     }
841 }
842
843 impl HirDisplay for LifetimeOutlives {
844     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
845         self.a.hir_fmt(f)?;
846         write!(f, ": ")?;
847         self.b.hir_fmt(f)
848     }
849 }
850
851 impl HirDisplay for Lifetime {
852     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
853         self.interned().hir_fmt(f)
854     }
855 }
856
857 impl HirDisplay for LifetimeData {
858     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
859         match self {
860             LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
861             LifetimeData::InferenceVar(_) => write!(f, "_"),
862             LifetimeData::Placeholder(idx) => {
863                 let id = lt_from_placeholder_idx(f.db, *idx);
864                 let generics = generics(f.db.upcast(), id.parent);
865                 let param_data = &generics.params.lifetimes[id.local_id];
866                 write!(f, "{}", param_data.name)
867             }
868             LifetimeData::Static => write!(f, "'static"),
869             LifetimeData::Empty(_) => Ok(()),
870             LifetimeData::Erased => Ok(()),
871             LifetimeData::Phantom(_, _) => Ok(()),
872         }
873     }
874 }
875
876 impl HirDisplay for DomainGoal {
877     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
878         match self {
879             DomainGoal::Holds(wc) => {
880                 write!(f, "Holds(")?;
881                 wc.hir_fmt(f)?;
882                 write!(f, ")")
883             }
884         }
885     }
886 }
887
888 pub fn write_visibility(
889     module_id: ModuleId,
890     vis: Visibility,
891     f: &mut HirFormatter,
892 ) -> Result<(), HirDisplayError> {
893     match vis {
894         Visibility::Public => write!(f, "pub "),
895         Visibility::Module(vis_id) => {
896             let def_map = module_id.def_map(f.db.upcast());
897             let root_module_id = def_map.module_id(def_map.root());
898             if vis_id == module_id {
899                 // pub(self) or omitted
900                 Ok(())
901             } else if root_module_id == vis_id {
902                 write!(f, "pub(crate) ")
903             } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) {
904                 write!(f, "pub(super) ")
905             } else {
906                 write!(f, "pub(in ...) ")
907             }
908         }
909     }
910 }
911
912 impl HirDisplay for TypeRef {
913     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
914         match self {
915             TypeRef::Never => write!(f, "!")?,
916             TypeRef::Placeholder => write!(f, "_")?,
917             TypeRef::Tuple(elems) => {
918                 write!(f, "(")?;
919                 f.write_joined(elems, ", ")?;
920                 if elems.len() == 1 {
921                     write!(f, ",")?;
922                 }
923                 write!(f, ")")?;
924             }
925             TypeRef::Path(path) => path.hir_fmt(f)?,
926             TypeRef::RawPtr(inner, mutability) => {
927                 let mutability = match mutability {
928                     hir_def::type_ref::Mutability::Shared => "*const ",
929                     hir_def::type_ref::Mutability::Mut => "*mut ",
930                 };
931                 write!(f, "{}", mutability)?;
932                 inner.hir_fmt(f)?;
933             }
934             TypeRef::Reference(inner, lifetime, mutability) => {
935                 let mutability = match mutability {
936                     hir_def::type_ref::Mutability::Shared => "",
937                     hir_def::type_ref::Mutability::Mut => "mut ",
938                 };
939                 write!(f, "&")?;
940                 if let Some(lifetime) = lifetime {
941                     write!(f, "{} ", lifetime.name)?;
942                 }
943                 write!(f, "{}", mutability)?;
944                 inner.hir_fmt(f)?;
945             }
946             TypeRef::Array(inner) => {
947                 write!(f, "[")?;
948                 inner.hir_fmt(f)?;
949                 // FIXME: Array length?
950                 write!(f, "; _]")?;
951             }
952             TypeRef::Slice(inner) => {
953                 write!(f, "[")?;
954                 inner.hir_fmt(f)?;
955                 write!(f, "]")?;
956             }
957             TypeRef::Fn(tys, is_varargs) => {
958                 // FIXME: Function pointer qualifiers.
959                 write!(f, "fn(")?;
960                 f.write_joined(&tys[..tys.len() - 1], ", ")?;
961                 if *is_varargs {
962                     write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?;
963                 }
964                 write!(f, ")")?;
965                 let ret_ty = tys.last().unwrap();
966                 match ret_ty {
967                     TypeRef::Tuple(tup) if tup.is_empty() => {}
968                     _ => {
969                         write!(f, " -> ")?;
970                         ret_ty.hir_fmt(f)?;
971                     }
972                 }
973             }
974             TypeRef::ImplTrait(bounds) => {
975                 write!(f, "impl ")?;
976                 f.write_joined(bounds, " + ")?;
977             }
978             TypeRef::DynTrait(bounds) => {
979                 write!(f, "dyn ")?;
980                 f.write_joined(bounds, " + ")?;
981             }
982             TypeRef::Error => write!(f, "{{error}}")?,
983         }
984         Ok(())
985     }
986 }
987
988 impl HirDisplay for TypeBound {
989     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
990         match self {
991             TypeBound::Path(path) => path.hir_fmt(f),
992             TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
993             TypeBound::Error => write!(f, "{{error}}"),
994         }
995     }
996 }
997
998 impl HirDisplay for Path {
999     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1000         match (self.type_anchor(), self.kind()) {
1001             (Some(anchor), _) => {
1002                 write!(f, "<")?;
1003                 anchor.hir_fmt(f)?;
1004                 write!(f, ">")?;
1005             }
1006             (_, PathKind::Plain) => {}
1007             (_, PathKind::Abs) => write!(f, "::")?,
1008             (_, PathKind::Crate) => write!(f, "crate")?,
1009             (_, PathKind::Super(0)) => write!(f, "self")?,
1010             (_, PathKind::Super(n)) => {
1011                 write!(f, "super")?;
1012                 for _ in 0..*n {
1013                     write!(f, "::super")?;
1014                 }
1015             }
1016             (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?,
1017         }
1018
1019         for (seg_idx, segment) in self.segments().iter().enumerate() {
1020             if seg_idx != 0 {
1021                 write!(f, "::")?;
1022             }
1023             write!(f, "{}", segment.name)?;
1024             if let Some(generic_args) = segment.args_and_bindings {
1025                 // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
1026                 // Do we actually format expressions?
1027                 write!(f, "<")?;
1028                 let mut first = true;
1029                 for arg in &generic_args.args {
1030                     if first {
1031                         first = false;
1032                         if generic_args.has_self_type {
1033                             // FIXME: Convert to `<Ty as Trait>` form.
1034                             write!(f, "Self = ")?;
1035                         }
1036                     } else {
1037                         write!(f, ", ")?;
1038                     }
1039                     arg.hir_fmt(f)?;
1040                 }
1041                 for binding in &generic_args.bindings {
1042                     if first {
1043                         first = false;
1044                     } else {
1045                         write!(f, ", ")?;
1046                     }
1047                     write!(f, "{}", binding.name)?;
1048                     match &binding.type_ref {
1049                         Some(ty) => {
1050                             write!(f, " = ")?;
1051                             ty.hir_fmt(f)?
1052                         }
1053                         None => {
1054                             write!(f, ": ")?;
1055                             f.write_joined(&binding.bounds, " + ")?;
1056                         }
1057                     }
1058                 }
1059                 write!(f, ">")?;
1060             }
1061         }
1062         Ok(())
1063     }
1064 }
1065
1066 impl HirDisplay for hir_def::path::GenericArg {
1067     fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1068         match self {
1069             hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1070             hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1071         }
1072     }
1073 }