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