aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/display.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/display.rs')
-rw-r--r--crates/hir_ty/src/display.rs401
1 files changed, 303 insertions, 98 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index ab51cb0a6..c572bb114 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -5,15 +5,22 @@ use std::{borrow::Cow, fmt};
5use arrayvec::ArrayVec; 5use arrayvec::ArrayVec;
6use chalk_ir::Mutability; 6use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, 8 db::DefDatabase,
9 find_path,
10 generics::TypeParamProvenance,
11 item_scope::ItemInNs,
12 path::{GenericArg, Path, PathKind},
13 type_ref::{TypeBound, TypeRef},
14 visibility::Visibility,
9 AssocContainerId, Lookup, ModuleId, TraitId, 15 AssocContainerId, Lookup, ModuleId, TraitId,
10}; 16};
11use hir_expand::name::Name; 17use hir_expand::name::Name;
12 18
13use crate::{ 19use crate::{
14 db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, 20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
15 GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, 21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId,
16 TraitRef, Ty, 22 CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
23 ProjectionTy, Scalar, Substs, TraitRef, Ty, TyKind,
17}; 24};
18 25
19pub struct HirFormatter<'a> { 26pub struct HirFormatter<'a> {
@@ -231,7 +238,7 @@ where
231 238
232const TYPE_HINT_TRUNCATION: &str = "…"; 239const TYPE_HINT_TRUNCATION: &str = "…";
233 240
234impl HirDisplay for &Ty { 241impl<T: HirDisplay> HirDisplay for &'_ T {
235 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 242 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
236 HirDisplay::hir_fmt(*self, f) 243 HirDisplay::hir_fmt(*self, f)
237 } 244 }
@@ -244,19 +251,19 @@ impl HirDisplay for ProjectionTy {
244 } 251 }
245 252
246 let trait_ = f.db.trait_data(self.trait_(f.db)); 253 let trait_ = f.db.trait_data(self.trait_(f.db));
247 let first_parameter = self.parameters[0].into_displayable( 254 let first_parameter = self.substitution[0].into_displayable(
248 f.db, 255 f.db,
249 f.max_size, 256 f.max_size,
250 f.omit_verbose_types, 257 f.omit_verbose_types,
251 f.display_target, 258 f.display_target,
252 ); 259 );
253 write!(f, "<{} as {}", first_parameter, trait_.name)?; 260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
254 if self.parameters.len() > 1 { 261 if self.substitution.len() > 1 {
255 write!(f, "<")?; 262 write!(f, "<")?;
256 f.write_joined(&self.parameters[1..], ", ")?; 263 f.write_joined(&self.substitution[1..], ", ")?;
257 write!(f, ">")?; 264 write!(f, ">")?;
258 } 265 }
259 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; 266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
260 Ok(()) 267 Ok(())
261 } 268 }
262} 269}
@@ -267,32 +274,29 @@ impl HirDisplay for Ty {
267 return write!(f, "{}", TYPE_HINT_TRUNCATION); 274 return write!(f, "{}", TYPE_HINT_TRUNCATION);
268 } 275 }
269 276
270 match self { 277 match self.interned(&Interner) {
271 Ty::Never => write!(f, "!")?, 278 TyKind::Never => write!(f, "!")?,
272 Ty::Str => write!(f, "str")?, 279 TyKind::Str => write!(f, "str")?,
273 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, 280 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
274 Ty::Scalar(Scalar::Char) => write!(f, "char")?, 281 TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
275 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, 282 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
276 &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, 283 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
277 &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, 284 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
278 Ty::Slice(parameters) => { 285 TyKind::Slice(t) => {
279 let t = parameters.as_single();
280 write!(f, "[")?; 286 write!(f, "[")?;
281 t.hir_fmt(f)?; 287 t.hir_fmt(f)?;
282 write!(f, "]")?; 288 write!(f, "]")?;
283 } 289 }
284 Ty::Array(parameters) => { 290 TyKind::Array(t) => {
285 let t = parameters.as_single();
286 write!(f, "[")?; 291 write!(f, "[")?;
287 t.hir_fmt(f)?; 292 t.hir_fmt(f)?;
288 write!(f, "; _]")?; 293 write!(f, "; _]")?;
289 } 294 }
290 Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { 295 TyKind::Raw(m, t) | TyKind::Ref(m, t) => {
291 let t = parameters.as_single();
292 let ty_display = 296 let ty_display =
293 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 297 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
294 298
295 if matches!(self, Ty::Raw(..)) { 299 if matches!(self.interned(&Interner), TyKind::Raw(..)) {
296 write!( 300 write!(
297 f, 301 f,
298 "*{}", 302 "*{}",
@@ -312,22 +316,29 @@ impl HirDisplay for Ty {
312 )?; 316 )?;
313 } 317 }
314 318
319 // FIXME: all this just to decide whether to use parentheses...
315 let datas; 320 let datas;
316 let predicates = match t { 321 let predicates = match t.interned(&Interner) {
317 Ty::Dyn(predicates) if predicates.len() > 1 => { 322 TyKind::Dyn(predicates) if predicates.len() > 1 => {
318 Cow::Borrowed(predicates.as_ref()) 323 Cow::Borrowed(predicates.as_ref())
319 } 324 }
320 &Ty::Alias(AliasTy::Opaque(OpaqueTy { 325 &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
321 opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), 326 opaque_ty_id,
322 ref parameters, 327 substitution: ref parameters,
323 })) => { 328 })) => {
324 datas = 329 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into());
325 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 330 if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
326 let data = (*datas) 331 datas =
327 .as_ref() 332 f.db.return_type_impl_traits(func)
328 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 333 .expect("impl trait id without data");
329 let bounds = data.subst(parameters); 334 let data = (*datas)
330 Cow::Owned(bounds.value) 335 .as_ref()
336 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
337 let bounds = data.subst(parameters);
338 Cow::Owned(bounds.value)
339 } else {
340 Cow::Borrowed(&[][..])
341 }
331 } 342 }
332 _ => Cow::Borrowed(&[][..]), 343 _ => Cow::Borrowed(&[][..]),
333 }; 344 };
@@ -347,7 +358,7 @@ impl HirDisplay for Ty {
347 write!(f, "{}", ty_display)?; 358 write!(f, "{}", ty_display)?;
348 } 359 }
349 } 360 }
350 Ty::Tuple(_, substs) => { 361 TyKind::Tuple(_, substs) => {
351 if substs.len() == 1 { 362 if substs.len() == 1 {
352 write!(f, "(")?; 363 write!(f, "(")?;
353 substs[0].hir_fmt(f)?; 364 substs[0].hir_fmt(f)?;
@@ -358,12 +369,12 @@ impl HirDisplay for Ty {
358 write!(f, ")")?; 369 write!(f, ")")?;
359 } 370 }
360 } 371 }
361 Ty::Function(fn_ptr) => { 372 TyKind::Function(fn_ptr) => {
362 let sig = CallableSig::from_fn_ptr(fn_ptr); 373 let sig = CallableSig::from_fn_ptr(fn_ptr);
363 sig.hir_fmt(f)?; 374 sig.hir_fmt(f)?;
364 } 375 }
365 Ty::FnDef(def, parameters) => { 376 TyKind::FnDef(def, parameters) => {
366 let def = *def; 377 let def = from_chalk(f.db, *def);
367 let sig = f.db.callable_item_signature(def).subst(parameters); 378 let sig = f.db.callable_item_signature(def).subst(parameters);
368 match def { 379 match def {
369 CallableDefId::FunctionId(ff) => { 380 CallableDefId::FunctionId(ff) => {
@@ -401,7 +412,7 @@ impl HirDisplay for Ty {
401 write!(f, " -> {}", ret_display)?; 412 write!(f, " -> {}", ret_display)?;
402 } 413 }
403 } 414 }
404 Ty::Adt(AdtId(def_id), parameters) => { 415 TyKind::Adt(AdtId(def_id), parameters) => {
405 match f.display_target { 416 match f.display_target {
406 DisplayTarget::Diagnostics | DisplayTarget::Test => { 417 DisplayTarget::Diagnostics | DisplayTarget::Test => {
407 let name = match *def_id { 418 let name = match *def_id {
@@ -427,37 +438,39 @@ impl HirDisplay for Ty {
427 } 438 }
428 439
429 if parameters.len() > 0 { 440 if parameters.len() > 0 {
430 let parameters_to_write = 441 let parameters_to_write = if f.display_target.is_source_code()
431 if f.display_target.is_source_code() || f.omit_verbose_types() { 442 || f.omit_verbose_types()
432 match self 443 {
433 .as_generic_def() 444 match self
434 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 445 .as_generic_def(f.db)
435 .filter(|defaults| !defaults.is_empty()) 446 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
436 { 447 .filter(|defaults| !defaults.is_empty())
437 None => parameters.0.as_ref(), 448 {
438 Some(default_parameters) => { 449 None => parameters.0.as_ref(),
439 let mut default_from = 0; 450 Some(default_parameters) => {
440 for (i, parameter) in parameters.iter().enumerate() { 451 let mut default_from = 0;
441 match (parameter, default_parameters.get(i)) { 452 for (i, parameter) in parameters.iter().enumerate() {
442 (&Ty::Unknown, _) | (_, None) => { 453 match (parameter.interned(&Interner), default_parameters.get(i))
454 {
455 (&TyKind::Unknown, _) | (_, None) => {
456 default_from = i + 1;
457 }
458 (_, Some(default_parameter)) => {
459 let actual_default = default_parameter
460 .clone()
461 .subst(&parameters.prefix(i));
462 if parameter != &actual_default {
443 default_from = i + 1; 463 default_from = i + 1;
444 } 464 }
445 (_, Some(default_parameter)) => {
446 let actual_default = default_parameter
447 .clone()
448 .subst(&parameters.prefix(i));
449 if parameter != &actual_default {
450 default_from = i + 1;
451 }
452 }
453 } 465 }
454 } 466 }
455 &parameters.0[0..default_from]
456 } 467 }
468 &parameters.0[0..default_from]
457 } 469 }
458 } else { 470 }
459 parameters.0.as_ref() 471 } else {
460 }; 472 parameters.0.as_ref()
473 };
461 if !parameters_to_write.is_empty() { 474 if !parameters_to_write.is_empty() {
462 write!(f, "<")?; 475 write!(f, "<")?;
463 f.write_joined(parameters_to_write, ", ")?; 476 f.write_joined(parameters_to_write, ", ")?;
@@ -465,13 +478,14 @@ impl HirDisplay for Ty {
465 } 478 }
466 } 479 }
467 } 480 }
468 Ty::AssociatedType(type_alias, parameters) => { 481 TyKind::AssociatedType(assoc_type_id, parameters) => {
482 let type_alias = from_assoc_type_id(*assoc_type_id);
469 let trait_ = match type_alias.lookup(f.db.upcast()).container { 483 let trait_ = match type_alias.lookup(f.db.upcast()).container {
470 AssocContainerId::TraitId(it) => it, 484 AssocContainerId::TraitId(it) => it,
471 _ => panic!("not an associated type"), 485 _ => panic!("not an associated type"),
472 }; 486 };
473 let trait_ = f.db.trait_data(trait_); 487 let trait_ = f.db.trait_data(trait_);
474 let type_alias_data = f.db.type_alias_data(*type_alias); 488 let type_alias_data = f.db.type_alias_data(type_alias);
475 489
476 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 490 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
477 if f.display_target.is_test() { 491 if f.display_target.is_test() {
@@ -482,19 +496,22 @@ impl HirDisplay for Ty {
482 write!(f, ">")?; 496 write!(f, ">")?;
483 } 497 }
484 } else { 498 } else {
485 let projection_ty = 499 let projection_ty = ProjectionTy {
486 ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; 500 associated_ty_id: to_assoc_type_id(type_alias),
501 substitution: parameters.clone(),
502 };
487 503
488 projection_ty.hir_fmt(f)?; 504 projection_ty.hir_fmt(f)?;
489 } 505 }
490 } 506 }
491 Ty::ForeignType(type_alias) => { 507 TyKind::ForeignType(type_alias) => {
492 let type_alias = f.db.type_alias_data(*type_alias); 508 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
493 write!(f, "{}", type_alias.name)?; 509 write!(f, "{}", type_alias.name)?;
494 } 510 }
495 Ty::OpaqueType(opaque_ty_id, parameters) => { 511 TyKind::OpaqueType(opaque_ty_id, parameters) => {
496 match opaque_ty_id { 512 let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
497 &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 513 match impl_trait_id {
514 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
498 let datas = 515 let datas =
499 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 516 f.db.return_type_impl_traits(func).expect("impl trait id without data");
500 let data = (*datas) 517 let data = (*datas)
@@ -504,14 +521,14 @@ impl HirDisplay for Ty {
504 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 521 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
505 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 522 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
506 } 523 }
507 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 524 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
508 write!(f, "impl Future<Output = ")?; 525 write!(f, "impl Future<Output = ")?;
509 parameters[0].hir_fmt(f)?; 526 parameters[0].hir_fmt(f)?;
510 write!(f, ">")?; 527 write!(f, ">")?;
511 } 528 }
512 } 529 }
513 } 530 }
514 Ty::Closure(.., substs) => { 531 TyKind::Closure(.., substs) => {
515 let sig = substs[0].callable_sig(f.db); 532 let sig = substs[0].callable_sig(f.db);
516 if let Some(sig) = sig { 533 if let Some(sig) = sig {
517 if sig.params().is_empty() { 534 if sig.params().is_empty() {
@@ -535,7 +552,8 @@ impl HirDisplay for Ty {
535 write!(f, "{{closure}}")?; 552 write!(f, "{{closure}}")?;
536 } 553 }
537 } 554 }
538 Ty::Placeholder(id) => { 555 TyKind::Placeholder(idx) => {
556 let id = from_placeholder_idx(f.db, *idx);
539 let generics = generics(f.db.upcast(), id.parent); 557 let generics = generics(f.db.upcast(), id.parent);
540 let param_data = &generics.params.types[id.local_id]; 558 let param_data = &generics.params.types[id.local_id];
541 match param_data.provenance { 559 match param_data.provenance {
@@ -543,8 +561,8 @@ impl HirDisplay for Ty {
543 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 561 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
544 } 562 }
545 TypeParamProvenance::ArgumentImplTrait => { 563 TypeParamProvenance::ArgumentImplTrait => {
546 let bounds = f.db.generic_predicates_for_param(*id); 564 let bounds = f.db.generic_predicates_for_param(id);
547 let substs = Substs::type_params_for_generics(&generics); 565 let substs = Substs::type_params_for_generics(f.db, &generics);
548 write_bounds_like_dyn_trait_with_prefix( 566 write_bounds_like_dyn_trait_with_prefix(
549 "impl", 567 "impl",
550 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), 568 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
@@ -553,28 +571,29 @@ impl HirDisplay for Ty {
553 } 571 }
554 } 572 }
555 } 573 }
556 Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 574 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
557 Ty::Dyn(predicates) => { 575 TyKind::Dyn(predicates) => {
558 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; 576 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
559 } 577 }
560 Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, 578 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
561 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 579 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
562 match opaque_ty.opaque_ty_id { 580 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
563 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 581 match impl_trait_id {
582 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
564 let datas = 583 let datas =
565 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 584 f.db.return_type_impl_traits(func).expect("impl trait id without data");
566 let data = (*datas) 585 let data = (*datas)
567 .as_ref() 586 .as_ref()
568 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 587 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
569 let bounds = data.subst(&opaque_ty.parameters); 588 let bounds = data.subst(&opaque_ty.substitution);
570 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 589 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
571 } 590 }
572 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 591 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
573 write!(f, "{{async block}}")?; 592 write!(f, "{{async block}}")?;
574 } 593 }
575 }; 594 };
576 } 595 }
577 Ty::Unknown => { 596 TyKind::Unknown => {
578 if f.display_target.is_source_code() { 597 if f.display_target.is_source_code() {
579 return Err(HirDisplayError::DisplaySourceCodeError( 598 return Err(HirDisplayError::DisplaySourceCodeError(
580 DisplaySourceCodeError::UnknownType, 599 DisplaySourceCodeError::UnknownType,
@@ -582,7 +601,7 @@ impl HirDisplay for Ty {
582 } 601 }
583 write!(f, "{{unknown}}")?; 602 write!(f, "{{unknown}}")?;
584 } 603 }
585 Ty::InferenceVar(..) => write!(f, "_")?, 604 TyKind::InferenceVar(..) => write!(f, "_")?,
586 } 605 }
587 Ok(()) 606 Ok(())
588 } 607 }
@@ -695,7 +714,9 @@ fn write_bounds_like_dyn_trait(
695 write!(f, "<")?; 714 write!(f, "<")?;
696 angle_open = true; 715 angle_open = true;
697 } 716 }
698 let type_alias = f.db.type_alias_data(projection_pred.projection_ty.associated_ty); 717 let type_alias = f.db.type_alias_data(from_assoc_type_id(
718 projection_pred.projection_ty.associated_ty_id,
719 ));
699 write!(f, "{} = ", type_alias.name)?; 720 write!(f, "{} = ", type_alias.name)?;
700 projection_pred.ty.hir_fmt(f)?; 721 projection_pred.ty.hir_fmt(f)?;
701 } 722 }
@@ -746,12 +767,6 @@ impl HirDisplay for TraitRef {
746 } 767 }
747} 768}
748 769
749impl HirDisplay for &GenericPredicate {
750 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
751 HirDisplay::hir_fmt(*self, f)
752 }
753}
754
755impl HirDisplay for GenericPredicate { 770impl HirDisplay for GenericPredicate {
756 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 771 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
757 if f.should_truncate() { 772 if f.should_truncate() {
@@ -766,7 +781,10 @@ impl HirDisplay for GenericPredicate {
766 write!( 781 write!(
767 f, 782 f,
768 ">::{} = ", 783 ">::{} = ",
769 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, 784 f.db.type_alias_data(from_assoc_type_id(
785 projection_pred.projection_ty.associated_ty_id
786 ))
787 .name,
770 )?; 788 )?;
771 projection_pred.ty.hir_fmt(f)?; 789 projection_pred.ty.hir_fmt(f)?;
772 } 790 }
@@ -807,3 +825,190 @@ impl HirDisplay for Obligation {
807 } 825 }
808 } 826 }
809} 827}
828
829pub fn write_visibility(
830 module_id: ModuleId,
831 vis: Visibility,
832 f: &mut HirFormatter,
833) -> Result<(), HirDisplayError> {
834 match vis {
835 Visibility::Public => write!(f, "pub "),
836 Visibility::Module(vis_id) => {
837 let def_map = module_id.def_map(f.db.upcast());
838 let root_module_id = def_map.module_id(def_map.root());
839 if vis_id == module_id {
840 // pub(self) or omitted
841 Ok(())
842 } else if root_module_id == vis_id {
843 write!(f, "pub(crate) ")
844 } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) {
845 write!(f, "pub(super) ")
846 } else {
847 write!(f, "pub(in ...) ")
848 }
849 }
850 }
851}
852
853impl HirDisplay for TypeRef {
854 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
855 match self {
856 TypeRef::Never => write!(f, "!")?,
857 TypeRef::Placeholder => write!(f, "_")?,
858 TypeRef::Tuple(elems) => {
859 write!(f, "(")?;
860 f.write_joined(elems, ", ")?;
861 if elems.len() == 1 {
862 write!(f, ",")?;
863 }
864 write!(f, ")")?;
865 }
866 TypeRef::Path(path) => path.hir_fmt(f)?,
867 TypeRef::RawPtr(inner, mutability) => {
868 let mutability = match mutability {
869 hir_def::type_ref::Mutability::Shared => "*const ",
870 hir_def::type_ref::Mutability::Mut => "*mut ",
871 };
872 write!(f, "{}", mutability)?;
873 inner.hir_fmt(f)?;
874 }
875 TypeRef::Reference(inner, lifetime, mutability) => {
876 let mutability = match mutability {
877 hir_def::type_ref::Mutability::Shared => "",
878 hir_def::type_ref::Mutability::Mut => "mut ",
879 };
880 write!(f, "&")?;
881 if let Some(lifetime) = lifetime {
882 write!(f, "{} ", lifetime.name)?;
883 }
884 write!(f, "{}", mutability)?;
885 inner.hir_fmt(f)?;
886 }
887 TypeRef::Array(inner) => {
888 write!(f, "[")?;
889 inner.hir_fmt(f)?;
890 // FIXME: Array length?
891 write!(f, "; _]")?;
892 }
893 TypeRef::Slice(inner) => {
894 write!(f, "[")?;
895 inner.hir_fmt(f)?;
896 write!(f, "]")?;
897 }
898 TypeRef::Fn(tys, is_varargs) => {
899 // FIXME: Function pointer qualifiers.
900 write!(f, "fn(")?;
901 f.write_joined(&tys[..tys.len() - 1], ", ")?;
902 if *is_varargs {
903 write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?;
904 }
905 write!(f, ")")?;
906 let ret_ty = tys.last().unwrap();
907 match ret_ty {
908 TypeRef::Tuple(tup) if tup.is_empty() => {}
909 _ => {
910 write!(f, " -> ")?;
911 ret_ty.hir_fmt(f)?;
912 }
913 }
914 }
915 TypeRef::ImplTrait(bounds) => {
916 write!(f, "impl ")?;
917 f.write_joined(bounds, " + ")?;
918 }
919 TypeRef::DynTrait(bounds) => {
920 write!(f, "dyn ")?;
921 f.write_joined(bounds, " + ")?;
922 }
923 TypeRef::Error => write!(f, "{{error}}")?,
924 }
925 Ok(())
926 }
927}
928
929impl HirDisplay for TypeBound {
930 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
931 match self {
932 TypeBound::Path(path) => path.hir_fmt(f),
933 TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
934 TypeBound::Error => write!(f, "{{error}}"),
935 }
936 }
937}
938
939impl HirDisplay for Path {
940 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
941 match (self.type_anchor(), self.kind()) {
942 (Some(anchor), _) => {
943 write!(f, "<")?;
944 anchor.hir_fmt(f)?;
945 write!(f, ">")?;
946 }
947 (_, PathKind::Plain) => {}
948 (_, PathKind::Abs) => write!(f, "::")?,
949 (_, PathKind::Crate) => write!(f, "crate")?,
950 (_, PathKind::Super(0)) => write!(f, "self")?,
951 (_, PathKind::Super(n)) => {
952 write!(f, "super")?;
953 for _ in 0..*n {
954 write!(f, "::super")?;
955 }
956 }
957 (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?,
958 }
959
960 for (seg_idx, segment) in self.segments().iter().enumerate() {
961 if seg_idx != 0 {
962 write!(f, "::")?;
963 }
964 write!(f, "{}", segment.name)?;
965 if let Some(generic_args) = segment.args_and_bindings {
966 // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`.
967 // Do we actually format expressions?
968 write!(f, "<")?;
969 let mut first = true;
970 for arg in &generic_args.args {
971 if first {
972 first = false;
973 if generic_args.has_self_type {
974 // FIXME: Convert to `<Ty as Trait>` form.
975 write!(f, "Self = ")?;
976 }
977 } else {
978 write!(f, ", ")?;
979 }
980 arg.hir_fmt(f)?;
981 }
982 for binding in &generic_args.bindings {
983 if first {
984 first = false;
985 } else {
986 write!(f, ", ")?;
987 }
988 write!(f, "{}", binding.name)?;
989 match &binding.type_ref {
990 Some(ty) => {
991 write!(f, " = ")?;
992 ty.hir_fmt(f)?
993 }
994 None => {
995 write!(f, ": ")?;
996 f.write_joined(&binding.bounds, " + ")?;
997 }
998 }
999 }
1000 write!(f, ">")?;
1001 }
1002 }
1003 Ok(())
1004 }
1005}
1006
1007impl HirDisplay for GenericArg {
1008 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1009 match self {
1010 GenericArg::Type(ty) => ty.hir_fmt(f),
1011 GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1012 }
1013 }
1014}