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