src/tools/rust-analyzer/crates/hir-ty/src/display.rs RUST 2,813 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,813.
1//! The `HirDisplay` trait, which serves two purposes: Turning various bits from2//! HIR back into source code, and just displaying them for debugging/testing3//! purposes.45use std::{6    fmt::{self, Debug},7    mem,8};910use base_db::{Crate, FxIndexMap};11use either::Either;12use hir_def::{13    ExpressionStoreOwnerId, FindPathConfig, GenericDefId, GenericParamId, HasModule,14    ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId, TypeAliasId,15    expr_store::{ExpressionStore, path::Path},16    find_path::{self, PrefixKind},17    hir::{18        ClosureKind as HirClosureKind, CoroutineKind, PatId,19        generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},20    },21    item_scope::ItemInNs,22    item_tree::FieldsShape,23    lang_item::LangItems,24    signatures::{25        ConstSignature, EnumSignature, FunctionSignature, StaticSignature, StructSignature,26        TraitSignature, TypeAliasSignature, UnionSignature, VariantFields,27    },28    type_ref::{29        ConstRef, LifetimeRef, LifetimeRefId, TraitBoundModifier, TypeBound, TypeRef, TypeRefId,30        UseArgRef,31    },32    visibility::Visibility,33};34use hir_expand::{mod_path::PathKind, name::Name};35use intern::{Internable, Interned, sym};36use itertools::Itertools;37use la_arena::ArenaMap;38use rustc_abi::ExternAbi;39use rustc_apfloat::{40    Float,41    ieee::{Half as f16, Quad as f128},42};43use rustc_ast_ir::FloatTy;44use rustc_hash::FxHashSet;45use rustc_type_ir::{46    AliasTyKind, BoundVarIndexKind, CoroutineArgsParts, RegionKind, Upcast,47    inherent::{GenericArgs as _, IntoKind, Term as _, Ty as _, Tys as _},48};49use smallvec::SmallVec;50use span::Edition;51use stdx::never;5253use crate::{54    CallableDefId, FieldType, ImplTraitId, MemoryMap, ParamEnvAndCrate, consteval,55    db::{GeneralConstId, HirDatabase},56    generics::{ProvenanceSplit, generics},57    layout::Layout,58    lower::GenericPredicates,59    mir::pad16,60    next_solver::{61        AliasTy, Allocation, Clause, ClauseKind, Const, ConstKind, DbInterner,62        ExistentialPredicate, FnSig, GenericArg, GenericArgKind, GenericArgs, ParamEnv, PolyFnSig,63        Region, Term, TermId, TermKind, TraitPredicate, TraitRef, Ty, TyKind, TypingMode,64        Unnormalized, ValTree,65        abi::Safety,66        infer::{DbInternerInferExt, traits::ObligationCause},67    },68    primitive,69    utils::{detect_variant_from_bytes, fn_traits},70};7172fn async_gen_item_ty_from_yield_ty<'db>(73    lang_items: &LangItems,74    yield_ty: Ty<'db>,75) -> Option<Ty<'db>> {76    let poll_id = lang_items.Poll.map(hir_def::AdtId::EnumId)?;77    let option_id = lang_items.Option.map(hir_def::AdtId::EnumId)?;7879    let TyKind::Adt(poll_def, poll_args) = yield_ty.kind() else {80        return None;81    };82    if poll_def.def_id() != poll_id {83        return None;84    }85    let [poll_inner] = poll_args.as_slice() else {86        return None;87    };88    let poll_inner = poll_inner.ty()?;8990    let TyKind::Adt(option_def, option_args) = poll_inner.kind() else {91        return None;92    };93    if option_def.def_id() != option_id {94        return None;95    }96    let [item] = option_args.as_slice() else {97        return None;98    };99    item.ty()100}101102pub type Result<T = (), E = HirDisplayError> = std::result::Result<T, E>;103104pub trait HirWrite: fmt::Write {105    fn start_location_link(&mut self, _location: ModuleDefId) {}106    fn start_location_link_generic(&mut self, _location: GenericParamId) {}107    fn end_location_link(&mut self) {}108}109110// String will ignore link metadata111impl HirWrite for String {}112113// `core::Formatter` will ignore metadata114impl HirWrite for fmt::Formatter<'_> {}115116pub struct HirFormatter<'a, 'db> {117    /// The database handle118    pub db: &'db dyn HirDatabase,119    pub interner: DbInterner<'db>,120    /// The sink to write into121    fmt: &'a mut dyn HirWrite,122    /// A buffer to intercept writes with, this allows us to track the overall size of the formatted output.123    buf: String,124    /// The current size of the formatted output.125    curr_size: usize,126    /// Size from which we should truncate the output.127    max_size: Option<usize>,128    /// When rendering something that has a concept of "children" (like fields in a struct), this limits129    /// how many should be rendered.130    pub entity_limit: Option<usize>,131    /// When rendering functions, whether to show the constraint from the container132    show_container_bounds: bool,133    omit_verbose_types: bool,134    closure_style: ClosureStyle,135    display_lifetimes: DisplayLifetime,136    display_kind: DisplayKind,137    display_target: DisplayTarget,138    /// We can have recursive bounds like the following case:139    /// ```ignore140    /// where141    ///     T: Foo,142    ///     T::FooAssoc: Baz<<T::FooAssoc as Bar>::BarAssoc> + Bar143    /// ```144    /// So, record the projection types met while formatting bounds and145    /// prevent recursing into their bounds to avoid infinite loops.146    currently_formatting_bounds: FxHashSet<AliasTy<'db>>,147    /// Whether formatting `impl Trait1 + Trait2` or `dyn Trait1 + Trait2` needs parentheses around it,148    /// for example when formatting `&(impl Trait1 + Trait2)`.149    trait_bounds_need_parens: bool,150}151152// FIXME: To consider, ref and dyn trait lifetimes can be omitted if they are `'_`, path args should153// not be when in signatures154// So this enum does not encode this well enough155// Also 'static can be omitted for ref and dyn trait lifetimes in static/const item types156// FIXME: Also named lifetimes may be rendered in places where their name is not in scope?157#[derive(Copy, Clone)]158pub enum DisplayLifetime {159    Always,160    OnlyStatic,161    OnlyNamed,162    OnlyNamedOrStatic,163    Never,164}165166impl<'db> HirFormatter<'_, 'db> {167    pub fn start_location_link(&mut self, location: ModuleDefId) {168        self.fmt.start_location_link(location);169    }170171    pub fn start_location_link_generic(&mut self, location: GenericParamId) {172        self.fmt.start_location_link_generic(location);173    }174175    pub fn end_location_link(&mut self) {176        self.fmt.end_location_link();177    }178179    fn format_bounds_with<F: FnOnce(&mut Self) -> Result>(180        &mut self,181        target: AliasTy<'db>,182        format_bounds: F,183    ) -> Result {184        if self.currently_formatting_bounds.insert(target) {185            let result = format_bounds(self);186            self.currently_formatting_bounds.remove(&target);187            result188        } else {189            if self.display_kind.is_source_code() {190                Err(HirDisplayError::DisplaySourceCodeError(DisplaySourceCodeError::Cycle))191            } else {192                match target.kind {193                    AliasTyKind::Projection { def_id } => {194                        let def_id = def_id.0;195                        let ItemContainerId::TraitId(trait_) = def_id.loc(self.db).container else {196                            panic!("expected an assoc type");197                        };198                        let trait_name = &TraitSignature::of(self.db, trait_).name;199                        let assoc_type_name = &TypeAliasSignature::of(self.db, def_id).name;200                        write!(201                            self,202                            "<… as {}>::{}",203                            trait_name.display(self.db, self.edition()),204                            assoc_type_name.display(self.db, self.edition()),205                        )?;206                        if target.args.len() > 1 {207                            self.write_str("<…>")?;208                        }209                        Ok(())210                    }211                    AliasTyKind::Inherent { .. }212                    | AliasTyKind::Opaque { .. }213                    | AliasTyKind::Free { .. } => self.write_str("…"),214                }215            }216        }217    }218219    fn render_region(&self, lifetime: Region<'db>) -> bool {220        match self.display_lifetimes {221            DisplayLifetime::Always => true,222            DisplayLifetime::OnlyStatic => matches!(lifetime.kind(), RegionKind::ReStatic),223            DisplayLifetime::OnlyNamed => {224                matches!(lifetime.kind(), RegionKind::ReEarlyParam(_))225            }226            DisplayLifetime::OnlyNamedOrStatic => {227                matches!(lifetime.kind(), RegionKind::ReStatic | RegionKind::ReEarlyParam(_))228            }229            DisplayLifetime::Never => false,230        }231    }232}233234pub trait HirDisplay<'db> {235    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result;236237    /// Returns a `Display`able type that is human-readable.238    fn into_displayable<'a>(239        &'a self,240        db: &'db dyn HirDatabase,241        max_size: Option<usize>,242        limited_size: Option<usize>,243        omit_verbose_types: bool,244        display_target: DisplayTarget,245        display_kind: DisplayKind,246        closure_style: ClosureStyle,247        show_container_bounds: bool,248    ) -> HirDisplayWrapper<'a, 'db, Self>249    where250        Self: Sized,251    {252        assert!(253            !matches!(display_kind, DisplayKind::SourceCode { .. }),254            "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"255        );256        HirDisplayWrapper {257            db,258            t: self,259            max_size,260            limited_size,261            omit_verbose_types,262            display_target,263            display_kind,264            closure_style,265            show_container_bounds,266            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,267        }268    }269270    /// Returns a `Display`able type that is human-readable.271    /// Use this for showing types to the user (e.g. diagnostics)272    fn display<'a>(273        &'a self,274        db: &'db dyn HirDatabase,275        display_target: DisplayTarget,276    ) -> HirDisplayWrapper<'a, 'db, Self>277    where278        Self: Sized,279    {280        HirDisplayWrapper {281            db,282            t: self,283            max_size: None,284            limited_size: None,285            omit_verbose_types: false,286            closure_style: ClosureStyle::ImplFn,287            display_target,288            display_kind: DisplayKind::Diagnostics,289            show_container_bounds: false,290            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,291        }292    }293294    /// Returns a `Display`able type that is human-readable and tries to be succinct.295    /// Use this for showing types to the user where space is constrained (e.g. doc popups)296    fn display_truncated<'a>(297        &'a self,298        db: &'db dyn HirDatabase,299        max_size: Option<usize>,300        display_target: DisplayTarget,301    ) -> HirDisplayWrapper<'a, 'db, Self>302    where303        Self: Sized,304    {305        HirDisplayWrapper {306            db,307            t: self,308            max_size,309            limited_size: None,310            omit_verbose_types: true,311            closure_style: ClosureStyle::ImplFn,312            display_target,313            display_kind: DisplayKind::Diagnostics,314            show_container_bounds: false,315            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,316        }317    }318319    /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside.320    /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum`321    fn display_limited<'a>(322        &'a self,323        db: &'db dyn HirDatabase,324        limited_size: Option<usize>,325        display_target: DisplayTarget,326    ) -> HirDisplayWrapper<'a, 'db, Self>327    where328        Self: Sized,329    {330        HirDisplayWrapper {331            db,332            t: self,333            max_size: None,334            limited_size,335            omit_verbose_types: true,336            closure_style: ClosureStyle::ImplFn,337            display_target,338            display_kind: DisplayKind::Diagnostics,339            show_container_bounds: false,340            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,341        }342    }343344    /// Returns a String representation of `self` that can be inserted into the given module.345    /// Use this when generating code (e.g. assists)346    fn display_source_code<'a>(347        &'a self,348        db: &'db dyn HirDatabase,349        module_id: ModuleId,350        allow_opaque: bool,351    ) -> Result<String, DisplaySourceCodeError> {352        let mut result = String::new();353        let interner = DbInterner::new_with(db, module_id.krate(db));354        match self.hir_fmt(&mut HirFormatter {355            db,356            interner,357            fmt: &mut result,358            buf: String::with_capacity(20),359            curr_size: 0,360            max_size: None,361            entity_limit: None,362            omit_verbose_types: false,363            closure_style: ClosureStyle::ImplFn,364            display_target: DisplayTarget::from_crate(db, module_id.krate(db)),365            display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },366            show_container_bounds: false,367            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,368            currently_formatting_bounds: Default::default(),369            trait_bounds_need_parens: false,370        }) {371            Ok(()) => {}372            Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),373            Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),374        };375        Ok(result)376    }377378    /// Returns a String representation of `self` for test purposes379    fn display_test<'a>(380        &'a self,381        db: &'db dyn HirDatabase,382        display_target: DisplayTarget,383    ) -> HirDisplayWrapper<'a, 'db, Self>384    where385        Self: Sized,386    {387        HirDisplayWrapper {388            db,389            t: self,390            max_size: None,391            limited_size: None,392            omit_verbose_types: false,393            closure_style: ClosureStyle::ImplFn,394            display_target,395            display_kind: DisplayKind::Test,396            show_container_bounds: false,397            display_lifetimes: DisplayLifetime::Always,398        }399    }400401    /// Returns a String representation of `self` that shows the constraint from402    /// the container for functions403    fn display_with_container_bounds<'a>(404        &'a self,405        db: &'db dyn HirDatabase,406        show_container_bounds: bool,407        display_target: DisplayTarget,408    ) -> HirDisplayWrapper<'a, 'db, Self>409    where410        Self: Sized,411    {412        HirDisplayWrapper {413            db,414            t: self,415            max_size: None,416            limited_size: None,417            omit_verbose_types: false,418            closure_style: ClosureStyle::ImplFn,419            display_target,420            display_kind: DisplayKind::Diagnostics,421            show_container_bounds,422            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,423        }424    }425}426427impl<'db> HirFormatter<'_, 'db> {428    pub fn krate(&self) -> Crate {429        self.display_target.krate430    }431432    pub fn edition(&self) -> Edition {433        self.display_target.edition434    }435436    #[inline]437    pub fn lang_items(&self) -> &'db LangItems {438        self.interner.lang_items()439    }440441    pub fn write_joined<T: HirDisplay<'db>>(442        &mut self,443        iter: impl IntoIterator<Item = T>,444        sep: &str,445    ) -> Result {446        let mut first = true;447        for e in iter {448            if !first {449                write!(self, "{sep}")?;450            }451            first = false;452453            // Abbreviate multiple omitted types with a single ellipsis.454            if self.should_truncate() {455                return write!(self, "{TYPE_HINT_TRUNCATION}");456            }457458            e.hir_fmt(self)?;459        }460        Ok(())461    }462463    /// This allows using the `write!` macro directly with a `HirFormatter`.464    pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result {465        // We write to a buffer first to track output size466        self.buf.clear();467        fmt::write(&mut self.buf, args)?;468        self.curr_size += self.buf.len();469470        // Then we write to the internal formatter from the buffer471        self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)472    }473474    pub fn write_str(&mut self, s: &str) -> Result {475        self.fmt.write_str(s)?;476        Ok(())477    }478479    pub fn write_char(&mut self, c: char) -> Result {480        self.fmt.write_char(c)?;481        Ok(())482    }483484    pub fn should_truncate(&self) -> bool {485        match self.max_size {486            Some(max_size) => self.curr_size >= max_size,487            None => false,488        }489    }490491    pub fn omit_verbose_types(&self) -> bool {492        self.omit_verbose_types493    }494495    pub fn show_container_bounds(&self) -> bool {496        self.show_container_bounds497    }498}499500#[derive(Debug, Clone, Copy)]501pub struct DisplayTarget {502    krate: Crate,503    pub edition: Edition,504}505506impl DisplayTarget {507    pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self {508        let edition = krate.data(db).edition;509        Self { krate, edition }510    }511}512513#[derive(Clone, Copy)]514pub enum DisplayKind {515    /// Display types for inlays, doc popups, autocompletion, etc...516    /// Showing `{unknown}` or not qualifying paths is fine here.517    /// There's no reason for this to fail.518    Diagnostics,519    /// Display types for inserting them in source files.520    /// The generated code should compile, so paths need to be qualified.521    SourceCode { target_module_id: ModuleId, allow_opaque: bool },522    /// Only for test purpose to keep real types523    Test,524}525526impl DisplayKind {527    fn is_source_code(self) -> bool {528        matches!(self, Self::SourceCode { .. })529    }530531    fn allows_opaque(self) -> bool {532        match self {533            Self::SourceCode { allow_opaque, .. } => allow_opaque,534            _ => true,535        }536    }537}538539#[derive(Debug)]540pub enum DisplaySourceCodeError {541    PathNotFound,542    Coroutine,543    OpaqueType,544    Cycle,545}546547pub enum HirDisplayError {548    /// Errors that can occur when generating source code549    DisplaySourceCodeError(DisplaySourceCodeError),550    /// `FmtError` is required to be compatible with std::fmt::Display551    FmtError,552}553impl From<fmt::Error> for HirDisplayError {554    fn from(_: fmt::Error) -> Self {555        Self::FmtError556    }557}558559pub struct HirDisplayWrapper<'a, 'db, T> {560    db: &'db dyn HirDatabase,561    t: &'a T,562    max_size: Option<usize>,563    limited_size: Option<usize>,564    omit_verbose_types: bool,565    closure_style: ClosureStyle,566    display_kind: DisplayKind,567    display_target: DisplayTarget,568    show_container_bounds: bool,569    display_lifetimes: DisplayLifetime,570}571572#[derive(Debug, PartialEq, Eq, Clone, Copy)]573pub enum ClosureStyle {574    /// `impl FnX(i32, i32) -> i32`, where `FnX` is the most special trait between `Fn`, `FnMut`, `FnOnce` that the575    /// closure implements. This is the default.576    ImplFn,577    /// `|i32, i32| -> i32`578    RANotation,579    /// `{closure#14825}`, useful for some diagnostics (like type mismatch) and internal usage.580    ClosureWithId,581    /// `{closure#14825}<i32, ()>`, useful for internal usage.582    ClosureWithSubst,583    /// `…`, which is the `TYPE_HINT_TRUNCATION`584    Hide,585}586587impl<'db, T: HirDisplay<'db>> HirDisplayWrapper<'_, 'db, T> {588    pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result {589        let krate = self.display_target.krate;590        let interner = DbInterner::new_with(self.db, krate);591        self.t.hir_fmt(&mut HirFormatter {592            db: self.db,593            interner,594            fmt: f,595            buf: String::with_capacity(self.max_size.unwrap_or(20)),596            curr_size: 0,597            max_size: self.max_size,598            entity_limit: self.limited_size,599            omit_verbose_types: self.omit_verbose_types,600            display_kind: self.display_kind,601            display_target: self.display_target,602            closure_style: self.closure_style,603            show_container_bounds: self.show_container_bounds,604            display_lifetimes: self.display_lifetimes,605            currently_formatting_bounds: Default::default(),606            trait_bounds_need_parens: false,607        })608    }609610    pub fn with_closure_style(mut self, c: ClosureStyle) -> Self {611        self.closure_style = c;612        self613    }614615    pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self {616        self.display_lifetimes = l;617        self618    }619}620621impl<'db, T> fmt::Display for HirDisplayWrapper<'_, 'db, T>622where623    T: HirDisplay<'db>,624{625    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {626        match self.write_to(f) {627            Ok(()) => Ok(()),628            Err(HirDisplayError::FmtError) => Err(fmt::Error),629            Err(HirDisplayError::DisplaySourceCodeError(_)) => {630                // This should never happen631                panic!(632                    "HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!"633                )634            }635        }636    }637}638639const TYPE_HINT_TRUNCATION: &str = "…";640641impl<'db, T: HirDisplay<'db>> HirDisplay<'db> for &T {642    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {643        HirDisplay::hir_fmt(*self, f)644    }645}646647impl<'db, T: HirDisplay<'db> + Internable> HirDisplay<'db> for Interned<T> {648    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {649        HirDisplay::hir_fmt(&**self, f)650    }651}652653fn write_projection<'db>(654    f: &mut HirFormatter<'_, 'db>,655    alias: &AliasTy<'db>,656    needs_parens_if_multi: bool,657    def_id: TypeAliasId,658) -> Result {659    f.format_bounds_with(*alias, |f| {660        if f.should_truncate() {661            return write!(f, "{TYPE_HINT_TRUNCATION}");662        }663        let trait_ref = alias.trait_ref(f.interner);664        let self_ty = trait_ref.self_ty();665666        // if we are projection on a type parameter, check if the projection target has bounds667        // itself, if so, we render them directly as `impl Bound` instead of the less useful668        // `<Param as Trait>::Assoc`669        if !f.display_kind.is_source_code()670            && let TyKind::Param(param) = self_ty.kind()671        {672            // FIXME: We shouldn't use `param.id`, it should be removed. We should know the673            // `GenericDefId` from the formatted type (store it inside the `HirFormatter`).674            let bounds = GenericPredicates::query_all(f.db, param.id.parent())675                .iter_identity()676                .map(Unnormalized::skip_norm_wip)677                .filter(|wc| {678                    let ty = match wc.kind().skip_binder() {679                        ClauseKind::Trait(tr) => tr.self_ty(),680                        ClauseKind::TypeOutlives(t) => t.0,681                        _ => return false,682                    };683                    let TyKind::Alias(a) = ty.kind() else {684                        return false;685                    };686                    a == *alias687                })688                .collect::<Vec<_>>();689            if !bounds.is_empty() {690                return write_bounds_like_dyn_trait_with_prefix(691                    f,692                    "impl",693                    Either::Left(Ty::new_alias(f.interner, *alias)),694                    &bounds,695                    SizedByDefault::NotSized,696                    needs_parens_if_multi,697                );698            }699        }700701        write!(f, "<")?;702        self_ty.hir_fmt(f)?;703        write!(f, " as ")?;704        trait_ref.hir_fmt(f)?;705        write!(f, ">::{}", TypeAliasSignature::of(f.db, def_id).name.display(f.db, f.edition()))?;706        let proj_params = &alias.args.as_slice()[trait_ref.args.len()..];707        hir_fmt_generics(f, proj_params, None, None)708    })709}710711impl<'db> HirDisplay<'db> for GenericArg<'db> {712    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {713        match self.kind() {714            GenericArgKind::Type(ty) => ty.hir_fmt(f),715            GenericArgKind::Lifetime(lt) => lt.hir_fmt(f),716            GenericArgKind::Const(c) => c.hir_fmt(f),717        }718    }719}720721impl<'db> HirDisplay<'db> for Allocation<'db> {722    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {723        render_const_scalar(f, &self.memory, &self.memory_map, self.ty)724    }725}726727impl<'db> HirDisplay<'db> for Const<'db> {728    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {729        match self.kind() {730            ConstKind::Placeholder(_) => write!(f, "<placeholder>"),731            ConstKind::Bound(BoundVarIndexKind::Bound(db), bound_const) => {732                write!(f, "?{}.{}", db.as_u32(), bound_const.var.as_u32())733            }734            ConstKind::Bound(BoundVarIndexKind::Canonical, bound_const) => {735                write!(f, "?c.{}", bound_const.var.as_u32())736            }737            ConstKind::Infer(..) => write!(f, "#c#"),738            ConstKind::Param(param) => {739                let generics = GenericParams::of(f.db, param.id.parent());740                let param_data = &generics[param.id.local_id()];741                f.start_location_link_generic(param.id.into());742                write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;743                f.end_location_link();744                Ok(())745            }746            ConstKind::Value(value) => render_const_scalar_from_valtree(f, value.ty, value.value),747            ConstKind::Unevaluated(unev) => {748                let c = unev.def.0;749                match c {750                    GeneralConstId::ConstId(id) => match &ConstSignature::of(f.db, id).name {751                        Some(name) => {752                            f.start_location_link(id.into());753                            write!(f, "{}", name.display(f.db, f.edition()))?;754                            f.end_location_link();755                        }756                        None => f.write_str("_")?,757                    },758                    GeneralConstId::StaticId(id) => {759                        let name = &StaticSignature::of(f.db, id).name;760                        f.start_location_link(id.into());761                        write!(f, "{}", name.display(f.db, f.edition()))?;762                        f.end_location_link();763                    }764                    GeneralConstId::AnonConstId(_) => {765                        f.write_str(if f.display_kind.is_source_code() { "_" } else { "{const}" })?766                    }767                };768                hir_fmt_generics(f, unev.args.as_slice(), c.generic_def(f.db), None)?;769                Ok(())770            }771            ConstKind::Error(..) => f.write_char('_'),772            ConstKind::Expr(..) => write!(f, "<const-expr>"),773        }774    }775}776777fn render_const_scalar<'db>(778    f: &mut HirFormatter<'_, 'db>,779    b: &[u8],780    memory_map: &MemoryMap<'db>,781    ty: Ty<'db>,782) -> Result {783    let param_env = ParamEnv::empty(f.interner);784    let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis);785    let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty);786    render_const_scalar_inner(f, b, memory_map, ty, param_env)787}788789fn render_const_scalar_inner<'db>(790    f: &mut HirFormatter<'_, 'db>,791    b: &[u8],792    memory_map: &MemoryMap<'db>,793    ty: Ty<'db>,794    param_env: ParamEnv<'db>,795) -> Result {796    use TyKind;797    let param_env = ParamEnvAndCrate { param_env, krate: f.krate() };798    match ty.kind() {799        TyKind::Bool => write!(f, "{}", b[0] != 0),800        TyKind::Char => {801            let it = u128::from_le_bytes(pad16(b, false)) as u32;802            let Ok(c) = char::try_from(it) else {803                return f.write_str("<unicode-error>");804            };805            write!(f, "{c:?}")806        }807        TyKind::Int(_) => {808            let it = i128::from_le_bytes(pad16(b, true));809            write!(f, "{it}")810        }811        TyKind::Uint(_) => {812            let it = u128::from_le_bytes(pad16(b, false));813            write!(f, "{it}")814        }815        TyKind::Float(fl) => match fl {816            FloatTy::F16 => {817                // FIXME(#17451): Replace with builtins once they are stabilised.818                let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());819                let s = it.to_string();820                if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {821                    // Match Rust debug formatting822                    write!(f, "{s}.0")823                } else {824                    write!(f, "{s}")825                }826            }827            FloatTy::F32 => {828                let it = f32::from_le_bytes(b.try_into().unwrap());829                write!(f, "{it:?}")830            }831            FloatTy::F64 => {832                let it = f64::from_le_bytes(b.try_into().unwrap());833                write!(f, "{it:?}")834            }835            FloatTy::F128 => {836                // FIXME(#17451): Replace with builtins once they are stabilised.837                let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));838                let s = it.to_string();839                if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {840                    // Match Rust debug formatting841                    write!(f, "{s}.0")842                } else {843                    write!(f, "{s}")844                }845            }846        },847        TyKind::Ref(_, t, _) => match t.kind() {848            TyKind::Str => {849                let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());850                let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());851                let Some(bytes) = memory_map.get(addr, size) else {852                    return f.write_str("<ref-data-not-available>");853                };854                let s = std::str::from_utf8(bytes).unwrap_or("<utf8-error>");855                write!(f, "{s:?}")856            }857            TyKind::Slice(ty) => {858                let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());859                let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());860                let Ok(layout) = f.db.layout_of_ty(ty.store(), param_env.store()) else {861                    return f.write_str("<layout-error>");862                };863                let size_one = layout.size.bytes_usize();864                let Some(bytes) = memory_map.get(addr, size_one * count) else {865                    return f.write_str("<ref-data-not-available>");866                };867                let expected_len = count * size_one;868                if bytes.len() < expected_len {869                    never!(870                        "Memory map size is too small. Expected {expected_len}, got {}",871                        bytes.len(),872                    );873                    return f.write_str("<layout-error>");874                }875                f.write_str("&[")?;876                let mut first = true;877                for i in 0..count {878                    if first {879                        first = false;880                    } else {881                        f.write_str(", ")?;882                    }883                    let offset = size_one * i;884                    render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, ty)?;885                }886                f.write_str("]")887            }888            TyKind::Dynamic(_, _) => {889                let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());890                let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());891                let Ok(t) = memory_map.vtable_ty(ty_id) else {892                    return f.write_str("<ty-missing-in-vtable-map>");893                };894                let Ok(layout) = f.db.layout_of_ty(t.store(), param_env.store()) else {895                    return f.write_str("<layout-error>");896                };897                let size = layout.size.bytes_usize();898                let Some(bytes) = memory_map.get(addr, size) else {899                    return f.write_str("<ref-data-not-available>");900                };901                f.write_str("&")?;902                render_const_scalar(f, bytes, memory_map, t)903            }904            TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.def_id() {905                hir_def::AdtId::StructId(s) => {906                    let data = StructSignature::of(f.db, s);907                    write!(f, "&{}", data.name.display(f.db, f.edition()))?;908                    Ok(())909                }910                _ => f.write_str("<unsized-enum-or-union>"),911            },912            _ => {913                let addr = usize::from_le_bytes(match b.try_into() {914                    Ok(b) => b,915                    Err(_) => {916                        never!(917                            "tried rendering ty {:?} in const ref with incorrect byte count {}",918                            t,919                            b.len()920                        );921                        return f.write_str("<layout-error>");922                    }923                });924                let Ok(layout) = f.db.layout_of_ty(t.store(), param_env.store()) else {925                    return f.write_str("<layout-error>");926                };927                let size = layout.size.bytes_usize();928                let Some(bytes) = memory_map.get(addr, size) else {929                    return f.write_str("<ref-data-not-available>");930                };931                f.write_str("&")?;932                render_const_scalar(f, bytes, memory_map, t)933            }934        },935        TyKind::Tuple(tys) => {936            let Ok(layout) = f.db.layout_of_ty(ty.store(), param_env.store()) else {937                return f.write_str("<layout-error>");938            };939            f.write_str("(")?;940            let mut first = true;941            for (id, ty) in tys.iter().enumerate() {942                if first {943                    first = false;944                } else {945                    f.write_str(", ")?;946                }947                let offset = layout.fields.offset(id).bytes_usize();948                let Ok(layout) = f.db.layout_of_ty(ty.store(), param_env.store()) else {949                    f.write_str("<layout-error>")?;950                    continue;951                };952                let size = layout.size.bytes_usize();953                render_const_scalar(f, &b[offset..offset + size], memory_map, ty)?;954            }955            f.write_str(")")956        }957        TyKind::Adt(def, args) => {958            let def = def.def_id();959            let Ok(layout) = f.db.layout_of_adt(def, args.store(), param_env.store()) else {960                return f.write_str("<layout-error>");961            };962            match def {963                hir_def::AdtId::StructId(s) => {964                    let data = StructSignature::of(f.db, s);965                    write!(f, "{}", data.name.display(f.db, f.edition()))?;966                    let field_types = f.db.field_types(s.into());967                    render_variant_after_name(968                        s.fields(f.db),969                        f,970                        field_types,971                        f.db.trait_environment(def.into()),972                        &layout,973                        args,974                        b,975                        memory_map,976                    )977                }978                hir_def::AdtId::UnionId(u) => {979                    write!(f, "{}", UnionSignature::of(f.db, u).name.display(f.db, f.edition()))980                }981                hir_def::AdtId::EnumId(e) => {982                    let Ok(target_data_layout) = f.db.target_data_layout(f.krate()) else {983                        return f.write_str("<target-layout-not-available>");984                    };985                    let Some((var_id, var_layout)) =986                        detect_variant_from_bytes(&layout, f.db, target_data_layout, b, e)987                    else {988                        return f.write_str("<failed-to-detect-variant>");989                    };990                    let loc = var_id.lookup(f.db);991                    write!(f, "{}", loc.name.display(f.db, f.edition()))?;992                    let field_types = f.db.field_types(var_id.into());993                    render_variant_after_name(994                        var_id.fields(f.db),995                        f,996                        field_types,997                        f.db.trait_environment(def.into()),998                        var_layout,999                        args,1000                        b,1001                        memory_map,1002                    )1003                }1004            }1005        }1006        TyKind::FnDef(..) => ty.hir_fmt(f),1007        TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {1008            let it = u128::from_le_bytes(pad16(b, false));1009            write!(f, "{it:#X} as ")?;1010            ty.hir_fmt(f)1011        }1012        TyKind::Array(ty, len) => {1013            let Some(len) = consteval::try_const_usize(f.db, len) else {1014                return f.write_str("<unknown-array-len>");1015            };1016            let Ok(layout) = f.db.layout_of_ty(ty.store(), param_env.store()) else {1017                return f.write_str("<layout-error>");1018            };1019            let size_one = layout.size.bytes_usize();1020            f.write_str("[")?;1021            let mut first = true;1022            for i in 0..len as usize {1023                if first {1024                    first = false;1025                } else {1026                    f.write_str(", ")?;1027                }1028                let offset = size_one * i;1029                render_const_scalar(f, &b[offset..offset + size_one], memory_map, ty)?;1030            }1031            f.write_str("]")1032        }1033        TyKind::Never => f.write_str("!"),1034        TyKind::Closure(_, _) => f.write_str("<closure>"),1035        TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),1036        TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),1037        TyKind::CoroutineClosure(_, _) => f.write_str("<coroutine-closure>"),1038        TyKind::UnsafeBinder(_) => f.write_str("<unsafe-binder>"),1039        // The below arms are unreachable, since const eval will bail out before here.1040        TyKind::Foreign(_) => f.write_str("<extern-type>"),1041        TyKind::Pat(_, _) => f.write_str("<pat>"),1042        TyKind::Error(..)1043        | TyKind::Placeholder(_)1044        | TyKind::Alias(..)1045        | TyKind::Param(_)1046        | TyKind::Bound(_, _)1047        | TyKind::Infer(_) => f.write_str("<placeholder-or-unknown-type>"),1048        // The below arms are unreachable, since we handled them in ref case.1049        TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(_, _) => f.write_str("<unsized-value>"),1050    }1051}10521053fn render_const_scalar_from_valtree<'db>(1054    f: &mut HirFormatter<'_, 'db>,1055    ty: Ty<'db>,1056    valtree: ValTree<'db>,1057) -> Result {1058    let param_env = ParamEnv::empty(f.interner);1059    let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis);1060    let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty);1061    render_const_scalar_from_valtree_inner(f, ty, valtree, param_env)1062}10631064fn render_const_scalar_from_valtree_inner<'db>(1065    f: &mut HirFormatter<'_, 'db>,1066    ty: Ty<'db>,1067    valtree: ValTree<'db>,1068    _param_env: ParamEnv<'db>,1069) -> Result {1070    use TyKind;1071    match ty.kind() {1072        TyKind::Bool => write!(f, "{}", valtree.inner().to_leaf().try_to_bool().unwrap()),1073        TyKind::Char => {1074            let it = valtree.inner().to_leaf().to_u32();1075            let Ok(c) = char::try_from(it) else {1076                return f.write_str("<unicode-error>");1077            };1078            write!(f, "{c:?}")1079        }1080        TyKind::Int(_) => {1081            let it = valtree.inner().to_leaf().to_int_unchecked();1082            write!(f, "{it}")1083        }1084        TyKind::Uint(_) => {1085            let it = valtree.inner().to_leaf().to_uint_unchecked();1086            write!(f, "{it}")1087        }1088        TyKind::Float(fl) => match fl {1089            FloatTy::F16 => {1090                // FIXME(#17451): Replace with builtins once they are stabilised.1091                let it = f16::from_bits(valtree.inner().to_leaf().to_u16() as u128);1092                let s = it.to_string();1093                if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {1094                    // Match Rust debug formatting1095                    write!(f, "{s}.0")1096                } else {1097                    write!(f, "{s}")1098                }1099            }1100            FloatTy::F32 => {1101                let it = f32::from_bits(valtree.inner().to_leaf().to_u32());1102                write!(f, "{it:?}")1103            }1104            FloatTy::F64 => {1105                let it = f64::from_bits(valtree.inner().to_leaf().to_u64());1106                write!(f, "{it:?}")1107            }1108            FloatTy::F128 => {1109                // FIXME(#17451): Replace with builtins once they are stabilised.1110                let it = f128::from_bits(valtree.inner().to_leaf().to_u128());1111                let s = it.to_string();1112                if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {1113                    // Match Rust debug formatting1114                    write!(f, "{s}.0")1115                } else {1116                    write!(f, "{s}")1117                }1118            }1119        },1120        TyKind::Ref(_, inner_ty, _) => {1121            render_const_scalar_from_valtree_inner(f, inner_ty, valtree, _param_env)1122        }1123        TyKind::Str => {1124            let bytes = valtree1125                .inner()1126                .to_branch()1127                .iter()1128                .map(|konst| match konst.kind() {1129                    ConstKind::Value(value) => Some(value.value.inner().to_leaf().to_u8()),1130                    _ => None,1131                })1132                .collect::<Option<Vec<_>>>();1133            let Some(bytes) = bytes else { return f.write_str("<invalid-str>") };1134            let s = std::str::from_utf8(&bytes).unwrap_or("<utf8-error>");1135            write!(f, "{s:?}")1136        }1137        TyKind::Slice(inner_ty) | TyKind::Array(inner_ty, _) => {1138            let mut first = true;1139            write!(f, "[")?;1140            for item in valtree.inner().to_branch() {1141                if !first {1142                    write!(f, ", ")?;1143                } else {1144                    first = false;1145                }1146                let ConstKind::Value(value) = item.kind() else {1147                    return f.write_str("<invalid-const>");1148                };1149                render_const_scalar_from_valtree_inner(f, inner_ty, value.value, _param_env)?;1150            }1151            write!(f, "]")1152        }1153        TyKind::Tuple(tys) => {1154            let mut first = true;1155            write!(f, "(")?;1156            for (inner_ty, item) in std::iter::zip(tys, valtree.inner().to_branch()) {1157                if !first {1158                    write!(f, ", ")?;1159                } else {1160                    first = false;1161                }1162                let ConstKind::Value(value) = item.kind() else {1163                    return f.write_str("<invalid-const>");1164                };1165                render_const_scalar_from_valtree_inner(f, inner_ty, value.value, _param_env)?;1166            }1167            write!(f, ")")1168        }1169        TyKind::Adt(..) => {1170            // FIXME: ADTs, requires `adt_const_params`.1171            f.write_str("<adt>")1172        }1173        TyKind::FnDef(..) => ty.hir_fmt(f),1174        TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {1175            let it = valtree.inner().to_leaf().to_uint_unchecked();1176            write!(f, "{it:#X} as ")?;1177            ty.hir_fmt(f)1178        }1179        TyKind::Never => f.write_str("!"),1180        TyKind::Closure(_, _) => f.write_str("<closure>"),1181        TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),1182        TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),1183        TyKind::CoroutineClosure(_, _) => f.write_str("<coroutine-closure>"),1184        TyKind::UnsafeBinder(_) => f.write_str("<unsafe-binder>"),1185        // The below arms are unreachable, since const eval will bail out before here.1186        TyKind::Foreign(_) => f.write_str("<extern-type>"),1187        TyKind::Pat(_, _) => f.write_str("<pat>"),1188        TyKind::Error(..)1189        | TyKind::Placeholder(_)1190        | TyKind::Alias(..)1191        | TyKind::Param(_)1192        | TyKind::Bound(_, _)1193        | TyKind::Infer(_) => f.write_str("<placeholder-or-unknown-type>"),1194        TyKind::Dynamic(_, _) => f.write_str("<dyn-trait>"),1195    }1196}11971198fn render_variant_after_name<'db>(1199    data: &VariantFields,1200    f: &mut HirFormatter<'_, 'db>,1201    field_types: &'db ArenaMap<LocalFieldId, FieldType>,1202    param_env: ParamEnv<'db>,1203    layout: &Layout,1204    args: GenericArgs<'db>,1205    b: &[u8],1206    memory_map: &MemoryMap<'db>,1207) -> Result {1208    let param_env = ParamEnvAndCrate { param_env, krate: f.krate() };1209    match data.shape {1210        FieldsShape::Record | FieldsShape::Tuple => {1211            let render_field = |f: &mut HirFormatter<'_, 'db>, id: LocalFieldId| {1212                let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();1213                let ty = field_types[id].ty().instantiate(f.interner, args).skip_norm_wip();1214                let Ok(layout) = f.db.layout_of_ty(ty.store(), param_env.store()) else {1215                    return f.write_str("<layout-error>");1216                };1217                let size = layout.size.bytes_usize();1218                render_const_scalar(f, &b[offset..offset + size], memory_map, ty)1219            };1220            let mut it = data.fields().iter();1221            if matches!(data.shape, FieldsShape::Record) {1222                write!(f, " {{")?;1223                if let Some((id, data)) = it.next() {1224                    write!(f, " {}: ", data.name.display(f.db, f.edition()))?;1225                    render_field(f, id)?;1226                }1227                for (id, data) in it {1228                    write!(f, ", {}: ", data.name.display(f.db, f.edition()))?;1229                    render_field(f, id)?;1230                }1231                write!(f, " }}")?;1232            } else {1233                let mut it = it.map(|it| it.0);1234                write!(f, "(")?;1235                if let Some(id) = it.next() {1236                    render_field(f, id)?;1237                }1238                for id in it {1239                    write!(f, ", ")?;1240                    render_field(f, id)?;1241                }1242                write!(f, ")")?;1243            }1244            Ok(())1245        }1246        FieldsShape::Unit => Ok(()),1247    }1248}12491250impl<'db> HirDisplay<'db> for Ty<'db> {1251    fn hir_fmt(&self, f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_, 'db>) -> Result {1252        let interner = f.interner;1253        if f.should_truncate() {1254            return write!(f, "{TYPE_HINT_TRUNCATION}");1255        }12561257        let trait_bounds_need_parens = mem::replace(&mut f.trait_bounds_need_parens, false);1258        match self.kind() {1259            TyKind::Never => write!(f, "!")?,1260            TyKind::Str => write!(f, "str")?,1261            TyKind::Bool => write!(f, "bool")?,1262            TyKind::Char => write!(f, "char")?,1263            TyKind::Float(t) => write!(f, "{}", primitive::float_ty_to_string(t))?,1264            TyKind::Int(t) => write!(f, "{}", primitive::int_ty_to_string(t))?,1265            TyKind::Uint(t) => write!(f, "{}", primitive::uint_ty_to_string(t))?,1266            TyKind::Slice(t) => {1267                write!(f, "[")?;1268                t.hir_fmt(f)?;1269                write!(f, "]")?;1270            }1271            TyKind::Array(t, c) => {1272                write!(f, "[")?;1273                t.hir_fmt(f)?;1274                write!(f, "; ")?;1275                c.hir_fmt(f)?;1276                write!(f, "]")?;1277            }1278            TyKind::Ref(l, t, m) => {1279                f.write_char('&')?;1280                if f.render_region(l) {1281                    l.hir_fmt(f)?;1282                    f.write_char(' ')?;1283                }1284                match m {1285                    rustc_ast_ir::Mutability::Not => (),1286                    rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?,1287                }12881289                f.trait_bounds_need_parens = true;1290                t.hir_fmt(f)?;1291                f.trait_bounds_need_parens = false;1292            }1293            TyKind::RawPtr(t, m) => {1294                write!(1295                    f,1296                    "*{}",1297                    match m {1298                        rustc_ast_ir::Mutability::Not => "const ",1299                        rustc_ast_ir::Mutability::Mut => "mut ",1300                    }1301                )?;13021303                f.trait_bounds_need_parens = true;1304                t.hir_fmt(f)?;1305                f.trait_bounds_need_parens = false;1306            }1307            TyKind::Tuple(tys) => {1308                if tys.len() == 1 {1309                    write!(f, "(")?;1310                    tys.as_slice()[0].hir_fmt(f)?;1311                    write!(f, ",)")?;1312                } else {1313                    write!(f, "(")?;1314                    f.write_joined(tys.as_slice(), ", ")?;1315                    write!(f, ")")?;1316                }1317            }1318            TyKind::FnPtr(sig, header) => {1319                let sig = sig.with(header);1320                sig.hir_fmt(f)?;1321            }1322            TyKind::FnDef(def, args) => {1323                let def = def.0;1324                let sig =1325                    db.callable_item_signature(def).instantiate(interner, args).skip_norm_wip();13261327                if f.display_kind.is_source_code() {1328                    // `FnDef` is anonymous and there's no surface syntax for it. Show it as a1329                    // function pointer type.1330                    return sig.hir_fmt(f);1331                }1332                if let Safety::Unsafe = sig.safety() {1333                    write!(f, "unsafe ")?;1334                }1335                if !sig.abi().is_rustic_abi() {1336                    f.write_str("extern \"")?;1337                    f.write_str(sig.abi().as_str())?;1338                    f.write_str("\" ")?;1339                }13401341                let sig = sig.skip_binder();1342                write!(f, "fn ")?;1343                f.start_location_link(def.into());1344                match def {1345                    CallableDefId::FunctionId(ff) => write!(1346                        f,1347                        "{}",1348                        FunctionSignature::of(db, ff).name.display(f.db, f.edition())1349                    )?,1350                    CallableDefId::StructId(s) => {1351                        write!(f, "{}", StructSignature::of(db, s).name.display(f.db, f.edition()))?1352                    }1353                    CallableDefId::EnumVariantId(e) => {1354                        let loc = e.lookup(db);1355                        write!(f, "{}", loc.name.display(db, f.edition()))?1356                    }1357                };1358                f.end_location_link();13591360                if !args.is_empty() {1361                    let generic_def_id = GenericDefId::from_callable(db, def);1362                    let generics = generics(db, generic_def_id);1363                    let ProvenanceSplit {1364                        parent_total: parent_len,1365                        has_self_param: self_param,1366                        non_impl_trait_type_params: type_,1367                        const_params: const_,1368                        impl_trait_type_params: impl_,1369                        lifetimes: lifetime,1370                    } = generics.provenance_split();1371                    let parameters = args.as_slice();1372                    debug_assert_eq!(1373                        parameters.len(),1374                        parent_len + self_param as usize + type_ + const_ + impl_ + lifetime1375                    );1376                    // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?1377                    if parameters.len() - impl_ > 0 {1378                        let params_len = parameters.len();1379                        // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes1380                        let parameters =1381                            generic_args_sans_defaults(f, Some(generic_def_id), parameters);1382                        assert!(params_len >= parameters.len());1383                        let defaults = params_len - parameters.len();13841385                        // Normally, functions cannot have default parameters, but they can,1386                        // for function-like things such as struct names or enum variants.1387                        // The former cannot have defaults but does have parents,1388                        // but the latter cannot have parents but can have defaults.1389                        //1390                        // However, it's also true that *traits* can have defaults too.1391                        // In this case, there can be no function params.1392                        let parent_end = if parent_len > 0 {1393                            // If `parent_len` > 0, then there cannot be defaults on the function1394                            // and all defaults must come from the parent.1395                            parent_len - defaults1396                        } else {1397                            parent_len1398                        };1399                        let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;1400                        let (parent_params, fn_params) = parameters.split_at(parent_end);14011402                        write!(f, "<")?;1403                        hir_fmt_generic_arguments(f, parent_params, None)?;1404                        if !parent_params.is_empty() && !fn_params.is_empty() {1405                            write!(f, ", ")?;1406                        }1407                        hir_fmt_generic_arguments(1408                            f,1409                            &fn_params[..fn_params_no_impl_or_defaults],1410                            None,1411                        )?;1412                        write!(f, ">")?;1413                    }1414                }1415                write!(f, "(")?;1416                f.write_joined(sig.inputs(), ", ")?;1417                write!(f, ")")?;1418                let ret = sig.output();1419                if !ret.is_unit() {1420                    write!(f, " -> ")?;1421                    ret.hir_fmt(f)?;1422                }1423            }1424            TyKind::Adt(def, parameters) => {1425                let def_id = def.def_id();1426                f.start_location_link(def_id.into());1427                match f.display_kind {1428                    DisplayKind::Diagnostics | DisplayKind::Test => {1429                        let name = match def_id {1430                            hir_def::AdtId::StructId(it) => {1431                                StructSignature::of(db, it).name.clone()1432                            }1433                            hir_def::AdtId::UnionId(it) => UnionSignature::of(db, it).name.clone(),1434                            hir_def::AdtId::EnumId(it) => EnumSignature::of(db, it).name.clone(),1435                        };1436                        write!(f, "{}", name.display(f.db, f.edition()))?;1437                    }1438                    DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => {1439                        if let Some(path) = find_path::find_path(1440                            db,1441                            ItemInNs::Types(def_id.into()),1442                            module_id,1443                            PrefixKind::Plain,1444                            false,1445                            // FIXME: no_std Cfg?1446                            FindPathConfig {1447                                prefer_no_std: false,1448                                prefer_prelude: true,1449                                prefer_absolute: false,1450                                allow_unstable: true,1451                            },1452                        ) {1453                            write!(f, "{}", path.display(f.db, f.edition()))?;1454                        } else {1455                            return Err(HirDisplayError::DisplaySourceCodeError(1456                                DisplaySourceCodeError::PathNotFound,1457                            ));1458                        }1459                    }1460                }1461                f.end_location_link();14621463                hir_fmt_generics(f, parameters.as_slice(), Some(def.def_id().into()), None)?;1464            }1465            TyKind::Alias(alias_ty @ AliasTy { kind: AliasTyKind::Projection { def_id }, .. }) => {1466                write_projection(f, &alias_ty, trait_bounds_need_parens, def_id.0)?1467            }1468            TyKind::Foreign(alias) => {1469                let type_alias = TypeAliasSignature::of(db, alias.0);1470                f.start_location_link(alias.0.into());1471                write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;1472                f.end_location_link();1473            }1474            TyKind::Alias(alias_ty @ AliasTy { kind: AliasTyKind::Opaque { def_id }, .. }) => {1475                let opaque_ty_id = def_id.0;1476                if !f.display_kind.allows_opaque() {1477                    return Err(HirDisplayError::DisplaySourceCodeError(1478                        DisplaySourceCodeError::OpaqueType,1479                    ));1480                }1481                let impl_trait_id = opaque_ty_id.loc(db);1482                let data = impl_trait_id.predicates(db);1483                let bounds = data1484                    .iter_instantiated_copied(interner, alias_ty.args.as_slice())1485                    .map(Unnormalized::skip_norm_wip)1486                    .collect::<Vec<_>>();1487                let krate = match impl_trait_id {1488                    ImplTraitId::ReturnTypeImplTrait(func, _) => {1489                        func.krate(db)1490                        // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution1491                    }1492                    ImplTraitId::TypeAliasImplTrait(alias, _) => alias.krate(db),1493                };1494                write_bounds_like_dyn_trait_with_prefix(1495                    f,1496                    "impl",1497                    Either::Left(*self),1498                    &bounds,1499                    SizedByDefault::Sized { anchor: krate },1500                    trait_bounds_need_parens,1501                )?;1502            }1503            TyKind::Closure(id, substs) => {1504                let id = id.0;1505                if f.display_kind.is_source_code() {1506                    if !f.display_kind.allows_opaque() {1507                        return Err(HirDisplayError::DisplaySourceCodeError(1508                            DisplaySourceCodeError::OpaqueType,1509                        ));1510                    } else if f.closure_style != ClosureStyle::ImplFn {1511                        never!("Only `impl Fn` is valid for displaying closures in source code");1512                    }1513                }1514                match f.closure_style {1515                    ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),1516                    ClosureStyle::ClosureWithId => {1517                        return write!(1518                            f,1519                            "{{closure#{:?}}}",1520                            salsa::plumbing::AsId::as_id(&id).index()1521                        );1522                    }1523                    ClosureStyle::ClosureWithSubst => {1524                        write!(f, "{{closure#{:?}}}", salsa::plumbing::AsId::as_id(&id).index())?;1525                        return hir_fmt_generics(f, substs.as_slice(), None, None);1526                    }1527                    _ => (),1528                }1529                let sig = interner.signature_unclosure(substs.as_closure().sig(), Safety::Safe);1530                let sig = sig.skip_binder();1531                let kind = substs.as_closure().kind();1532                match f.closure_style {1533                    ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,1534                    ClosureStyle::RANotation => write!(f, "|")?,1535                    _ => unreachable!(),1536                }1537                if sig.inputs().is_empty() {1538                } else if f.should_truncate() {1539                    write!(f, "{TYPE_HINT_TRUNCATION}")?;1540                } else {1541                    f.write_joined(sig.inputs(), ", ")?;1542                };1543                match f.closure_style {1544                    ClosureStyle::ImplFn => write!(f, ")")?,1545                    ClosureStyle::RANotation => write!(f, "|")?,1546                    _ => unreachable!(),1547                }1548                if f.closure_style == ClosureStyle::RANotation || !sig.output().is_unit() {1549                    write!(f, " -> ")?;1550                    sig.output().hir_fmt(f)?;1551                }1552            }1553            TyKind::CoroutineClosure(id, args) => {1554                let id = id.0;1555                let closure_kind = match id.loc(db).kind {1556                    HirClosureKind::CoroutineClosure(kind) => kind,1557                    kind => panic!("invalid kind for coroutine closure: {kind:?}"),1558                };1559                let closure_label = match closure_kind {1560                    CoroutineKind::Async => "async closure",1561                    CoroutineKind::Gen => "gen closure",1562                    CoroutineKind::AsyncGen => "async gen closure",1563                };1564                if f.display_kind.is_source_code() {1565                    if !f.display_kind.allows_opaque() {1566                        return Err(HirDisplayError::DisplaySourceCodeError(1567                            DisplaySourceCodeError::OpaqueType,1568                        ));1569                    } else if f.closure_style != ClosureStyle::ImplFn {1570                        never!("Only `impl Fn` is valid for displaying closures in source code");1571                    }1572                }1573                match f.closure_style {1574                    ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),1575                    ClosureStyle::ClosureWithId => {1576                        return write!(1577                            f,1578                            "{{{closure_label}#{:?}}}",1579                            salsa::plumbing::AsId::as_id(&id).index()1580                        );1581                    }1582                    ClosureStyle::ClosureWithSubst => {1583                        write!(1584                            f,1585                            "{{{closure_label}#{:?}}}",1586                            salsa::plumbing::AsId::as_id(&id).index()1587                        )?;1588                        return hir_fmt_generics(f, args.as_slice(), None, None);1589                    }1590                    _ => (),1591                }1592                let callable_kind = args.as_coroutine_closure().kind();1593                let kind = match (closure_kind, callable_kind) {1594                    (CoroutineKind::Async, rustc_type_ir::ClosureKind::Fn) => "AsyncFn",1595                    (CoroutineKind::Async, rustc_type_ir::ClosureKind::FnMut) => "AsyncFnMut",1596                    (CoroutineKind::Async, rustc_type_ir::ClosureKind::FnOnce) => "AsyncFnOnce",1597                    (_, rustc_type_ir::ClosureKind::Fn) => "Fn",1598                    (_, rustc_type_ir::ClosureKind::FnMut) => "FnMut",1599                    (_, rustc_type_ir::ClosureKind::FnOnce) => "FnOnce",1600                };1601                let coroutine_sig = args.as_coroutine_closure().coroutine_closure_sig();1602                let coroutine_sig = coroutine_sig.skip_binder();1603                let coroutine_inputs = coroutine_sig.tupled_inputs_ty.tuple_fields();1604                let coroutine_output = coroutine_sig.return_ty;1605                match f.closure_style {1606                    ClosureStyle::ImplFn => write!(f, "impl {kind}(")?,1607                    ClosureStyle::RANotation => match closure_kind {1608                        CoroutineKind::Async => write!(f, "async |")?,1609                        CoroutineKind::Gen => write!(f, "gen |")?,1610                        CoroutineKind::AsyncGen => write!(f, "async gen |")?,1611                    },1612                    _ => unreachable!(),1613                }1614                if coroutine_inputs.is_empty() {1615                } else if f.should_truncate() {1616                    write!(f, "{TYPE_HINT_TRUNCATION}")?;1617                } else {1618                    f.write_joined(coroutine_inputs, ", ")?;1619                };1620                match f.closure_style {1621                    ClosureStyle::ImplFn => write!(f, ")")?,1622                    ClosureStyle::RANotation => write!(f, "|")?,1623                    _ => unreachable!(),1624                }1625                if f.closure_style == ClosureStyle::RANotation || !coroutine_output.is_unit() {1626                    write!(f, " -> ")?;1627                    coroutine_output.hir_fmt(f)?;1628                }1629            }1630            TyKind::Placeholder(_) => write!(f, "{{placeholder}}")?,1631            TyKind::Param(param) => {1632                // FIXME: We should not access `param.id`, it should be removed, and we should know the1633                // parent from the formatted type.1634                let generics = GenericParams::of(db, param.id.parent());1635                let param_data = &generics[param.id.local_id()];1636                match param_data {1637                    TypeOrConstParamData::TypeParamData(p) => match p.provenance {1638                        TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {1639                            f.start_location_link_generic(param.id.into());1640                            write!(1641                                f,1642                                "{}",1643                                p.name1644                                    .clone()1645                                    .unwrap_or_else(Name::missing)1646                                    .display(f.db, f.edition())1647                            )?;1648                            f.end_location_link();1649                        }1650                        TypeParamProvenance::ArgumentImplTrait => {1651                            let bounds = GenericPredicates::query_all(f.db, param.id.parent())1652                                .iter_identity()1653                                .map(Unnormalized::skip_norm_wip)1654                                .filter(|wc| match wc.kind().skip_binder() {1655                                    ClauseKind::Trait(tr) => tr.self_ty() == *self,1656                                    ClauseKind::Projection(proj) => proj.self_ty() == *self,1657                                    ClauseKind::TypeOutlives(to) => to.0 == *self,1658                                    _ => false,1659                                })1660                                .collect::<Vec<_>>();1661                            let krate = param.id.parent().module(db).krate(db);1662                            write_bounds_like_dyn_trait_with_prefix(1663                                f,1664                                "impl",1665                                Either::Left(*self),1666                                &bounds,1667                                SizedByDefault::Sized { anchor: krate },1668                                trait_bounds_need_parens,1669                            )?;1670                        }1671                    },1672                    TypeOrConstParamData::ConstParamData(p) => {1673                        f.start_location_link_generic(param.id.into());1674                        write!(f, "{}", p.name.display(f.db, f.edition()))?;1675                        f.end_location_link();1676                    }1677                }1678            }1679            TyKind::Bound(BoundVarIndexKind::Bound(debruijn), ty) => {1680                write!(f, "?{}.{}", debruijn.as_usize(), ty.var.as_usize())?1681            }1682            TyKind::Bound(BoundVarIndexKind::Canonical, ty) => {1683                write!(f, "?c.{}", ty.var.as_usize())?1684            }1685            TyKind::Dynamic(bounds, region) => {1686                // We want to put auto traits after principal traits, regardless of their written order.1687                let mut bounds_to_display = SmallVec::<[_; 4]>::new();1688                let mut auto_trait_bounds = SmallVec::<[_; 4]>::new();1689                for bound in bounds.iter() {1690                    let clause = bound.with_self_ty(interner, *self);1691                    match bound.skip_binder() {1692                        ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {1693                            bounds_to_display.push(clause);1694                        }1695                        ExistentialPredicate::AutoTrait(_) => auto_trait_bounds.push(clause),1696                    }1697                }1698                bounds_to_display.append(&mut auto_trait_bounds);16991700                if f.render_region(region) {1701                    bounds_to_display1702                        .push(rustc_type_ir::OutlivesPredicate(*self, region).upcast(interner));1703                }17041705                write_bounds_like_dyn_trait_with_prefix(1706                    f,1707                    "dyn",1708                    Either::Left(*self),1709                    &bounds_to_display,1710                    SizedByDefault::NotSized,1711                    trait_bounds_need_parens,1712                )?;1713            }1714            TyKind::Error(_) => {1715                if f.display_kind.is_source_code() {1716                    f.write_char('_')?;1717                } else {1718                    write!(f, "{{unknown}}")?;1719                }1720            }1721            TyKind::Infer(..) => write!(f, "_")?,1722            TyKind::Coroutine(coroutine_id, subst) => {1723                let kind = coroutine_id.0.loc(db).kind;1724                let CoroutineArgsParts { resume_ty, yield_ty, return_ty, .. } =1725                    subst.split_coroutine_args();1726                match kind {1727                    HirClosureKind::Coroutine { kind: CoroutineKind::Async, .. } => {1728                        let lang_items = f.lang_items();1729                        let future_trait = lang_items.Future;1730                        let output = lang_items.FutureOutput;1731                        write!(f, "impl ")?;1732                        if let Some(t) = future_trait {1733                            f.start_location_link(t.into());1734                        }1735                        write!(f, "Future")?;1736                        if future_trait.is_some() {1737                            f.end_location_link();1738                        }1739                        write!(f, "<")?;1740                        if let Some(t) = output {1741                            f.start_location_link(t.into());1742                        }1743                        write!(f, "Output")?;1744                        if output.is_some() {1745                            f.end_location_link();1746                        }1747                        write!(f, " = ")?;1748                        return_ty.hir_fmt(f)?;1749                        write!(f, ">")?;1750                    }1751                    HirClosureKind::Coroutine { kind: CoroutineKind::Gen, .. } => {1752                        let lang_items = f.lang_items();1753                        let iterator_trait = lang_items.Iterator;1754                        let item = lang_items.IteratorItem;1755                        write!(f, "impl ")?;1756                        if let Some(t) = iterator_trait {1757                            f.start_location_link(t.into());1758                        }1759                        write!(f, "Iterator")?;1760                        if iterator_trait.is_some() {1761                            f.end_location_link();1762                        }1763                        write!(f, "<")?;1764                        if let Some(t) = item {1765                            f.start_location_link(t.into());1766                        }1767                        write!(f, "Item")?;1768                        if item.is_some() {1769                            f.end_location_link();1770                        }1771                        write!(f, " = ")?;1772                        yield_ty.hir_fmt(f)?;1773                        write!(f, ">")?;1774                    }1775                    HirClosureKind::Coroutine { kind: CoroutineKind::AsyncGen, .. } => {1776                        let lang_items = f.lang_items();1777                        let async_iterator_trait = lang_items.AsyncIterator;1778                        let item = lang_items.AsyncIteratorItem;1779                        write!(f, "impl ")?;1780                        if let Some(t) = async_iterator_trait {1781                            f.start_location_link(t.into());1782                        }1783                        write!(f, "AsyncIterator")?;1784                        if async_iterator_trait.is_some() {1785                            f.end_location_link();1786                        }1787                        write!(f, "<")?;1788                        if let Some(t) = item {1789                            f.start_location_link(t.into());1790                        }1791                        write!(f, "Item")?;1792                        if item.is_some() {1793                            f.end_location_link();1794                        }1795                        write!(f, " = ")?;1796                        let item_ty = async_gen_item_ty_from_yield_ty(f.lang_items(), yield_ty)1797                            .unwrap_or(yield_ty);1798                        item_ty.hir_fmt(f)?;1799                        write!(f, ">")?;1800                    }1801                    HirClosureKind::OldCoroutine(..) => {1802                        if f.display_kind.is_source_code() {1803                            return Err(HirDisplayError::DisplaySourceCodeError(1804                                DisplaySourceCodeError::Coroutine,1805                            ));1806                        }1807                        write!(f, "|")?;1808                        resume_ty.hir_fmt(f)?;1809                        write!(f, "|")?;18101811                        write!(f, " yields ")?;1812                        yield_ty.hir_fmt(f)?;18131814                        write!(f, " -> ")?;1815                        return_ty.hir_fmt(f)?;1816                    }1817                    _ => panic!("invalid kind for coroutine: {kind:?}"),1818                }1819            }1820            TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,1821            TyKind::Pat(_, _) => write!(f, "{{pat}}")?,1822            TyKind::UnsafeBinder(_) => write!(f, "{{unsafe binder}}")?,1823            TyKind::Alias(..) => write!(f, "{{alias}}")?,1824        }1825        Ok(())1826    }1827}18281829fn hir_fmt_generics<'db>(1830    f: &mut HirFormatter<'_, 'db>,1831    parameters: &[GenericArg<'db>],1832    generic_def: Option<hir_def::GenericDefId>,1833    self_: Option<Ty<'db>>,1834) -> Result {1835    if parameters.is_empty() {1836        return Ok(());1837    }18381839    let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);18401841    if !parameters_to_write.is_empty() {1842        write!(f, "<")?;1843        hir_fmt_generic_arguments(f, parameters_to_write, self_)?;1844        write!(f, ">")?;1845    }18461847    Ok(())1848}18491850fn generic_args_sans_defaults<'ga, 'db>(1851    f: &mut HirFormatter<'_, 'db>,1852    generic_def: Option<hir_def::GenericDefId>,1853    parameters: &'ga [GenericArg<'db>],1854) -> &'ga [GenericArg<'db>] {1855    if f.display_kind.is_source_code() || f.omit_verbose_types() {1856        match generic_def.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) {1857            None => parameters,1858            Some(default_parameters) => {1859                let should_show = |arg: GenericArg<'db>, i: usize| match default_parameters.get(i) {1860                    None => true,1861                    Some(default_parameter) => {1862                        arg != default_parameter1863                            .instantiate(f.interner, &parameters[..i])1864                            .skip_norm_wip()1865                    }1866                };1867                let mut default_from = 0;1868                for (i, &parameter) in parameters.iter().enumerate() {1869                    if should_show(parameter, i) {1870                        default_from = i + 1;1871                    }1872                }1873                &parameters[0..default_from]1874            }1875        }1876    } else {1877        parameters1878    }1879}18801881fn hir_fmt_generic_args<'db>(1882    f: &mut HirFormatter<'_, 'db>,1883    parameters: &[GenericArg<'db>],1884    generic_def: Option<hir_def::GenericDefId>,1885    self_: Option<Ty<'db>>,1886) -> Result {1887    if parameters.is_empty() {1888        return Ok(());1889    }18901891    let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);18921893    if !parameters_to_write.is_empty() {1894        write!(f, "<")?;1895        hir_fmt_generic_arguments(f, parameters_to_write, self_)?;1896        write!(f, ">")?;1897    }18981899    Ok(())1900}19011902fn hir_fmt_generic_arguments<'db>(1903    f: &mut HirFormatter<'_, 'db>,1904    parameters: &[GenericArg<'db>],1905    self_: Option<Ty<'db>>,1906) -> Result {1907    let mut first = true;1908    let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some());19091910    let (ty_or_const, lifetimes) = match lifetime_offset {1911        Some(offset) => parameters.split_at(offset),1912        None => (parameters, &[][..]),1913    };1914    for generic_arg in lifetimes.iter().chain(ty_or_const) {1915        if !mem::take(&mut first) {1916            write!(f, ", ")?;1917        }1918        match self_ {1919            self_ @ Some(_) if generic_arg.ty() == self_ => write!(f, "Self")?,1920            _ => generic_arg.hir_fmt(f)?,1921        }1922    }1923    Ok(())1924}19251926fn hir_fmt_tys<'db>(1927    f: &mut HirFormatter<'_, 'db>,1928    tys: &[Ty<'db>],1929    self_: Option<Ty<'db>>,1930) -> Result {1931    let mut first = true;19321933    for ty in tys {1934        if !mem::take(&mut first) {1935            write!(f, ", ")?;1936        }1937        match self_ {1938            Some(self_) if *ty == self_ => write!(f, "Self")?,1939            _ => ty.hir_fmt(f)?,1940        }1941    }1942    Ok(())1943}19441945impl<'db> HirDisplay<'db> for PolyFnSig<'db> {1946    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {1947        let FnSig { inputs_and_output, fn_sig_kind } = self.skip_binder();1948        if let Safety::Unsafe = fn_sig_kind.safety() {1949            write!(f, "unsafe ")?;1950        }1951        // FIXME: Enable this when the FIXME on FnAbi regarding PartialEq is fixed.1952        // if !matches!(abi, FnAbi::Rust) {1953        //     f.write_str("extern \"")?;1954        //     f.write_str(abi.as_str())?;1955        //     f.write_str("\" ")?;1956        // }1957        write!(f, "fn(")?;1958        f.write_joined(inputs_and_output.inputs(), ", ")?;1959        if fn_sig_kind.c_variadic() {1960            if inputs_and_output.inputs().is_empty() {1961                write!(f, "...")?;1962            } else {1963                write!(f, ", ...")?;1964            }1965        }1966        write!(f, ")")?;1967        let ret = inputs_and_output.output();1968        if !ret.is_unit() {1969            write!(f, " -> ")?;1970            ret.hir_fmt(f)?;1971        }1972        Ok(())1973    }1974}19751976impl<'db> HirDisplay<'db> for Term<'db> {1977    fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {1978        match self.kind() {1979            TermKind::Ty(it) => it.hir_fmt(f),1980            TermKind::Const(it) => it.hir_fmt(f),1981        }1982    }1983}19841985#[derive(Clone, Copy, PartialEq, Eq)]1986pub enum SizedByDefault {1987    NotSized,1988    Sized { anchor: Crate },1989}19901991impl SizedByDefault {1992    fn is_sized_trait(self, trait_: TraitId, interner: DbInterner<'_>) -> bool {1993        match self {1994            Self::NotSized => false,1995            Self::Sized { .. } => {1996                let sized_trait = interner.lang_items().Sized;1997                Some(trait_) == sized_trait1998            }1999        }2000    }

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.