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