1use std::{
6 fmt::{self, Debug},
7 mem,
8};
9
10use base_db::Crate;
11use chalk_ir::{BoundVar, Safety, TyKind};
12use either::Either;
13use hir_def::{
14 GeneralConstId, GenericDefId, HasModule, ImportPathConfig, LocalFieldId, Lookup, ModuleDefId,
15 ModuleId, TraitId,
16 db::DefDatabase,
17 expr_store::{ExpressionStore, path::Path},
18 find_path::{self, PrefixKind},
19 hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
20 item_scope::ItemInNs,
21 item_tree::FieldsShape,
22 lang_item::LangItem,
23 nameres::DefMap,
24 signatures::VariantFields,
25 type_ref::{
26 ConstRef, LifetimeRef, LifetimeRefId, TraitBoundModifier, TypeBound, TypeRef, TypeRefId,
27 UseArgRef,
28 },
29 visibility::Visibility,
30};
31use hir_expand::{mod_path::PathKind, name::Name};
32use intern::{Internable, Interned, sym};
33use itertools::Itertools;
34use la_arena::ArenaMap;
35use rustc_apfloat::{
36 Float,
37 ieee::{Half as f16, Quad as f128},
38};
39use rustc_hash::FxHashSet;
40use rustc_type_ir::{
41 AliasTyKind, RegionKind,
42 inherent::{AdtDef, IntoKind, SliceLike},
43};
44use smallvec::SmallVec;
45use span::Edition;
46use stdx::never;
47use triomphe::Arc;
48
49use crate::{
50 AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, ConstScalar,
51 ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
52 LifetimeOutlives, MemoryMap, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
53 TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, consteval_nextsolver,
54 db::{HirDatabase, InternedClosure},
55 from_assoc_type_id, from_placeholder_idx,
56 generics::generics,
57 infer::normalize,
58 layout::Layout,
59 lt_from_placeholder_idx,
60 mir::pad16,
61 next_solver::{
62 BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId,
63 mapping::{
64 ChalkToNextSolver, convert_args_for_result, convert_const_for_result,
65 convert_region_for_result, convert_ty_for_result,
66 },
67 },
68 primitive, to_assoc_type_id,
69 utils::{self, ClosureSubst, detect_variant_from_bytes},
70};
71
72pub trait HirWrite: fmt::Write {
73 fn start_location_link(&mut self, _location: ModuleDefId) {}
74 fn end_location_link(&mut self) {}
75}
76
77impl HirWrite for String {}
79
80impl HirWrite for fmt::Formatter<'_> {}
82
83pub struct HirFormatter<'a> {
84 pub db: &'a dyn HirDatabase,
86 fmt: &'a mut dyn HirWrite,
88 buf: String,
90 curr_size: usize,
92 max_size: Option<usize>,
94 pub entity_limit: Option<usize>,
97 show_container_bounds: bool,
99 omit_verbose_types: bool,
100 closure_style: ClosureStyle,
101 display_lifetimes: DisplayLifetime,
102 display_kind: DisplayKind,
103 display_target: DisplayTarget,
104 bounds_formatting_ctx: BoundsFormattingCtx,
105}
106
107#[derive(Copy, Clone)]
113pub enum DisplayLifetime {
114 Always,
115 OnlyStatic,
116 OnlyNamed,
117 OnlyNamedOrStatic,
118 Never,
119}
120
121#[derive(Default)]
122enum BoundsFormattingCtx {
123 Entered {
124 projection_tys_met: FxHashSet<ProjectionTy>,
133 },
134 #[default]
135 Exited,
136}
137
138impl BoundsFormattingCtx {
139 fn contains(&mut self, proj: &ProjectionTy) -> bool {
140 match self {
141 BoundsFormattingCtx::Entered { projection_tys_met } => {
142 projection_tys_met.contains(proj)
143 }
144 BoundsFormattingCtx::Exited => false,
145 }
146 }
147}
148
149impl HirFormatter<'_> {
150 fn start_location_link(&mut self, location: ModuleDefId) {
151 self.fmt.start_location_link(location);
152 }
153
154 fn end_location_link(&mut self) {
155 self.fmt.end_location_link();
156 }
157
158 fn format_bounds_with<T, F: FnOnce(&mut Self) -> T>(
159 &mut self,
160 target: ProjectionTy,
161 format_bounds: F,
162 ) -> T {
163 match self.bounds_formatting_ctx {
164 BoundsFormattingCtx::Entered { ref mut projection_tys_met } => {
165 projection_tys_met.insert(target);
166 format_bounds(self)
167 }
168 BoundsFormattingCtx::Exited => {
169 let mut projection_tys_met = FxHashSet::default();
170 projection_tys_met.insert(target);
171 self.bounds_formatting_ctx = BoundsFormattingCtx::Entered { projection_tys_met };
172 let res = format_bounds(self);
173 self.bounds_formatting_ctx = BoundsFormattingCtx::Exited;
177 res
178 }
179 }
180 }
181
182 fn render_lifetime(&self, lifetime: &Lifetime) -> bool {
183 match self.display_lifetimes {
184 DisplayLifetime::Always => true,
185 DisplayLifetime::OnlyStatic => matches!(***lifetime.interned(), LifetimeData::Static),
186 DisplayLifetime::OnlyNamed => {
187 matches!(***lifetime.interned(), LifetimeData::Placeholder(_))
188 }
189 DisplayLifetime::OnlyNamedOrStatic => matches!(
190 ***lifetime.interned(),
191 LifetimeData::Static | LifetimeData::Placeholder(_)
192 ),
193 DisplayLifetime::Never => false,
194 }
195 }
196
197 fn render_region(&self, lifetime: crate::next_solver::Region<'_>) -> bool {
198 match self.display_lifetimes {
199 DisplayLifetime::Always => true,
200 DisplayLifetime::OnlyStatic => {
201 matches!(lifetime.kind(), rustc_type_ir::RegionKind::ReStatic)
202 }
203 DisplayLifetime::OnlyNamed => {
204 matches!(
205 lifetime.kind(),
206 rustc_type_ir::RegionKind::RePlaceholder(_)
207 | rustc_type_ir::RegionKind::ReEarlyParam(_)
208 )
209 }
210 DisplayLifetime::OnlyNamedOrStatic => matches!(
211 lifetime.kind(),
212 rustc_type_ir::RegionKind::ReStatic
213 | rustc_type_ir::RegionKind::RePlaceholder(_)
214 | rustc_type_ir::RegionKind::ReEarlyParam(_)
215 ),
216 DisplayLifetime::Never => false,
217 }
218 }
219}
220
221pub trait HirDisplay {
222 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
223
224 fn into_displayable<'a>(
226 &'a self,
227 db: &'a dyn HirDatabase,
228 max_size: Option<usize>,
229 limited_size: Option<usize>,
230 omit_verbose_types: bool,
231 display_target: DisplayTarget,
232 display_kind: DisplayKind,
233 closure_style: ClosureStyle,
234 show_container_bounds: bool,
235 ) -> HirDisplayWrapper<'a, Self>
236 where
237 Self: Sized,
238 {
239 assert!(
240 !matches!(display_kind, DisplayKind::SourceCode { .. }),
241 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
242 );
243 HirDisplayWrapper {
244 db,
245 t: self,
246 max_size,
247 limited_size,
248 omit_verbose_types,
249 display_target,
250 display_kind,
251 closure_style,
252 show_container_bounds,
253 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
254 }
255 }
256
257 fn display<'a>(
260 &'a self,
261 db: &'a dyn HirDatabase,
262 display_target: DisplayTarget,
263 ) -> HirDisplayWrapper<'a, Self>
264 where
265 Self: Sized,
266 {
267 HirDisplayWrapper {
268 db,
269 t: self,
270 max_size: None,
271 limited_size: None,
272 omit_verbose_types: false,
273 closure_style: ClosureStyle::ImplFn,
274 display_target,
275 display_kind: DisplayKind::Diagnostics,
276 show_container_bounds: false,
277 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
278 }
279 }
280
281 fn display_truncated<'a>(
284 &'a self,
285 db: &'a dyn HirDatabase,
286 max_size: Option<usize>,
287 display_target: DisplayTarget,
288 ) -> HirDisplayWrapper<'a, Self>
289 where
290 Self: Sized,
291 {
292 HirDisplayWrapper {
293 db,
294 t: self,
295 max_size,
296 limited_size: None,
297 omit_verbose_types: true,
298 closure_style: ClosureStyle::ImplFn,
299 display_target,
300 display_kind: DisplayKind::Diagnostics,
301 show_container_bounds: false,
302 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
303 }
304 }
305
306 fn display_limited<'a>(
309 &'a self,
310 db: &'a dyn HirDatabase,
311 limited_size: Option<usize>,
312 display_target: DisplayTarget,
313 ) -> HirDisplayWrapper<'a, Self>
314 where
315 Self: Sized,
316 {
317 HirDisplayWrapper {
318 db,
319 t: self,
320 max_size: None,
321 limited_size,
322 omit_verbose_types: true,
323 closure_style: ClosureStyle::ImplFn,
324 display_target,
325 display_kind: DisplayKind::Diagnostics,
326 show_container_bounds: false,
327 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
328 }
329 }
330
331 fn display_source_code<'a>(
334 &'a self,
335 db: &'a dyn HirDatabase,
336 module_id: ModuleId,
337 allow_opaque: bool,
338 ) -> Result<String, DisplaySourceCodeError> {
339 let mut result = String::new();
340 match self.hir_fmt(&mut HirFormatter {
341 db,
342 fmt: &mut result,
343 buf: String::with_capacity(20),
344 curr_size: 0,
345 max_size: None,
346 entity_limit: None,
347 omit_verbose_types: false,
348 closure_style: ClosureStyle::ImplFn,
349 display_target: DisplayTarget::from_crate(db, module_id.krate()),
350 display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },
351 show_container_bounds: false,
352 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
353 bounds_formatting_ctx: Default::default(),
354 }) {
355 Ok(()) => {}
356 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
357 Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
358 };
359 Ok(result)
360 }
361
362 fn display_test<'a>(
364 &'a self,
365 db: &'a dyn HirDatabase,
366 display_target: DisplayTarget,
367 ) -> HirDisplayWrapper<'a, Self>
368 where
369 Self: Sized,
370 {
371 HirDisplayWrapper {
372 db,
373 t: self,
374 max_size: None,
375 limited_size: None,
376 omit_verbose_types: false,
377 closure_style: ClosureStyle::ImplFn,
378 display_target,
379 display_kind: DisplayKind::Test,
380 show_container_bounds: false,
381 display_lifetimes: DisplayLifetime::Always,
382 }
383 }
384
385 fn display_with_container_bounds<'a>(
388 &'a self,
389 db: &'a dyn HirDatabase,
390 show_container_bounds: bool,
391 display_target: DisplayTarget,
392 ) -> HirDisplayWrapper<'a, Self>
393 where
394 Self: Sized,
395 {
396 HirDisplayWrapper {
397 db,
398 t: self,
399 max_size: None,
400 limited_size: None,
401 omit_verbose_types: false,
402 closure_style: ClosureStyle::ImplFn,
403 display_target,
404 display_kind: DisplayKind::Diagnostics,
405 show_container_bounds,
406 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
407 }
408 }
409}
410
411impl HirFormatter<'_> {
412 pub fn krate(&self) -> Crate {
413 self.display_target.krate
414 }
415
416 pub fn edition(&self) -> Edition {
417 self.display_target.edition
418 }
419
420 pub fn write_joined<T: HirDisplay>(
421 &mut self,
422 iter: impl IntoIterator<Item = T>,
423 sep: &str,
424 ) -> Result<(), HirDisplayError> {
425 let mut first = true;
426 for e in iter {
427 if !first {
428 write!(self, "{sep}")?;
429 }
430 first = false;
431
432 if self.should_truncate() {
434 return write!(self, "{TYPE_HINT_TRUNCATION}");
435 }
436
437 e.hir_fmt(self)?;
438 }
439 Ok(())
440 }
441
442 pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> {
444 self.buf.clear();
446 fmt::write(&mut self.buf, args)?;
447 self.curr_size += self.buf.len();
448
449 self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
451 }
452
453 pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> {
454 self.fmt.write_str(s)?;
455 Ok(())
456 }
457
458 pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> {
459 self.fmt.write_char(c)?;
460 Ok(())
461 }
462
463 pub fn should_truncate(&self) -> bool {
464 match self.max_size {
465 Some(max_size) => self.curr_size >= max_size,
466 None => false,
467 }
468 }
469
470 pub fn omit_verbose_types(&self) -> bool {
471 self.omit_verbose_types
472 }
473
474 pub fn show_container_bounds(&self) -> bool {
475 self.show_container_bounds
476 }
477}
478
479#[derive(Debug, Clone, Copy)]
480pub struct DisplayTarget {
481 krate: Crate,
482 pub edition: Edition,
483}
484
485impl DisplayTarget {
486 pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self {
487 let edition = krate.data(db).edition;
488 Self { krate, edition }
489 }
490}
491
492#[derive(Clone, Copy)]
493pub enum DisplayKind {
494 Diagnostics,
498 SourceCode { target_module_id: ModuleId, allow_opaque: bool },
501 Test,
503}
504
505impl DisplayKind {
506 fn is_source_code(self) -> bool {
507 matches!(self, Self::SourceCode { .. })
508 }
509
510 fn allows_opaque(self) -> bool {
511 match self {
512 Self::SourceCode { allow_opaque, .. } => allow_opaque,
513 _ => true,
514 }
515 }
516}
517
518#[derive(Debug)]
519pub enum DisplaySourceCodeError {
520 PathNotFound,
521 Coroutine,
522 OpaqueType,
523}
524
525pub enum HirDisplayError {
526 DisplaySourceCodeError(DisplaySourceCodeError),
528 FmtError,
530}
531impl From<fmt::Error> for HirDisplayError {
532 fn from(_: fmt::Error) -> Self {
533 Self::FmtError
534 }
535}
536
537pub struct HirDisplayWrapper<'a, T> {
538 db: &'a dyn HirDatabase,
539 t: &'a T,
540 max_size: Option<usize>,
541 limited_size: Option<usize>,
542 omit_verbose_types: bool,
543 closure_style: ClosureStyle,
544 display_kind: DisplayKind,
545 display_target: DisplayTarget,
546 show_container_bounds: bool,
547 display_lifetimes: DisplayLifetime,
548}
549
550#[derive(Debug, PartialEq, Eq, Clone, Copy)]
551pub enum ClosureStyle {
552 ImplFn,
555 RANotation,
557 ClosureWithId,
559 ClosureWithSubst,
561 Hide,
563}
564
565impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
566 pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
567 self.t.hir_fmt(&mut HirFormatter {
568 db: self.db,
569 fmt: f,
570 buf: String::with_capacity(self.max_size.unwrap_or(20)),
571 curr_size: 0,
572 max_size: self.max_size,
573 entity_limit: self.limited_size,
574 omit_verbose_types: self.omit_verbose_types,
575 display_kind: self.display_kind,
576 display_target: self.display_target,
577 closure_style: self.closure_style,
578 show_container_bounds: self.show_container_bounds,
579 display_lifetimes: self.display_lifetimes,
580 bounds_formatting_ctx: Default::default(),
581 })
582 }
583
584 pub fn with_closure_style(mut self, c: ClosureStyle) -> Self {
585 self.closure_style = c;
586 self
587 }
588
589 pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self {
590 self.display_lifetimes = l;
591 self
592 }
593}
594
595impl<T> fmt::Display for HirDisplayWrapper<'_, T>
596where
597 T: HirDisplay,
598{
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 match self.write_to(f) {
601 Ok(()) => Ok(()),
602 Err(HirDisplayError::FmtError) => Err(fmt::Error),
603 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
604 panic!(
606 "HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!"
607 )
608 }
609 }
610 }
611}
612
613const TYPE_HINT_TRUNCATION: &str = "…";
614
615impl<T: HirDisplay> HirDisplay for &T {
616 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
617 HirDisplay::hir_fmt(*self, f)
618 }
619}
620
621impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
622 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
623 HirDisplay::hir_fmt(self.as_ref(), f)
624 }
625}
626
627impl HirDisplay for ProjectionTy {
628 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
629 if f.should_truncate() {
630 return write!(f, "{TYPE_HINT_TRUNCATION}");
631 }
632 let trait_ref = self.trait_ref(f.db);
633 let self_ty = trait_ref.self_type_parameter(Interner);
634
635 if !f.display_kind.is_source_code()
639 && let TyKind::Placeholder(idx) = self_ty.kind(Interner)
640 && !f.bounds_formatting_ctx.contains(self)
641 {
642 let db = f.db;
643 let id = from_placeholder_idx(db, *idx).0;
644 let generics = generics(db, id.parent);
645
646 let substs = generics.placeholder_subst(db);
647 let bounds = db
648 .generic_predicates(id.parent)
649 .iter()
650 .map(|pred| pred.clone().substitute(Interner, &substs))
651 .filter(|wc| {
652 let ty = match wc.skip_binders() {
653 WhereClause::Implemented(tr) => tr.self_type_parameter(Interner),
654 WhereClause::TypeOutlives(t) => t.ty.clone(),
655 WhereClause::AliasEq(_) | WhereClause::LifetimeOutlives(_) => {
657 return false;
658 }
659 };
660 let TyKind::Alias(AliasTy::Projection(proj)) = ty.kind(Interner) else {
661 return false;
662 };
663 proj == self
664 })
665 .collect::<Vec<_>>();
666 if !bounds.is_empty() {
667 return f.format_bounds_with(self.clone(), |f| {
668 write_bounds_like_dyn_trait_with_prefix(
669 f,
670 "impl",
671 Either::Left(
672 &TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner),
673 ),
674 &bounds,
675 SizedByDefault::NotSized,
676 )
677 });
678 }
679 }
680
681 write!(f, "<")?;
682 self_ty.hir_fmt(f)?;
683 write!(f, " as ")?;
684 trait_ref.hir_fmt(f)?;
685 write!(
686 f,
687 ">::{}",
688 f.db.type_alias_signature(from_assoc_type_id(self.associated_ty_id))
689 .name
690 .display(f.db, f.edition())
691 )?;
692 let proj_params =
693 &self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..];
694 hir_fmt_generics(f, proj_params, None, None)
695 }
696}
697
698impl HirDisplay for OpaqueTy {
699 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
700 if f.should_truncate() {
701 return write!(f, "{TYPE_HINT_TRUNCATION}");
702 }
703
704 self.substitution.at(Interner, 0).hir_fmt(f)
705 }
706}
707
708impl HirDisplay for GenericArg {
709 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
710 match self.interned() {
711 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
712 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
713 crate::GenericArgData::Const(c) => c.hir_fmt(f),
714 }
715 }
716}
717
718impl<'db> HirDisplay for crate::next_solver::GenericArg<'db> {
719 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
720 match self.kind() {
721 rustc_type_ir::GenericArgKind::Type(ty) => ty.hir_fmt(f),
722 rustc_type_ir::GenericArgKind::Lifetime(lt) => lt.hir_fmt(f),
723 rustc_type_ir::GenericArgKind::Const(c) => c.hir_fmt(f),
724 }
725 }
726}
727
728impl HirDisplay for Const {
729 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
730 let c = self.to_nextsolver(DbInterner::new_with(f.db, None, None));
731 c.hir_fmt(f)
732 }
733}
734
735impl<'db> HirDisplay for crate::next_solver::Const<'db> {
736 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
737 match self.kind() {
738 rustc_type_ir::ConstKind::Placeholder(_) => write!(f, "<placeholder>"),
739 rustc_type_ir::ConstKind::Bound(db, bound_const) => {
740 write!(f, "?{}.{}", db.as_u32(), bound_const.as_u32())
741 }
742 rustc_type_ir::ConstKind::Infer(..) => write!(f, "#c#"),
743 rustc_type_ir::ConstKind::Param(param) => {
744 let generics = generics(f.db, param.id.parent());
745 let param_data = &generics[param.id.local_id()];
746 write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
747 Ok(())
748 }
749 rustc_type_ir::ConstKind::Value(const_bytes) => render_const_scalar_ns(
750 f,
751 &const_bytes.value.inner().0,
752 &const_bytes.value.inner().1,
753 const_bytes.ty,
754 ),
755 rustc_type_ir::ConstKind::Unevaluated(unev) => {
756 let c = match unev.def {
757 SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
758 SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
759 _ => unreachable!(),
760 };
761 write!(f, "{}", c.name(f.db))?;
762 hir_fmt_generics_ns(f, unev.args.as_slice(), c.generic_def(f.db), None)?;
763 Ok(())
764 }
765 rustc_type_ir::ConstKind::Error(..) => f.write_char('_'),
766 rustc_type_ir::ConstKind::Expr(..) => write!(f, "<const-expr>"),
767 }
768 }
769}
770
771fn render_const_scalar(
772 f: &mut HirFormatter<'_>,
773 b: &[u8],
774 memory_map: &MemoryMap<'_>,
775 ty: &Ty,
776) -> Result<(), HirDisplayError> {
777 let trait_env = TraitEnvironment::empty(f.krate());
778 let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
779 let ty = normalize(f.db, trait_env.clone(), ty.clone());
780 let ty = ty.to_nextsolver(interner);
781 render_const_scalar_inner(f, b, memory_map, ty, trait_env)
782}
783
784fn render_const_scalar_ns(
785 f: &mut HirFormatter<'_>,
786 b: &[u8],
787 memory_map: &MemoryMap<'_>,
788 ty: crate::next_solver::Ty<'_>,
789) -> Result<(), HirDisplayError> {
790 let trait_env = TraitEnvironment::empty(f.krate());
791 let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
792 let ty = crate::next_solver::project::solve_normalize::normalize(
793 interner,
794 trait_env.env.to_nextsolver(interner),
795 ty,
796 );
797 render_const_scalar_inner(f, b, memory_map, ty, trait_env)
798}
799
800fn render_const_scalar_inner(
801 f: &mut HirFormatter<'_>,
802 b: &[u8],
803 memory_map: &MemoryMap<'_>,
804 ty: crate::next_solver::Ty<'_>,
805 trait_env: Arc<TraitEnvironment>,
806) -> Result<(), HirDisplayError> {
807 use rustc_type_ir::TyKind;
808 match ty.kind() {
809 TyKind::Bool => write!(f, "{}", b[0] != 0),
810 TyKind::Char => {
811 let it = u128::from_le_bytes(pad16(b, false)) as u32;
812 let Ok(c) = char::try_from(it) else {
813 return f.write_str("<unicode-error>");
814 };
815 write!(f, "{c:?}")
816 }
817 TyKind::Int(_) => {
818 let it = i128::from_le_bytes(pad16(b, true));
819 write!(f, "{it}")
820 }
821 TyKind::Uint(_) => {
822 let it = u128::from_le_bytes(pad16(b, false));
823 write!(f, "{it}")
824 }
825 TyKind::Float(fl) => match fl {
826 rustc_type_ir::FloatTy::F16 => {
827 let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());
829 let s = it.to_string();
830 if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
831 write!(f, "{s}.0")
833 } else {
834 write!(f, "{s}")
835 }
836 }
837 rustc_type_ir::FloatTy::F32 => {
838 let it = f32::from_le_bytes(b.try_into().unwrap());
839 write!(f, "{it:?}")
840 }
841 rustc_type_ir::FloatTy::F64 => {
842 let it = f64::from_le_bytes(b.try_into().unwrap());
843 write!(f, "{it:?}")
844 }
845 rustc_type_ir::FloatTy::F128 => {
846 let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));
848 let s = it.to_string();
849 if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
850 write!(f, "{s}.0")
852 } else {
853 write!(f, "{s}")
854 }
855 }
856 },
857 TyKind::Ref(_, t, _) => match t.kind() {
858 TyKind::Str => {
859 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
860 let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
861 let Some(bytes) = memory_map.get(addr, size) else {
862 return f.write_str("<ref-data-not-available>");
863 };
864 let s = std::str::from_utf8(bytes).unwrap_or("<utf8-error>");
865 write!(f, "{s:?}")
866 }
867 TyKind::Slice(ty) => {
868 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
869 let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
870 let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
871 return f.write_str("<layout-error>");
872 };
873 let size_one = layout.size.bytes_usize();
874 let Some(bytes) = memory_map.get(addr, size_one * count) else {
875 return f.write_str("<ref-data-not-available>");
876 };
877 let expected_len = count * size_one;
878 if bytes.len() < expected_len {
879 never!(
880 "Memory map size is too small. Expected {expected_len}, got {}",
881 bytes.len(),
882 );
883 return f.write_str("<layout-error>");
884 }
885 f.write_str("&[")?;
886 let mut first = true;
887 for i in 0..count {
888 if first {
889 first = false;
890 } else {
891 f.write_str(", ")?;
892 }
893 let offset = size_one * i;
894 render_const_scalar_ns(f, &bytes[offset..offset + size_one], memory_map, ty)?;
895 }
896 f.write_str("]")
897 }
898 TyKind::Dynamic(_, _, _) => {
899 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
900 let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
901 let Ok(t) = memory_map.vtable_ty(ty_id) else {
902 return f.write_str("<ty-missing-in-vtable-map>");
903 };
904 let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
905 return f.write_str("<layout-error>");
906 };
907 let size = layout.size.bytes_usize();
908 let Some(bytes) = memory_map.get(addr, size) else {
909 return f.write_str("<ref-data-not-available>");
910 };
911 f.write_str("&")?;
912 render_const_scalar_ns(f, bytes, memory_map, t)
913 }
914 TyKind::Adt(adt, _) if b.len() == 2 * size_of::<usize>() => match adt.def_id() {
915 SolverDefId::AdtId(hir_def::AdtId::StructId(s)) => {
916 let data = f.db.struct_signature(s);
917 write!(f, "&{}", data.name.display(f.db, f.edition()))?;
918 Ok(())
919 }
920 SolverDefId::AdtId(_) => f.write_str("<unsized-enum-or-union>"),
921 _ => unreachable!(),
922 },
923 _ => {
924 let addr = usize::from_le_bytes(match b.try_into() {
925 Ok(b) => b,
926 Err(_) => {
927 never!(
928 "tried rendering ty {:?} in const ref with incorrect byte count {}",
929 t,
930 b.len()
931 );
932 return f.write_str("<layout-error>");
933 }
934 });
935 let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
936 return f.write_str("<layout-error>");
937 };
938 let size = layout.size.bytes_usize();
939 let Some(bytes) = memory_map.get(addr, size) else {
940 return f.write_str("<ref-data-not-available>");
941 };
942 f.write_str("&")?;
943 render_const_scalar_ns(f, bytes, memory_map, t)
944 }
945 },
946 TyKind::Tuple(tys) => {
947 let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
948 return f.write_str("<layout-error>");
949 };
950 f.write_str("(")?;
951 let mut first = true;
952 for (id, ty) in tys.iter().enumerate() {
953 if first {
954 first = false;
955 } else {
956 f.write_str(", ")?;
957 }
958 let offset = layout.fields.offset(id).bytes_usize();
959 let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
960 f.write_str("<layout-error>")?;
961 continue;
962 };
963 let size = layout.size.bytes_usize();
964 render_const_scalar_ns(f, &b[offset..offset + size], memory_map, ty)?;
965 }
966 f.write_str(")")
967 }
968 TyKind::Adt(def, args) => {
969 let def = match def.def_id() {
970 SolverDefId::AdtId(def) => def,
971 _ => unreachable!(),
972 };
973 let Ok(layout) = f.db.layout_of_adt(def, args, trait_env.clone()) else {
974 return f.write_str("<layout-error>");
975 };
976 match def {
977 hir_def::AdtId::StructId(s) => {
978 let data = f.db.struct_signature(s);
979 write!(f, "{}", data.name.display(f.db, f.edition()))?;
980 let field_types = f.db.field_types(s.into());
981 render_variant_after_name(
982 s.fields(f.db),
983 f,
984 &field_types,
985 f.db.trait_environment(def.into()),
986 &layout,
987 args,
988 b,
989 memory_map,
990 )
991 }
992 hir_def::AdtId::UnionId(u) => {
993 write!(f, "{}", f.db.union_signature(u).name.display(f.db, f.edition()))
994 }
995 hir_def::AdtId::EnumId(e) => {
996 let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else {
997 return f.write_str("<target-layout-not-available>");
998 };
999 let Some((var_id, var_layout)) =
1000 detect_variant_from_bytes(&layout, f.db, &target_data_layout, b, e)
1001 else {
1002 return f.write_str("<failed-to-detect-variant>");
1003 };
1004 let loc = var_id.lookup(f.db);
1005 write!(
1006 f,
1007 "{}",
1008 loc.parent.enum_variants(f.db).variants[loc.index as usize]
1009 .1
1010 .display(f.db, f.edition())
1011 )?;
1012 let field_types = f.db.field_types(var_id.into());
1013 render_variant_after_name(
1014 var_id.fields(f.db),
1015 f,
1016 &field_types,
1017 f.db.trait_environment(def.into()),
1018 var_layout,
1019 args,
1020 b,
1021 memory_map,
1022 )
1023 }
1024 }
1025 }
1026 TyKind::FnDef(..) => ty.hir_fmt(f),
1027 TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {
1028 let it = u128::from_le_bytes(pad16(b, false));
1029 write!(f, "{it:#X} as ")?;
1030 ty.hir_fmt(f)
1031 }
1032 TyKind::Array(ty, len) => {
1033 let Some(len) = consteval_nextsolver::try_const_usize(f.db, len) else {
1034 return f.write_str("<unknown-array-len>");
1035 };
1036 let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
1037 return f.write_str("<layout-error>");
1038 };
1039 let size_one = layout.size.bytes_usize();
1040 f.write_str("[")?;
1041 let mut first = true;
1042 for i in 0..len as usize {
1043 if first {
1044 first = false;
1045 } else {
1046 f.write_str(", ")?;
1047 }
1048 let offset = size_one * i;
1049 render_const_scalar_ns(f, &b[offset..offset + size_one], memory_map, ty)?;
1050 }
1051 f.write_str("]")
1052 }
1053 TyKind::Never => f.write_str("!"),
1054 TyKind::Closure(_, _) => f.write_str("<closure>"),
1055 TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),
1056 TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),
1057 TyKind::CoroutineClosure(_, _) => f.write_str("<coroutine-closure>"),
1058 TyKind::UnsafeBinder(_) => f.write_str("<unsafe-binder>"),
1059 TyKind::Foreign(_) => f.write_str("<extern-type>"),
1061 TyKind::Pat(_, _) => f.write_str("<pat>"),
1062 TyKind::Error(..)
1063 | TyKind::Placeholder(_)
1064 | TyKind::Alias(_, _)
1065 | TyKind::Param(_)
1066 | TyKind::Bound(_, _)
1067 | TyKind::Infer(_) => f.write_str("<placeholder-or-unknown-type>"),
1068 TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(_, _, _) => f.write_str("<unsized-value>"),
1070 }
1071}
1072
1073fn render_variant_after_name(
1074 data: &VariantFields,
1075 f: &mut HirFormatter<'_>,
1076 field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
1077 trait_env: Arc<TraitEnvironment>,
1078 layout: &Layout,
1079 args: GenericArgs<'_>,
1080 b: &[u8],
1081 memory_map: &MemoryMap<'_>,
1082) -> Result<(), HirDisplayError> {
1083 let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
1084 match data.shape {
1085 FieldsShape::Record | FieldsShape::Tuple => {
1086 let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
1087 let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
1088 let ty = field_types[id]
1089 .clone()
1090 .substitute(Interner, &convert_args_for_result(interner, args.as_slice()));
1091 let Ok(layout) = f.db.layout_of_ty(ty.to_nextsolver(interner), trait_env.clone())
1092 else {
1093 return f.write_str("<layout-error>");
1094 };
1095 let size = layout.size.bytes_usize();
1096 render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)
1097 };
1098 let mut it = data.fields().iter();
1099 if matches!(data.shape, FieldsShape::Record) {
1100 write!(f, " {{")?;
1101 if let Some((id, data)) = it.next() {
1102 write!(f, " {}: ", data.name.display(f.db, f.edition()))?;
1103 render_field(f, id)?;
1104 }
1105 for (id, data) in it {
1106 write!(f, ", {}: ", data.name.display(f.db, f.edition()))?;
1107 render_field(f, id)?;
1108 }
1109 write!(f, " }}")?;
1110 } else {
1111 let mut it = it.map(|it| it.0);
1112 write!(f, "(")?;
1113 if let Some(id) = it.next() {
1114 render_field(f, id)?;
1115 }
1116 for id in it {
1117 write!(f, ", ")?;
1118 render_field(f, id)?;
1119 }
1120 write!(f, ")")?;
1121 }
1122 Ok(())
1123 }
1124 FieldsShape::Unit => Ok(()),
1125 }
1126}
1127
1128impl HirDisplay for BoundVar {
1129 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1130 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
1131 }
1132}
1133
1134impl HirDisplay for Ty {
1135 fn hir_fmt(
1136 &self,
1137 f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
1138 ) -> Result<(), HirDisplayError> {
1139 let ty = self.to_nextsolver(DbInterner::new_with(db, None, None));
1140 ty.hir_fmt(f)
1141 }
1142}
1143
1144impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
1145 fn hir_fmt(
1146 &self,
1147 f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
1148 ) -> Result<(), HirDisplayError> {
1149 let interner = DbInterner::new_with(db, None, None);
1150 if f.should_truncate() {
1151 return write!(f, "{TYPE_HINT_TRUNCATION}");
1152 }
1153
1154 use rustc_type_ir::TyKind;
1155 match self.kind() {
1156 TyKind::Never => write!(f, "!")?,
1157 TyKind::Str => write!(f, "str")?,
1158 TyKind::Bool => write!(f, "bool")?,
1159 TyKind::Char => write!(f, "char")?,
1160 TyKind::Float(t) => write!(f, "{}", primitive::float_ty_to_string_ns(t))?,
1161 TyKind::Int(t) => write!(f, "{}", primitive::int_ty_to_string_ns(t))?,
1162 TyKind::Uint(t) => write!(f, "{}", primitive::uint_ty_to_string_ns(t))?,
1163 TyKind::Slice(t) => {
1164 write!(f, "[")?;
1165 t.hir_fmt(f)?;
1166 write!(f, "]")?;
1167 }
1168 TyKind::Array(t, c) => {
1169 write!(f, "[")?;
1170 t.hir_fmt(f)?;
1171 write!(f, "; ")?;
1172 convert_const_for_result(interner, c).hir_fmt(f)?;
1173 write!(f, "]")?;
1174 }
1175 kind @ (TyKind::RawPtr(t, m) | TyKind::Ref(_, t, m)) => {
1176 if let TyKind::Ref(l, _, _) = kind {
1177 f.write_char('&')?;
1178 if f.render_region(l) {
1179 convert_region_for_result(interner, l).hir_fmt(f)?;
1180 f.write_char(' ')?;
1181 }
1182 match m {
1183 rustc_ast_ir::Mutability::Not => (),
1184 rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?,
1185 }
1186 } else {
1187 write!(
1188 f,
1189 "*{}",
1190 match m {
1191 rustc_ast_ir::Mutability::Not => "const ",
1192 rustc_ast_ir::Mutability::Mut => "mut ",
1193 }
1194 )?;
1195 }
1196
1197 let contains_impl_fn = |bounds: &[QuantifiedWhereClause]| {
1199 bounds.iter().any(|bound| {
1200 if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
1201 let trait_ = trait_ref.hir_trait_id();
1202 fn_traits(db, trait_).any(|it| it == trait_)
1203 } else {
1204 false
1205 }
1206 })
1207 };
1208 let contains_impl_fn_ns = |bounds: &[BoundExistentialPredicate<'_>]| {
1209 bounds.iter().any(|bound| match bound.skip_binder() {
1210 rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => {
1211 let trait_ = match trait_ref.def_id {
1212 SolverDefId::TraitId(id) => id,
1213 _ => unreachable!(),
1214 };
1215 fn_traits(db, trait_).any(|it| it == trait_)
1216 }
1217 _ => false,
1218 })
1219 };
1220 let (preds_to_print, has_impl_fn_pred) = match t.kind() {
1221 TyKind::Dynamic(bounds, region, _) => {
1222 let render_lifetime = f.render_region(region);
1223 (
1224 bounds.len() + render_lifetime as usize,
1225 contains_impl_fn_ns(bounds.as_slice()),
1226 )
1227 }
1228 TyKind::Alias(AliasTyKind::Opaque, ty) => {
1229 let opaque_ty_id = match ty.def_id {
1230 SolverDefId::InternedOpaqueTyId(id) => id,
1231 _ => unreachable!(),
1232 };
1233 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
1234 if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
1235 let datas = db
1236 .return_type_impl_traits(func)
1237 .expect("impl trait id without data");
1238 let data =
1239 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1240 let bounds = data.substitute(
1241 Interner,
1242 &convert_args_for_result(interner, ty.args.as_slice()),
1243 );
1244 let mut len = bounds.skip_binders().len();
1245
1246 let default_sized = SizedByDefault::Sized { anchor: func.krate(db) };
1249 let sized_bounds = bounds
1250 .skip_binders()
1251 .iter()
1252 .filter(|b| {
1253 matches!(
1254 b.skip_binders(),
1255 WhereClause::Implemented(trait_ref)
1256 if default_sized.is_sized_trait(
1257 trait_ref.hir_trait_id(),
1258 db,
1259 ),
1260 )
1261 })
1262 .count();
1263 match sized_bounds {
1264 0 => len += 1,
1265 _ => {
1266 len = len.saturating_sub(sized_bounds);
1267 }
1268 }
1269
1270 (len, contains_impl_fn(bounds.skip_binders()))
1271 } else {
1272 (0, false)
1273 }
1274 }
1275 _ => (0, false),
1276 };
1277
1278 if has_impl_fn_pred && preds_to_print <= 2 {
1279 return t.hir_fmt(f);
1280 }
1281
1282 if preds_to_print > 1 {
1283 write!(f, "(")?;
1284 t.hir_fmt(f)?;
1285 write!(f, ")")?;
1286 } else {
1287 t.hir_fmt(f)?;
1288 }
1289 }
1290 TyKind::Tuple(tys) => {
1291 if tys.len() == 1 {
1292 write!(f, "(")?;
1293 tys.as_slice()[0].hir_fmt(f)?;
1294 write!(f, ",)")?;
1295 } else {
1296 write!(f, "(")?;
1297 f.write_joined(tys.as_slice(), ", ")?;
1298 write!(f, ")")?;
1299 }
1300 }
1301 TyKind::FnPtr(sig, header) => {
1302 let sig = CallableSig::from_fn_sig_and_header(interner, sig, header);
1303 sig.hir_fmt(f)?;
1304 }
1305 TyKind::FnDef(def, args) => {
1306 let def = match def {
1307 SolverDefId::FunctionId(id) => CallableDefId::FunctionId(id),
1308 SolverDefId::Ctor(Ctor::Enum(e)) => CallableDefId::EnumVariantId(e),
1309 SolverDefId::Ctor(Ctor::Struct(s)) => CallableDefId::StructId(s),
1310 _ => unreachable!(),
1311 };
1312 let sig = db
1313 .callable_item_signature(def)
1314 .substitute(Interner, &convert_args_for_result(interner, args.as_slice()));
1315
1316 if f.display_kind.is_source_code() {
1317 return sig.hir_fmt(f);
1320 }
1321 if let Safety::Unsafe = sig.safety {
1322 write!(f, "unsafe ")?;
1323 }
1324 if !matches!(sig.abi, FnAbi::Rust | FnAbi::RustCall) {
1325 f.write_str("extern \"")?;
1326 f.write_str(sig.abi.as_str())?;
1327 f.write_str("\" ")?;
1328 }
1329
1330 write!(f, "fn ")?;
1331 f.start_location_link(def.into());
1332 match def {
1333 CallableDefId::FunctionId(ff) => {
1334 write!(f, "{}", db.function_signature(ff).name.display(f.db, f.edition()))?
1335 }
1336 CallableDefId::StructId(s) => {
1337 write!(f, "{}", db.struct_signature(s).name.display(f.db, f.edition()))?
1338 }
1339 CallableDefId::EnumVariantId(e) => {
1340 let loc = e.lookup(db);
1341 write!(
1342 f,
1343 "{}",
1344 loc.parent.enum_variants(db).variants[loc.index as usize]
1345 .1
1346 .display(db, f.edition())
1347 )?
1348 }
1349 };
1350 f.end_location_link();
1351
1352 let parameters = convert_args_for_result(interner, args.as_slice());
1353 if parameters.len(Interner) > 0 {
1354 let generic_def_id = GenericDefId::from_callable(db, def);
1355 let generics = generics(db, generic_def_id);
1356 let (parent_len, self_param, type_, const_, impl_, lifetime) =
1357 generics.provenance_split();
1358 let parameters = parameters.as_slice(Interner);
1359 debug_assert_eq!(
1360 parameters.len(),
1361 parent_len + self_param as usize + type_ + const_ + impl_ + lifetime
1362 );
1363 if parameters.len() - impl_ > 0 {
1365 let params_len = parameters.len();
1366 let parameters =
1368 generic_args_sans_defaults(f, Some(generic_def_id), parameters);
1369 assert!(params_len >= parameters.len());
1370 let defaults = params_len - parameters.len();
1371
1372 let parent_end = if parent_len > 0 {
1380 parent_len - defaults
1383 } else {
1384 parent_len
1385 };
1386 let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;
1387 let (parent_params, fn_params) = parameters.split_at(parent_end);
1388
1389 write!(f, "<")?;
1390 hir_fmt_generic_arguments(f, parent_params, None)?;
1391 if !parent_params.is_empty() && !fn_params.is_empty() {
1392 write!(f, ", ")?;
1393 }
1394 hir_fmt_generic_arguments(
1395 f,
1396 &fn_params[..fn_params_no_impl_or_defaults],
1397 None,
1398 )?;
1399 write!(f, ">")?;
1400 }
1401 }
1402 write!(f, "(")?;
1403 f.write_joined(sig.params(), ", ")?;
1404 write!(f, ")")?;
1405 let ret = sig.ret();
1406 if !ret.is_unit() {
1407 write!(f, " -> ")?;
1408 ret.hir_fmt(f)?;
1409 }
1410 }
1411 TyKind::Adt(def, parameters) => {
1412 let def_id = match def.def_id() {
1413 SolverDefId::AdtId(id) => id,
1414 _ => unreachable!(),
1415 };
1416 f.start_location_link(def_id.into());
1417 match f.display_kind {
1418 DisplayKind::Diagnostics | DisplayKind::Test => {
1419 let name = match def_id {
1420 hir_def::AdtId::StructId(it) => db.struct_signature(it).name.clone(),
1421 hir_def::AdtId::UnionId(it) => db.union_signature(it).name.clone(),
1422 hir_def::AdtId::EnumId(it) => db.enum_signature(it).name.clone(),
1423 };
1424 write!(f, "{}", name.display(f.db, f.edition()))?;
1425 }
1426 DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => {
1427 if let Some(path) = find_path::find_path(
1428 db,
1429 ItemInNs::Types(def_id.into()),
1430 module_id,
1431 PrefixKind::Plain,
1432 false,
1433 ImportPathConfig {
1435 prefer_no_std: false,
1436 prefer_prelude: true,
1437 prefer_absolute: false,
1438 allow_unstable: true,
1439 },
1440 ) {
1441 write!(f, "{}", path.display(f.db, f.edition()))?;
1442 } else {
1443 return Err(HirDisplayError::DisplaySourceCodeError(
1444 DisplaySourceCodeError::PathNotFound,
1445 ));
1446 }
1447 }
1448 }
1449 f.end_location_link();
1450
1451 hir_fmt_generics(
1452 f,
1453 convert_args_for_result(interner, parameters.as_slice()).as_slice(Interner),
1454 def.def_id().try_into().ok(),
1455 None,
1456 )?;
1457 }
1458 TyKind::Alias(AliasTyKind::Projection, alias_ty) => {
1459 let type_alias = match alias_ty.def_id {
1460 SolverDefId::TypeAliasId(id) => id,
1461 _ => unreachable!(),
1462 };
1463 let parameters = convert_args_for_result(interner, alias_ty.args.as_slice());
1464
1465 let projection_ty = ProjectionTy {
1466 associated_ty_id: to_assoc_type_id(type_alias),
1467 substitution: parameters.clone(),
1468 };
1469
1470 projection_ty.hir_fmt(f)?;
1471 }
1472 TyKind::Foreign(type_alias) => {
1473 let alias = match type_alias {
1474 SolverDefId::TypeAliasId(id) => id,
1475 _ => unreachable!(),
1476 };
1477 let type_alias = db.type_alias_signature(alias);
1478 f.start_location_link(alias.into());
1479 write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
1480 f.end_location_link();
1481 }
1482 TyKind::Alias(AliasTyKind::Opaque, alias_ty) => {
1483 let opaque_ty_id = match alias_ty.def_id {
1484 SolverDefId::InternedOpaqueTyId(id) => id,
1485 _ => unreachable!(),
1486 };
1487 let parameters = convert_args_for_result(interner, alias_ty.args.as_slice());
1488 if !f.display_kind.allows_opaque() {
1489 return Err(HirDisplayError::DisplaySourceCodeError(
1490 DisplaySourceCodeError::OpaqueType,
1491 ));
1492 }
1493 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
1494 match impl_trait_id {
1495 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1496 let datas =
1497 db.return_type_impl_traits(func).expect("impl trait id without data");
1498 let data =
1499 (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
1500 let bounds = data.substitute(Interner, ¶meters);
1501 let krate = func.krate(db);
1502 write_bounds_like_dyn_trait_with_prefix(
1503 f,
1504 "impl",
1505 Either::Left(&convert_ty_for_result(interner, *self)),
1506 bounds.skip_binders(),
1507 SizedByDefault::Sized { anchor: krate },
1508 )?;
1509 }
1511 ImplTraitId::TypeAliasImplTrait(alias, idx) => {
1512 let datas =
1513 db.type_alias_impl_traits(alias).expect("impl trait id without data");
1514 let data = (*datas).as_ref().map(|it| it.impl_traits[idx].bounds.clone());
1515 let bounds = data.substitute(Interner, ¶meters);
1516 let krate = alias.krate(db);
1517 write_bounds_like_dyn_trait_with_prefix(
1518 f,
1519 "impl",
1520 Either::Left(&convert_ty_for_result(interner, *self)),
1521 bounds.skip_binders(),
1522 SizedByDefault::Sized { anchor: krate },
1523 )?;
1524 }
1525 ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
1526 let future_trait =
1527 LangItem::Future.resolve_trait(db, body.module(db).krate());
1528 let output = future_trait.and_then(|t| {
1529 t.trait_items(db)
1530 .associated_type_by_name(&Name::new_symbol_root(sym::Output))
1531 });
1532 write!(f, "impl ")?;
1533 if let Some(t) = future_trait {
1534 f.start_location_link(t.into());
1535 }
1536 write!(f, "Future")?;
1537 if future_trait.is_some() {
1538 f.end_location_link();
1539 }
1540 write!(f, "<")?;
1541 if let Some(t) = output {
1542 f.start_location_link(t.into());
1543 }
1544 write!(f, "Output")?;
1545 if output.is_some() {
1546 f.end_location_link();
1547 }
1548 write!(f, " = ")?;
1549 parameters.at(Interner, 0).hir_fmt(f)?;
1550 write!(f, ">")?;
1551 }
1552 }
1553 }
1554 TyKind::Closure(id, substs) => {
1555 let id = match id {
1556 SolverDefId::InternedClosureId(id) => id,
1557 _ => unreachable!(),
1558 };
1559 let substs = convert_args_for_result(interner, substs.as_slice());
1560 if f.display_kind.is_source_code() {
1561 if !f.display_kind.allows_opaque() {
1562 return Err(HirDisplayError::DisplaySourceCodeError(
1563 DisplaySourceCodeError::OpaqueType,
1564 ));
1565 } else if f.closure_style != ClosureStyle::ImplFn {
1566 never!("Only `impl Fn` is valid for displaying closures in source code");
1567 }
1568 }
1569 let chalk_id: chalk_ir::ClosureId<_> = id.into();
1570 match f.closure_style {
1571 ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
1572 ClosureStyle::ClosureWithId => {
1573 return write!(f, "{{closure#{:?}}}", chalk_id.0.index());
1574 }
1575 ClosureStyle::ClosureWithSubst => {
1576 write!(f, "{{closure#{:?}}}", chalk_id.0.index())?;
1577 return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
1578 }
1579 _ => (),
1580 }
1581 let sig = ClosureSubst(&substs).sig_ty().callable_sig(db);
1582 if let Some(sig) = sig {
1583 let InternedClosure(def, _) = db.lookup_intern_closure(id);
1584 let infer = db.infer(def);
1585 let (_, kind) = infer.closure_info(&chalk_id);
1586 match f.closure_style {
1587 ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
1588 ClosureStyle::RANotation => write!(f, "|")?,
1589 _ => unreachable!(),
1590 }
1591 if sig.params().is_empty() {
1592 } else if f.should_truncate() {
1593 write!(f, "{TYPE_HINT_TRUNCATION}")?;
1594 } else {
1595 f.write_joined(sig.params(), ", ")?;
1596 };
1597 match f.closure_style {
1598 ClosureStyle::ImplFn => write!(f, ")")?,
1599 ClosureStyle::RANotation => write!(f, "|")?,
1600 _ => unreachable!(),
1601 }
1602 if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() {
1603 write!(f, " -> ")?;
1604 sig.ret().hir_fmt(f)?;
1607 }
1608 } else {
1609 write!(f, "{{closure}}")?;
1610 }
1611 }
1612 TyKind::Placeholder(_) => write!(f, "{{placeholder}}")?,
1613 TyKind::Param(param) => {
1614 let generics = generics(db, param.id.parent());
1615 let param_data = &generics[param.id.local_id()];
1616 match param_data {
1617 TypeOrConstParamData::TypeParamData(p) => match p.provenance {
1618 TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
1619 write!(
1620 f,
1621 "{}",
1622 p.name
1623 .clone()
1624 .unwrap_or_else(Name::missing)
1625 .display(f.db, f.edition())
1626 )?
1627 }
1628 TypeParamProvenance::ArgumentImplTrait => {
1629 let substs = generics.placeholder_subst(db);
1630 let bounds = db
1631 .generic_predicates(param.id.parent())
1632 .iter()
1633 .map(|pred| pred.clone().substitute(Interner, &substs))
1634 .filter(|wc| match wc.skip_binders() {
1635 WhereClause::Implemented(tr) => {
1636 tr.self_type_parameter(Interner)
1637 == convert_ty_for_result(interner, *self)
1638 }
1639 WhereClause::AliasEq(AliasEq {
1640 alias: AliasTy::Projection(proj),
1641 ty: _,
1642 }) => {
1643 proj.self_type_parameter(db)
1644 == convert_ty_for_result(interner, *self)
1645 }
1646 WhereClause::AliasEq(_) => false,
1647 WhereClause::TypeOutlives(to) => {
1648 to.ty == convert_ty_for_result(interner, *self)
1649 }
1650 WhereClause::LifetimeOutlives(_) => false,
1651 })
1652 .collect::<Vec<_>>();
1653 let krate = param.id.parent().module(db).krate();
1654 write_bounds_like_dyn_trait_with_prefix(
1655 f,
1656 "impl",
1657 Either::Left(&convert_ty_for_result(interner, *self)),
1658 &bounds,
1659 SizedByDefault::Sized { anchor: krate },
1660 )?;
1661 }
1662 },
1663 TypeOrConstParamData::ConstParamData(p) => {
1664 write!(f, "{}", p.name.display(f.db, f.edition()))?;
1665 }
1666 }
1667 }
1668 TyKind::Bound(debruijn_index, ty) => {
1669 let idx = chalk_ir::BoundVar {
1670 debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
1671 index: ty.var.as_usize(),
1672 };
1673 idx.hir_fmt(f)?
1674 }
1675 TyKind::Dynamic(..) => {
1676 let ty = convert_ty_for_result(interner, *self);
1677 let chalk_ir::TyKind::Dyn(dyn_ty) = ty.kind(Interner) else { unreachable!() };
1678 let mut bounds: SmallVec<[_; 4]> =
1682 dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
1683 let (auto_traits, others): (SmallVec<[_; 4]>, _) =
1684 bounds.drain(1..).partition(|b| b.skip_binders().trait_id().is_some());
1685 bounds.extend(others);
1686 bounds.extend(auto_traits);
1687
1688 if f.render_lifetime(&dyn_ty.lifetime) {
1689 bounds.push(Binders::empty(
1691 Interner,
1692 chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
1693 ty: ty.clone(),
1694 lifetime: dyn_ty.lifetime.clone(),
1695 }),
1696 ));
1697 }
1698
1699 write_bounds_like_dyn_trait_with_prefix(
1700 f,
1701 "dyn",
1702 Either::Left(&ty),
1703 &bounds,
1704 SizedByDefault::NotSized,
1705 )?;
1706 }
1707 TyKind::Error(_) => {
1708 if f.display_kind.is_source_code() {
1709 f.write_char('_')?;
1710 } else {
1711 write!(f, "{{unknown}}")?;
1712 }
1713 }
1714 TyKind::Infer(..) => write!(f, "_")?,
1715 TyKind::Coroutine(_, subst) => {
1716 if f.display_kind.is_source_code() {
1717 return Err(HirDisplayError::DisplaySourceCodeError(
1718 DisplaySourceCodeError::Coroutine,
1719 ));
1720 }
1721 let subst = convert_args_for_result(interner, subst.as_slice());
1722 let subst = subst.as_slice(Interner);
1723 let a: Option<SmallVec<[&Ty; 3]>> = subst
1724 .get(subst.len() - 3..)
1725 .and_then(|args| args.iter().map(|arg| arg.ty(Interner)).collect());
1726
1727 if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
1728 write!(f, "|")?;
1729 resume_ty.hir_fmt(f)?;
1730 write!(f, "|")?;
1731
1732 write!(f, " yields ")?;
1733 yield_ty.hir_fmt(f)?;
1734
1735 write!(f, " -> ")?;
1736 ret_ty.hir_fmt(f)?;
1737 } else {
1738 write!(f, "{{coroutine}}")?;
1740 }
1741 }
1742 TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
1743 TyKind::Pat(_, _) => write!(f, "{{pat}}")?,
1744 TyKind::UnsafeBinder(_) => write!(f, "{{unsafe binder}}")?,
1745 TyKind::CoroutineClosure(_, _) => write!(f, "{{coroutine closure}}")?,
1746 TyKind::Alias(_, _) => write!(f, "{{alias}}")?,
1747 }
1748 Ok(())
1749 }
1750}
1751
1752fn hir_fmt_generics(
1753 f: &mut HirFormatter<'_>,
1754 parameters: &[GenericArg],
1755 generic_def: Option<hir_def::GenericDefId>,
1756 self_: Option<&Ty>,
1757) -> Result<(), HirDisplayError> {
1758 if parameters.is_empty() {
1759 return Ok(());
1760 }
1761
1762 let parameters_to_write = generic_args_sans_defaults(f, generic_def, parameters);
1763
1764 if !parameters_to_write.is_empty() {
1765 write!(f, "<")?;
1766 hir_fmt_generic_arguments(f, parameters_to_write, self_)?;
1767 write!(f, ">")?;
1768 }
1769
1770 Ok(())
1771}
1772
1773fn hir_fmt_generics_ns<'db>(
1774 f: &mut HirFormatter<'_>,
1775 parameters: &[crate::next_solver::GenericArg<'db>],
1776 generic_def: Option<hir_def::GenericDefId>,
1777 self_: Option<crate::next_solver::Ty<'db>>,
1778) -> Result<(), HirDisplayError> {
1779 if parameters.is_empty() {
1780 return Ok(());
1781 }
1782
1783 let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
1784
1785 if !parameters_to_write.is_empty() {
1786 write!(f, "<")?;
1787 hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
1788 write!(f, ">")?;
1789 }
1790
1791 Ok(())
1792}
1793
1794fn generic_args_sans_defaults<'ga>(
1795 f: &mut HirFormatter<'_>,
1796 generic_def: Option<hir_def::GenericDefId>,
1797 parameters: &'ga [GenericArg],
1798) -> &'ga [GenericArg] {
1799 if f.display_kind.is_source_code() || f.omit_verbose_types() {
1800 match generic_def
1801 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
1802 .filter(|it| !it.is_empty())
1803 {
1804 None => parameters,
1805 Some(default_parameters) => {
1806 let should_show = |arg: &GenericArg, i: usize| {
1807 let is_err = |arg: &GenericArg| match arg.data(Interner) {
1808 chalk_ir::GenericArgData::Lifetime(it) => {
1809 *it.data(Interner) == LifetimeData::Error
1810 }
1811 chalk_ir::GenericArgData::Ty(it) => *it.kind(Interner) == TyKind::Error,
1812 chalk_ir::GenericArgData::Const(it) => matches!(
1813 it.data(Interner).value,
1814 ConstValue::Concrete(ConcreteConst {
1815 interned: ConstScalar::Unknown,
1816 ..
1817 })
1818 ),
1819 };
1820 if is_err(arg) {
1822 return true;
1823 }
1824 match default_parameters.get(i) {
1827 None => true,
1828 Some(default_parameter) => {
1829 arg != &default_parameter.clone().substitute(Interner, ¶meters[..i])
1832 }
1833 }
1834 };
1835 let mut default_from = 0;
1836 for (i, parameter) in parameters.iter().enumerate() {
1837 if should_show(parameter, i) {
1838 default_from = i + 1;
1839 }
1840 }
1841 ¶meters[0..default_from]
1842 }
1843 }
1844 } else {
1845 parameters
1846 }
1847}
1848
1849fn hir_fmt_generic_args<'db>(
1850 f: &mut HirFormatter<'_>,
1851 parameters: &[crate::next_solver::GenericArg<'db>],
1852 generic_def: Option<hir_def::GenericDefId>,
1853 self_: Option<crate::next_solver::Ty<'db>>,
1854) -> Result<(), HirDisplayError> {
1855 if parameters.is_empty() {
1856 return Ok(());
1857 }
1858
1859 let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
1860
1861 if !parameters_to_write.is_empty() {
1862 write!(f, "<")?;
1863 hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
1864 write!(f, ">")?;
1865 }
1866
1867 Ok(())
1868}
1869
1870fn generic_args_sans_defaults_ns<'ga, 'db>(
1871 f: &mut HirFormatter<'_>,
1872 generic_def: Option<hir_def::GenericDefId>,
1873 parameters: &'ga [crate::next_solver::GenericArg<'db>],
1874) -> &'ga [crate::next_solver::GenericArg<'db>] {
1875 let interner = DbInterner::new_with(f.db, Some(f.krate()), None);
1876 if f.display_kind.is_source_code() || f.omit_verbose_types() {
1877 match generic_def
1878 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
1879 .filter(|it| !it.is_empty())
1880 {
1881 None => parameters,
1882 Some(default_parameters) => {
1883 let should_show = |arg: &crate::next_solver::GenericArg<'db>, i: usize| {
1884 let is_err = |arg: &crate::next_solver::GenericArg<'db>| match arg.kind() {
1885 rustc_type_ir::GenericArgKind::Lifetime(it) => {
1886 matches!(it.kind(), RegionKind::ReError(..))
1887 }
1888 rustc_type_ir::GenericArgKind::Type(it) => {
1889 matches!(it.kind(), rustc_type_ir::TyKind::Error(..))
1890 }
1891 rustc_type_ir::GenericArgKind::Const(it) => {
1892 matches!(it.kind(), rustc_type_ir::ConstKind::Error(..),)
1893 }
1894 };
1895 if is_err(arg) {
1897 return true;
1898 }
1899 match default_parameters.get(i) {
1902 None => true,
1903 Some(default_parameter) => {
1904 arg != &default_parameter
1907 .clone()
1908 .substitute(
1909 Interner,
1910 &convert_args_for_result(interner, ¶meters[..i]),
1911 )
1912 .to_nextsolver(interner)
1913 }
1914 }
1915 };
1916 let mut default_from = 0;
1917 for (i, parameter) in parameters.iter().enumerate() {
1918 if should_show(parameter, i) {
1919 default_from = i + 1;
1920 }
1921 }
1922 ¶meters[0..default_from]
1923 }
1924 }
1925 } else {
1926 parameters
1927 }
1928}
1929
1930fn hir_fmt_generic_arguments(
1931 f: &mut HirFormatter<'_>,
1932 parameters: &[GenericArg],
1933 self_: Option<&Ty>,
1934) -> Result<(), HirDisplayError> {
1935 let mut first = true;
1936 let lifetime_offset = parameters.iter().position(|arg| arg.lifetime(Interner).is_some());
1937
1938 let (ty_or_const, lifetimes) = match lifetime_offset {
1939 Some(offset) => parameters.split_at(offset),
1940 None => (parameters, &[][..]),
1941 };
1942 for generic_arg in lifetimes.iter().chain(ty_or_const) {
1943 if !mem::take(&mut first) {
1944 write!(f, ", ")?;
1945 }
1946 match self_ {
1947 self_ @ Some(_) if generic_arg.ty(Interner) == self_ => write!(f, "Self")?,
1948 _ => generic_arg.hir_fmt(f)?,
1949 }
1950 }
1951 Ok(())
1952}
1953
1954fn hir_fmt_generic_arguments_ns<'db>(
1955 f: &mut HirFormatter<'_>,
1956 parameters: &[crate::next_solver::GenericArg<'db>],
1957 self_: Option<crate::next_solver::Ty<'db>>,
1958) -> Result<(), HirDisplayError> {
1959 let mut first = true;
1960 let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some());
1961
1962 let (ty_or_const, lifetimes) = match lifetime_offset {
1963 Some(offset) => parameters.split_at(offset),
1964 None => (parameters, &[][..]),
1965 };
1966 for generic_arg in lifetimes.iter().chain(ty_or_const) {
1967 if !mem::take(&mut first) {
1968 write!(f, ", ")?;
1969 }
1970 match self_ {
1971 self_ @ Some(_) if generic_arg.ty() == self_ => write!(f, "Self")?,
1972 _ => generic_arg.hir_fmt(f)?,
1973 }
1974 }
1975 Ok(())
1976}
1977
1978impl HirDisplay for CallableSig {
1979 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
1980 let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self;
1981 if let Safety::Unsafe = safety {
1982 write!(f, "unsafe ")?;
1983 }
1984 write!(f, "fn(")?;
1991 f.write_joined(self.params(), ", ")?;
1992 if is_varargs {
1993 if self.params().is_empty() {
1994 write!(f, "...")?;
1995 } else {
1996 write!(f, ", ...")?;
1997 }
1998 }
1999 write!(f, ")")?;
2000 let ret = self.ret();
2001 if !ret.is_unit() {
2002 write!(f, " -> ")?;
2003 ret.hir_fmt(f)?;
2004 }
2005 Ok(())
2006 }
2007}
2008
2009fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
2010 let krate = trait_.lookup(db).container.krate();
2011 utils::fn_traits(db, krate)
2012}
2013
2014#[derive(Clone, Copy, PartialEq, Eq)]
2015pub enum SizedByDefault {
2016 NotSized,
2017 Sized { anchor: Crate },
2018}
2019
2020impl SizedByDefault {
2021 fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
2022 match self {
2023 Self::NotSized => false,
2024 Self::Sized { anchor } => {
2025 let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
2026 Some(trait_) == sized_trait
2027 }
2028 }
2029 }
2030}
2031
2032pub fn write_bounds_like_dyn_trait_with_prefix(
2033 f: &mut HirFormatter<'_>,
2034 prefix: &str,
2035 this: Either<&Ty, &Lifetime>,
2036 predicates: &[QuantifiedWhereClause],
2037 default_sized: SizedByDefault,
2038) -> Result<(), HirDisplayError> {
2039 write!(f, "{prefix}")?;
2040 if !predicates.is_empty()
2041 || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
2042 {
2043 write!(f, " ")?;
2044 write_bounds_like_dyn_trait(f, this, predicates, default_sized)
2045 } else {
2046 Ok(())
2047 }
2048}
2049
2050fn write_bounds_like_dyn_trait(
2051 f: &mut HirFormatter<'_>,
2052 this: Either<&Ty, &Lifetime>,
2053 predicates: &[QuantifiedWhereClause],
2054 default_sized: SizedByDefault,
2055) -> Result<(), HirDisplayError> {
2056 let mut first = true;
2063 let mut angle_open = false;
2064 let mut is_fn_trait = false;
2065 let mut is_sized = false;
2066 for p in predicates.iter() {
2067 match p.skip_binders() {
2068 WhereClause::Implemented(trait_ref) => {
2069 let trait_ = trait_ref.hir_trait_id();
2070 if default_sized.is_sized_trait(trait_, f.db) {
2071 is_sized = true;
2072 if matches!(default_sized, SizedByDefault::Sized { .. }) {
2073 continue;
2075 }
2076 }
2077 if !is_fn_trait {
2078 is_fn_trait = fn_traits(f.db, trait_).any(|it| it == trait_);
2079 }
2080 if !is_fn_trait && angle_open {
2081 write!(f, ">")?;
2082 angle_open = false;
2083 }
2084 if !first {
2085 write!(f, " + ")?;
2086 }
2087 f.start_location_link(trait_.into());
2091 write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
2092 f.end_location_link();
2093 if is_fn_trait {
2094 if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner)
2095 && let Some(args) =
2096 params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
2097 {
2098 write!(f, "(")?;
2099 hir_fmt_generic_arguments(f, args.as_slice(Interner), self_.ty(Interner))?;
2100 write!(f, ")")?;
2101 }
2102 } else {
2103 let params = generic_args_sans_defaults(
2104 f,
2105 Some(trait_.into()),
2106 trait_ref.substitution.as_slice(Interner),
2107 );
2108 if let [self_, params @ ..] = params
2109 && !params.is_empty()
2110 {
2111 write!(f, "<")?;
2112 hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
2113 angle_open = true;
2115 }
2116 }
2117 }
2118 WhereClause::TypeOutlives(to) if Either::Left(&to.ty) == this => {
2119 if !is_fn_trait && angle_open {
2120 write!(f, ">")?;
2121 angle_open = false;
2122 }
2123 if !first {
2124 write!(f, " + ")?;
2125 }
2126 to.lifetime.hir_fmt(f)?;
2127 }
2128 WhereClause::TypeOutlives(_) => {}
2129 WhereClause::LifetimeOutlives(lo) if Either::Right(&lo.a) == this => {
2130 if !is_fn_trait && angle_open {
2131 write!(f, ">")?;
2132 angle_open = false;
2133 }
2134 if !first {
2135 write!(f, " + ")?;
2136 }
2137 lo.b.hir_fmt(f)?;
2138 }
2139 WhereClause::LifetimeOutlives(_) => {}
2140 WhereClause::AliasEq(alias_eq) if is_fn_trait => {
2141 is_fn_trait = false;
2142 if !alias_eq.ty.is_unit() {
2143 write!(f, " -> ")?;
2144 alias_eq.ty.hir_fmt(f)?;
2145 }
2146 }
2147 WhereClause::AliasEq(AliasEq { ty, alias }) => {
2148 if angle_open {
2151 write!(f, ", ")?;
2152 } else {
2153 write!(f, "<")?;
2154 angle_open = true;
2155 }
2156 if let AliasTy::Projection(proj) = alias {
2157 let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
2158 let type_alias = f.db.type_alias_signature(assoc_ty_id);
2159 f.start_location_link(assoc_ty_id.into());
2160 write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
2161 f.end_location_link();
2162
2163 let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self();
2164 let parent_len = proj.substitution.len(Interner) - proj_arg_count;
2165 if proj_arg_count > 0 {
2166 write!(f, "<")?;
2167 hir_fmt_generic_arguments(
2168 f,
2169 &proj.substitution.as_slice(Interner)[parent_len..],
2170 None,
2171 )?;
2172 write!(f, ">")?;
2173 }
2174 write!(f, " = ")?;
2175 }
2176 ty.hir_fmt(f)?;
2177 }
2178 }
2179 first = false;
2180 }
2181 if angle_open {
2182 write!(f, ">")?;
2183 }
2184 if let SizedByDefault::Sized { anchor } = default_sized {
2185 let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
2186 if !is_sized {
2187 if !first {
2188 write!(f, " + ")?;
2189 }
2190 if let Some(sized_trait) = sized_trait {
2191 f.start_location_link(sized_trait.into());
2192 }
2193 write!(f, "?Sized")?;
2194 } else if first {
2195 if let Some(sized_trait) = sized_trait {
2196 f.start_location_link(sized_trait.into());
2197 }
2198 write!(f, "Sized")?;
2199 }
2200 if sized_trait.is_some() {
2201 f.end_location_link();
2202 }
2203 }
2204 Ok(())
2205}
2206
2207impl HirDisplay for TraitRef {
2208 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2209 let trait_ = self.hir_trait_id();
2210 f.start_location_link(trait_.into());
2211 write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
2212 f.end_location_link();
2213 let substs = self.substitution.as_slice(Interner);
2214 hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
2215 }
2216}
2217
2218impl<'db> HirDisplay for crate::next_solver::TraitRef<'db> {
2219 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2220 let trait_ = match self.def_id {
2221 SolverDefId::TraitId(id) => id,
2222 _ => unreachable!(),
2223 };
2224 f.start_location_link(trait_.into());
2225 write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
2226 f.end_location_link();
2227 let substs = self.args.as_slice();
2228 hir_fmt_generic_args(f, &substs[1..], None, substs[0].ty())
2229 }
2230}
2231
2232impl HirDisplay for WhereClause {
2233 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2234 if f.should_truncate() {
2235 return write!(f, "{TYPE_HINT_TRUNCATION}");
2236 }
2237
2238 match self {
2239 WhereClause::Implemented(trait_ref) => {
2240 trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
2241 write!(f, ": ")?;
2242 trait_ref.hir_fmt(f)?;
2243 }
2244 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
2245 write!(f, "<")?;
2246 let trait_ref = &projection_ty.trait_ref(f.db);
2247 trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
2248 write!(f, " as ")?;
2249 trait_ref.hir_fmt(f)?;
2250 write!(f, ">::",)?;
2251 let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
2252 f.start_location_link(type_alias.into());
2253 write!(
2254 f,
2255 "{}",
2256 f.db.type_alias_signature(type_alias).name.display(f.db, f.edition()),
2257 )?;
2258 f.end_location_link();
2259 write!(f, " = ")?;
2260 ty.hir_fmt(f)?;
2261 }
2262 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
2263
2264 WhereClause::TypeOutlives(..) => {}
2266 WhereClause::LifetimeOutlives(..) => {}
2267 }
2268 Ok(())
2269 }
2270}
2271
2272impl HirDisplay for LifetimeOutlives {
2273 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2274 self.a.hir_fmt(f)?;
2275 write!(f, ": ")?;
2276 self.b.hir_fmt(f)
2277 }
2278}
2279
2280impl HirDisplay for Lifetime {
2281 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2282 self.interned().hir_fmt(f)
2283 }
2284}
2285
2286impl HirDisplay for LifetimeData {
2287 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2288 match self {
2289 LifetimeData::Placeholder(idx) => {
2290 let id = lt_from_placeholder_idx(f.db, *idx).0;
2291 let generics = generics(f.db, id.parent);
2292 let param_data = &generics[id.local_id];
2293 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
2294 Ok(())
2295 }
2296 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
2297 LifetimeData::InferenceVar(_) => write!(f, "_"),
2298 LifetimeData::Static => write!(f, "'static"),
2299 LifetimeData::Error => {
2300 if cfg!(test) {
2301 write!(f, "'?")
2302 } else {
2303 write!(f, "'_")
2304 }
2305 }
2306 LifetimeData::Erased => write!(f, "'<erased>"),
2307 LifetimeData::Phantom(void, _) => match *void {},
2308 }
2309 }
2310}
2311
2312impl<'db> HirDisplay for crate::next_solver::Region<'db> {
2313 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2314 match self.kind() {
2315 rustc_type_ir::RegionKind::ReEarlyParam(param) => {
2316 let generics = generics(f.db, param.id.parent);
2317 let param_data = &generics[param.id.local_id];
2318 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
2319 Ok(())
2320 }
2321 rustc_type_ir::RegionKind::ReBound(db, idx) => {
2322 write!(f, "?{}.{}", db.as_u32(), idx.var.as_u32())
2323 }
2324 rustc_type_ir::RegionKind::ReVar(_) => write!(f, "_"),
2325 rustc_type_ir::RegionKind::ReStatic => write!(f, "'static"),
2326 rustc_type_ir::RegionKind::ReError(..) => {
2327 if cfg!(test) {
2328 write!(f, "'?")
2329 } else {
2330 write!(f, "'_")
2331 }
2332 }
2333 rustc_type_ir::RegionKind::ReErased => write!(f, "'<erased>"),
2334 rustc_type_ir::RegionKind::RePlaceholder(_) => write!(f, "<placeholder>"),
2335 rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, "<late-param>"),
2336 }
2337 }
2338}
2339
2340impl HirDisplay for DomainGoal {
2341 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2342 match self {
2343 DomainGoal::Holds(wc) => {
2344 write!(f, "Holds(")?;
2345 wc.hir_fmt(f)?;
2346 write!(f, ")")?;
2347 }
2348 _ => write!(f, "_")?,
2349 }
2350 Ok(())
2351 }
2352}
2353
2354pub fn write_visibility(
2355 module_id: ModuleId,
2356 vis: Visibility,
2357 f: &mut HirFormatter<'_>,
2358) -> Result<(), HirDisplayError> {
2359 match vis {
2360 Visibility::Public => write!(f, "pub "),
2361 Visibility::PubCrate(_) => write!(f, "pub(crate) "),
2362 Visibility::Module(vis_id, _) => {
2363 let def_map = module_id.def_map(f.db);
2364 let root_module_id = def_map.module_id(DefMap::ROOT);
2365 if vis_id == module_id {
2366 Ok(())
2368 } else if root_module_id == vis_id {
2369 write!(f, "pub(crate) ")
2370 } else if module_id.containing_module(f.db) == Some(vis_id) {
2371 write!(f, "pub(super) ")
2372 } else {
2373 write!(f, "pub(in ...) ")
2374 }
2375 }
2376 }
2377}
2378
2379pub trait HirDisplayWithExpressionStore {
2380 fn hir_fmt(
2381 &self,
2382 f: &mut HirFormatter<'_>,
2383 store: &ExpressionStore,
2384 ) -> Result<(), HirDisplayError>;
2385}
2386
2387impl<T: ?Sized + HirDisplayWithExpressionStore> HirDisplayWithExpressionStore for &'_ T {
2388 fn hir_fmt(
2389 &self,
2390 f: &mut HirFormatter<'_>,
2391 store: &ExpressionStore,
2392 ) -> Result<(), HirDisplayError> {
2393 T::hir_fmt(&**self, f, store)
2394 }
2395}
2396
2397pub fn hir_display_with_store<'a, T: HirDisplayWithExpressionStore + 'a>(
2398 value: T,
2399 store: &'a ExpressionStore,
2400) -> impl HirDisplay + 'a {
2401 ExpressionStoreAdapter(value, store)
2402}
2403
2404struct ExpressionStoreAdapter<'a, T>(T, &'a ExpressionStore);
2405
2406impl<'a, T> ExpressionStoreAdapter<'a, T> {
2407 fn wrap(store: &'a ExpressionStore) -> impl Fn(T) -> ExpressionStoreAdapter<'a, T> {
2408 move |value| ExpressionStoreAdapter(value, store)
2409 }
2410}
2411
2412impl<T: HirDisplayWithExpressionStore> HirDisplay for ExpressionStoreAdapter<'_, T> {
2413 fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
2414 T::hir_fmt(&self.0, f, self.1)
2415 }
2416}
2417impl HirDisplayWithExpressionStore for LifetimeRefId {
2418 fn hir_fmt(
2419 &self,
2420 f: &mut HirFormatter<'_>,
2421 store: &ExpressionStore,
2422 ) -> Result<(), HirDisplayError> {
2423 match &store[*self] {
2424 LifetimeRef::Named(name) => write!(f, "{}", name.display(f.db, f.edition())),
2425 LifetimeRef::Static => write!(f, "'static"),
2426 LifetimeRef::Placeholder => write!(f, "'_"),
2427 LifetimeRef::Error => write!(f, "'{{error}}"),
2428 &LifetimeRef::Param(lifetime_param_id) => {
2429 let generic_params = f.db.generic_params(lifetime_param_id.parent);
2430 write!(
2431 f,
2432 "{}",
2433 generic_params[lifetime_param_id.local_id].name.display(f.db, f.edition())
2434 )
2435 }
2436 }
2437 }
2438}
2439
2440impl HirDisplayWithExpressionStore for TypeRefId {
2441 fn hir_fmt(
2442 &self,
2443 f: &mut HirFormatter<'_>,
2444 store: &ExpressionStore,
2445 ) -> Result<(), HirDisplayError> {
2446 match &store[*self] {
2447 TypeRef::Never => write!(f, "!")?,
2448 TypeRef::TypeParam(param) => {
2449 let generic_params = f.db.generic_params(param.parent());
2450 match generic_params[param.local_id()].name() {
2451 Some(name) => write!(f, "{}", name.display(f.db, f.edition()))?,
2452 None => {
2453 write!(f, "impl ")?;
2454 f.write_joined(
2455 generic_params
2456 .where_predicates()
2457 .iter()
2458 .filter_map(|it| match it {
2459 WherePredicate::TypeBound { target, bound }
2460 | WherePredicate::ForLifetime { lifetimes: _, target, bound }
2461 if matches!(
2462 store[*target],
2463 TypeRef::TypeParam(t) if t == *param
2464 ) =>
2465 {
2466 Some(bound)
2467 }
2468 _ => None,
2469 })
2470 .map(ExpressionStoreAdapter::wrap(store)),
2471 " + ",
2472 )?;
2473 }
2474 }
2475 }
2476 TypeRef::Placeholder => write!(f, "_")?,
2477 TypeRef::Tuple(elems) => {
2478 write!(f, "(")?;
2479 f.write_joined(elems.iter().map(ExpressionStoreAdapter::wrap(store)), ", ")?;
2480 if elems.len() == 1 {
2481 write!(f, ",")?;
2482 }
2483 write!(f, ")")?;
2484 }
2485 TypeRef::Path(path) => path.hir_fmt(f, store)?,
2486 TypeRef::RawPtr(inner, mutability) => {
2487 let mutability = match mutability {
2488 hir_def::type_ref::Mutability::Shared => "*const ",
2489 hir_def::type_ref::Mutability::Mut => "*mut ",
2490 };
2491 write!(f, "{mutability}")?;
2492 inner.hir_fmt(f, store)?;
2493 }
2494 TypeRef::Reference(ref_) => {
2495 let mutability = match ref_.mutability {
2496 hir_def::type_ref::Mutability::Shared => "",
2497 hir_def::type_ref::Mutability::Mut => "mut ",
2498 };
2499 write!(f, "&")?;
2500 if let Some(lifetime) = &ref_.lifetime {
2501 lifetime.hir_fmt(f, store)?;
2502 write!(f, " ")?;
2503 }
2504 write!(f, "{mutability}")?;
2505 ref_.ty.hir_fmt(f, store)?;
2506 }
2507 TypeRef::Array(array) => {
2508 write!(f, "[")?;
2509 array.ty.hir_fmt(f, store)?;
2510 write!(f, "; ")?;
2511 array.len.hir_fmt(f, store)?;
2512 write!(f, "]")?;
2513 }
2514 TypeRef::Slice(inner) => {
2515 write!(f, "[")?;
2516 inner.hir_fmt(f, store)?;
2517 write!(f, "]")?;
2518 }
2519 TypeRef::Fn(fn_) => {
2520 if fn_.is_unsafe {
2521 write!(f, "unsafe ")?;
2522 }
2523 if let Some(abi) = &fn_.abi {
2524 f.write_str("extern \"")?;
2525 f.write_str(abi.as_str())?;
2526 f.write_str("\" ")?;
2527 }
2528 write!(f, "fn(")?;
2529 if let Some(((_, return_type), function_parameters)) = fn_.params.split_last() {
2530 for index in 0..function_parameters.len() {
2531 let (param_name, param_type) = &function_parameters[index];
2532 if let Some(name) = param_name {
2533 write!(f, "{}: ", name.display(f.db, f.edition()))?;
2534 }
2535
2536 param_type.hir_fmt(f, store)?;
2537
2538 if index != function_parameters.len() - 1 {
2539 write!(f, ", ")?;
2540 }
2541 }
2542 if fn_.is_varargs {
2543 write!(f, "{}...", if fn_.params.len() == 1 { "" } else { ", " })?;
2544 }
2545 write!(f, ")")?;
2546 match &store[*return_type] {
2547 TypeRef::Tuple(tup) if tup.is_empty() => {}
2548 _ => {
2549 write!(f, " -> ")?;
2550 return_type.hir_fmt(f, store)?;
2551 }
2552 }
2553 }
2554 }
2555 TypeRef::ImplTrait(bounds) => {
2556 write!(f, "impl ")?;
2557 f.write_joined(bounds.iter().map(ExpressionStoreAdapter::wrap(store)), " + ")?;
2558 }
2559 TypeRef::DynTrait(bounds) => {
2560 write!(f, "dyn ")?;
2561 f.write_joined(bounds.iter().map(ExpressionStoreAdapter::wrap(store)), " + ")?;
2562 }
2563 TypeRef::Error => write!(f, "{{error}}")?,
2564 }
2565 Ok(())
2566 }
2567}
2568
2569impl HirDisplayWithExpressionStore for ConstRef {
2570 fn hir_fmt(
2571 &self,
2572 f: &mut HirFormatter<'_>,
2573 _store: &ExpressionStore,
2574 ) -> Result<(), HirDisplayError> {
2575 write!(f, "{{const}}")?;
2577
2578 Ok(())
2579 }
2580}
2581
2582impl HirDisplayWithExpressionStore for TypeBound {
2583 fn hir_fmt(
2584 &self,
2585 f: &mut HirFormatter<'_>,
2586 store: &ExpressionStore,
2587 ) -> Result<(), HirDisplayError> {
2588 match self {
2589 &TypeBound::Path(path, modifier) => {
2590 match modifier {
2591 TraitBoundModifier::None => (),
2592 TraitBoundModifier::Maybe => write!(f, "?")?,
2593 }
2594 store[path].hir_fmt(f, store)
2595 }
2596 TypeBound::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
2597 TypeBound::ForLifetime(lifetimes, path) => {
2598 let edition = f.edition();
2599 write!(
2600 f,
2601 "for<{}> ",
2602 lifetimes.iter().map(|it| it.display(f.db, edition)).format(", ")
2603 )?;
2604 store[*path].hir_fmt(f, store)
2605 }
2606 TypeBound::Use(args) => {
2607 write!(f, "use<")?;
2608 let edition = f.edition();
2609 let last = args.len().saturating_sub(1);
2610 for (idx, arg) in args.iter().enumerate() {
2611 match arg {
2612 UseArgRef::Lifetime(lt) => lt.hir_fmt(f, store)?,
2613 UseArgRef::Name(n) => write!(f, "{}", n.display(f.db, edition))?,
2614 }
2615 if idx != last {
2616 write!(f, ", ")?;
2617 }
2618 }
2619 write!(f, "> ")
2620 }
2621 TypeBound::Error => write!(f, "{{error}}"),
2622 }
2623 }
2624}
2625
2626impl HirDisplayWithExpressionStore for Path {
2627 fn hir_fmt(
2628 &self,
2629 f: &mut HirFormatter<'_>,
2630 store: &ExpressionStore,
2631 ) -> Result<(), HirDisplayError> {
2632 match (self.type_anchor(), self.kind()) {
2633 (Some(anchor), _) => {
2634 write!(f, "<")?;
2635 anchor.hir_fmt(f, store)?;
2636 write!(f, ">")?;
2637 }
2638 (_, PathKind::Plain) => {}
2639 (_, PathKind::Abs) => {}
2640 (_, PathKind::Crate) => write!(f, "crate")?,
2641 (_, &PathKind::SELF) => write!(f, "self")?,
2642 (_, PathKind::Super(n)) => {
2643 for i in 0..*n {
2644 if i > 0 {
2645 write!(f, "::")?;
2646 }
2647 write!(f, "super")?;
2648 }
2649 }
2650 (_, PathKind::DollarCrate(id)) => {
2651 let crate_data = id.extra_data(f.db);
2655 let name = crate_data
2656 .display_name
2657 .as_ref()
2658 .map(|name| (*name.canonical_name()).clone())
2659 .unwrap_or(sym::dollar_crate);
2660 write!(f, "{name}")?
2661 }
2662 }
2663
2664 let trait_self_ty = self.segments().iter().find_map(|seg| {
2673 let generic_args = seg.args_and_bindings?;
2674 generic_args.has_self_type.then(|| &generic_args.args[0])
2675 });
2676 if let Some(ty) = trait_self_ty {
2677 write!(f, "<")?;
2678 ty.hir_fmt(f, store)?;
2679 write!(f, " as ")?;
2680 }
2682
2683 for (seg_idx, segment) in self.segments().iter().enumerate() {
2684 if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
2685 write!(f, "::")?;
2686 }
2687 write!(f, "{}", segment.name.display(f.db, f.edition()))?;
2688 if let Some(generic_args) = segment.args_and_bindings {
2689 match generic_args.parenthesized {
2692 hir_def::expr_store::path::GenericArgsParentheses::ReturnTypeNotation => {
2693 write!(f, "(..)")?;
2694 }
2695 hir_def::expr_store::path::GenericArgsParentheses::ParenSugar => {
2696 let tuple = match generic_args.args[0] {
2699 hir_def::expr_store::path::GenericArg::Type(ty) => match &store[ty] {
2700 TypeRef::Tuple(it) => Some(it),
2701 _ => None,
2702 },
2703 _ => None,
2704 };
2705 if let Some(v) = tuple {
2706 if v.len() == 1 {
2707 write!(f, "(")?;
2708 v[0].hir_fmt(f, store)?;
2709 write!(f, ")")?;
2710 } else {
2711 generic_args.args[0].hir_fmt(f, store)?;
2712 }
2713 }
2714 if let Some(ret) = generic_args.bindings[0].type_ref
2715 && !matches!(&store[ret], TypeRef::Tuple(v) if v.is_empty())
2716 {
2717 write!(f, " -> ")?;
2718 ret.hir_fmt(f, store)?;
2719 }
2720 }
2721 hir_def::expr_store::path::GenericArgsParentheses::No => {
2722 let mut first = true;
2723 for arg in &generic_args.args[generic_args.has_self_type as usize..] {
2725 if first {
2726 first = false;
2727 write!(f, "<")?;
2728 } else {
2729 write!(f, ", ")?;
2730 }
2731 arg.hir_fmt(f, store)?;
2732 }
2733 for binding in generic_args.bindings.iter() {
2734 if first {
2735 first = false;
2736 write!(f, "<")?;
2737 } else {
2738 write!(f, ", ")?;
2739 }
2740 write!(f, "{}", binding.name.display(f.db, f.edition()))?;
2741 match &binding.type_ref {
2742 Some(ty) => {
2743 write!(f, " = ")?;
2744 ty.hir_fmt(f, store)?
2745 }
2746 None => {
2747 write!(f, ": ")?;
2748 f.write_joined(
2749 binding
2750 .bounds
2751 .iter()
2752 .map(ExpressionStoreAdapter::wrap(store)),
2753 " + ",
2754 )?;
2755 }
2756 }
2757 }
2758
2759 if !first {
2762 write!(f, ">")?;
2763 }
2764
2765 if generic_args.has_self_type {
2767 write!(f, ">")?;
2768 }
2769 }
2770 }
2771 }
2772 }
2773
2774 Ok(())
2775 }
2776}
2777
2778impl HirDisplayWithExpressionStore for hir_def::expr_store::path::GenericArg {
2779 fn hir_fmt(
2780 &self,
2781 f: &mut HirFormatter<'_>,
2782 store: &ExpressionStore,
2783 ) -> Result<(), HirDisplayError> {
2784 match self {
2785 hir_def::expr_store::path::GenericArg::Type(ty) => ty.hir_fmt(f, store),
2786 hir_def::expr_store::path::GenericArg::Const(_c) => {
2787 write!(f, "<expr>")
2789 }
2790 hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
2791 }
2792 }
2793}