ra_ap_hir_ty/
display.rs

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