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.rs195
1 files changed, 108 insertions, 87 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index ab51cb0a6..378c951c5 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -11,9 +11,10 @@ use hir_def::{
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{ 13use crate::{
14 db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, 14 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
15 GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, 15 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId,
16 TraitRef, Ty, 16 CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
17 ProjectionTy, Scalar, Substs, TraitRef, Ty, TyKind,
17}; 18};
18 19
19pub struct HirFormatter<'a> { 20pub struct HirFormatter<'a> {
@@ -244,19 +245,19 @@ impl HirDisplay for ProjectionTy {
244 } 245 }
245 246
246 let trait_ = f.db.trait_data(self.trait_(f.db)); 247 let trait_ = f.db.trait_data(self.trait_(f.db));
247 let first_parameter = self.parameters[0].into_displayable( 248 let first_parameter = self.substitution[0].into_displayable(
248 f.db, 249 f.db,
249 f.max_size, 250 f.max_size,
250 f.omit_verbose_types, 251 f.omit_verbose_types,
251 f.display_target, 252 f.display_target,
252 ); 253 );
253 write!(f, "<{} as {}", first_parameter, trait_.name)?; 254 write!(f, "<{} as {}", first_parameter, trait_.name)?;
254 if self.parameters.len() > 1 { 255 if self.substitution.len() > 1 {
255 write!(f, "<")?; 256 write!(f, "<")?;
256 f.write_joined(&self.parameters[1..], ", ")?; 257 f.write_joined(&self.substitution[1..], ", ")?;
257 write!(f, ">")?; 258 write!(f, ">")?;
258 } 259 }
259 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; 260 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
260 Ok(()) 261 Ok(())
261 } 262 }
262} 263}
@@ -267,32 +268,32 @@ impl HirDisplay for Ty {
267 return write!(f, "{}", TYPE_HINT_TRUNCATION); 268 return write!(f, "{}", TYPE_HINT_TRUNCATION);
268 } 269 }
269 270
270 match self { 271 match self.interned(&Interner) {
271 Ty::Never => write!(f, "!")?, 272 TyKind::Never => write!(f, "!")?,
272 Ty::Str => write!(f, "str")?, 273 TyKind::Str => write!(f, "str")?,
273 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, 274 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
274 Ty::Scalar(Scalar::Char) => write!(f, "char")?, 275 TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
275 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, 276 &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))?, 277 &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))?, 278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
278 Ty::Slice(parameters) => { 279 TyKind::Slice(parameters) => {
279 let t = parameters.as_single(); 280 let t = parameters.as_single();
280 write!(f, "[")?; 281 write!(f, "[")?;
281 t.hir_fmt(f)?; 282 t.hir_fmt(f)?;
282 write!(f, "]")?; 283 write!(f, "]")?;
283 } 284 }
284 Ty::Array(parameters) => { 285 TyKind::Array(parameters) => {
285 let t = parameters.as_single(); 286 let t = parameters.as_single();
286 write!(f, "[")?; 287 write!(f, "[")?;
287 t.hir_fmt(f)?; 288 t.hir_fmt(f)?;
288 write!(f, "; _]")?; 289 write!(f, "; _]")?;
289 } 290 }
290 Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { 291 TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => {
291 let t = parameters.as_single(); 292 let t = parameters.as_single();
292 let ty_display = 293 let ty_display =
293 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 294 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
294 295
295 if matches!(self, Ty::Raw(..)) { 296 if matches!(self.interned(&Interner), TyKind::Raw(..)) {
296 write!( 297 write!(
297 f, 298 f,
298 "*{}", 299 "*{}",
@@ -312,22 +313,29 @@ impl HirDisplay for Ty {
312 )?; 313 )?;
313 } 314 }
314 315
316 // FIXME: all this just to decide whether to use parentheses...
315 let datas; 317 let datas;
316 let predicates = match t { 318 let predicates = match t.interned(&Interner) {
317 Ty::Dyn(predicates) if predicates.len() > 1 => { 319 TyKind::Dyn(predicates) if predicates.len() > 1 => {
318 Cow::Borrowed(predicates.as_ref()) 320 Cow::Borrowed(predicates.as_ref())
319 } 321 }
320 &Ty::Alias(AliasTy::Opaque(OpaqueTy { 322 &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
321 opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), 323 opaque_ty_id,
322 ref parameters, 324 substitution: ref parameters,
323 })) => { 325 })) => {
324 datas = 326 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"); 327 if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
326 let data = (*datas) 328 datas =
327 .as_ref() 329 f.db.return_type_impl_traits(func)
328 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 330 .expect("impl trait id without data");
329 let bounds = data.subst(parameters); 331 let data = (*datas)
330 Cow::Owned(bounds.value) 332 .as_ref()
333 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
334 let bounds = data.subst(parameters);
335 Cow::Owned(bounds.value)
336 } else {
337 Cow::Borrowed(&[][..])
338 }
331 } 339 }
332 _ => Cow::Borrowed(&[][..]), 340 _ => Cow::Borrowed(&[][..]),
333 }; 341 };
@@ -347,7 +355,7 @@ impl HirDisplay for Ty {
347 write!(f, "{}", ty_display)?; 355 write!(f, "{}", ty_display)?;
348 } 356 }
349 } 357 }
350 Ty::Tuple(_, substs) => { 358 TyKind::Tuple(_, substs) => {
351 if substs.len() == 1 { 359 if substs.len() == 1 {
352 write!(f, "(")?; 360 write!(f, "(")?;
353 substs[0].hir_fmt(f)?; 361 substs[0].hir_fmt(f)?;
@@ -358,12 +366,12 @@ impl HirDisplay for Ty {
358 write!(f, ")")?; 366 write!(f, ")")?;
359 } 367 }
360 } 368 }
361 Ty::Function(fn_ptr) => { 369 TyKind::Function(fn_ptr) => {
362 let sig = CallableSig::from_fn_ptr(fn_ptr); 370 let sig = CallableSig::from_fn_ptr(fn_ptr);
363 sig.hir_fmt(f)?; 371 sig.hir_fmt(f)?;
364 } 372 }
365 Ty::FnDef(def, parameters) => { 373 TyKind::FnDef(def, parameters) => {
366 let def = *def; 374 let def = from_chalk(f.db, *def);
367 let sig = f.db.callable_item_signature(def).subst(parameters); 375 let sig = f.db.callable_item_signature(def).subst(parameters);
368 match def { 376 match def {
369 CallableDefId::FunctionId(ff) => { 377 CallableDefId::FunctionId(ff) => {
@@ -401,7 +409,7 @@ impl HirDisplay for Ty {
401 write!(f, " -> {}", ret_display)?; 409 write!(f, " -> {}", ret_display)?;
402 } 410 }
403 } 411 }
404 Ty::Adt(AdtId(def_id), parameters) => { 412 TyKind::Adt(AdtId(def_id), parameters) => {
405 match f.display_target { 413 match f.display_target {
406 DisplayTarget::Diagnostics | DisplayTarget::Test => { 414 DisplayTarget::Diagnostics | DisplayTarget::Test => {
407 let name = match *def_id { 415 let name = match *def_id {
@@ -427,37 +435,39 @@ impl HirDisplay for Ty {
427 } 435 }
428 436
429 if parameters.len() > 0 { 437 if parameters.len() > 0 {
430 let parameters_to_write = 438 let parameters_to_write = if f.display_target.is_source_code()
431 if f.display_target.is_source_code() || f.omit_verbose_types() { 439 || f.omit_verbose_types()
432 match self 440 {
433 .as_generic_def() 441 match self
434 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 442 .as_generic_def(f.db)
435 .filter(|defaults| !defaults.is_empty()) 443 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
436 { 444 .filter(|defaults| !defaults.is_empty())
437 None => parameters.0.as_ref(), 445 {
438 Some(default_parameters) => { 446 None => parameters.0.as_ref(),
439 let mut default_from = 0; 447 Some(default_parameters) => {
440 for (i, parameter) in parameters.iter().enumerate() { 448 let mut default_from = 0;
441 match (parameter, default_parameters.get(i)) { 449 for (i, parameter) in parameters.iter().enumerate() {
442 (&Ty::Unknown, _) | (_, None) => { 450 match (parameter.interned(&Interner), default_parameters.get(i))
451 {
452 (&TyKind::Unknown, _) | (_, None) => {
453 default_from = i + 1;
454 }
455 (_, Some(default_parameter)) => {
456 let actual_default = default_parameter
457 .clone()
458 .subst(&parameters.prefix(i));
459 if parameter != &actual_default {
443 default_from = i + 1; 460 default_from = i + 1;
444 } 461 }
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 } 462 }
454 } 463 }
455 &parameters.0[0..default_from]
456 } 464 }
465 &parameters.0[0..default_from]
457 } 466 }
458 } else { 467 }
459 parameters.0.as_ref() 468 } else {
460 }; 469 parameters.0.as_ref()
470 };
461 if !parameters_to_write.is_empty() { 471 if !parameters_to_write.is_empty() {
462 write!(f, "<")?; 472 write!(f, "<")?;
463 f.write_joined(parameters_to_write, ", ")?; 473 f.write_joined(parameters_to_write, ", ")?;
@@ -465,13 +475,14 @@ impl HirDisplay for Ty {
465 } 475 }
466 } 476 }
467 } 477 }
468 Ty::AssociatedType(type_alias, parameters) => { 478 TyKind::AssociatedType(assoc_type_id, parameters) => {
479 let type_alias = from_assoc_type_id(*assoc_type_id);
469 let trait_ = match type_alias.lookup(f.db.upcast()).container { 480 let trait_ = match type_alias.lookup(f.db.upcast()).container {
470 AssocContainerId::TraitId(it) => it, 481 AssocContainerId::TraitId(it) => it,
471 _ => panic!("not an associated type"), 482 _ => panic!("not an associated type"),
472 }; 483 };
473 let trait_ = f.db.trait_data(trait_); 484 let trait_ = f.db.trait_data(trait_);
474 let type_alias_data = f.db.type_alias_data(*type_alias); 485 let type_alias_data = f.db.type_alias_data(type_alias);
475 486
476 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 487 // 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() { 488 if f.display_target.is_test() {
@@ -482,19 +493,22 @@ impl HirDisplay for Ty {
482 write!(f, ">")?; 493 write!(f, ">")?;
483 } 494 }
484 } else { 495 } else {
485 let projection_ty = 496 let projection_ty = ProjectionTy {
486 ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; 497 associated_ty_id: to_assoc_type_id(type_alias),
498 substitution: parameters.clone(),
499 };
487 500
488 projection_ty.hir_fmt(f)?; 501 projection_ty.hir_fmt(f)?;
489 } 502 }
490 } 503 }
491 Ty::ForeignType(type_alias) => { 504 TyKind::ForeignType(type_alias) => {
492 let type_alias = f.db.type_alias_data(*type_alias); 505 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
493 write!(f, "{}", type_alias.name)?; 506 write!(f, "{}", type_alias.name)?;
494 } 507 }
495 Ty::OpaqueType(opaque_ty_id, parameters) => { 508 TyKind::OpaqueType(opaque_ty_id, parameters) => {
496 match opaque_ty_id { 509 let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
497 &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 510 match impl_trait_id {
511 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
498 let datas = 512 let datas =
499 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 513 f.db.return_type_impl_traits(func).expect("impl trait id without data");
500 let data = (*datas) 514 let data = (*datas)
@@ -504,14 +518,14 @@ impl HirDisplay for Ty {
504 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 518 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 519 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
506 } 520 }
507 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 521 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
508 write!(f, "impl Future<Output = ")?; 522 write!(f, "impl Future<Output = ")?;
509 parameters[0].hir_fmt(f)?; 523 parameters[0].hir_fmt(f)?;
510 write!(f, ">")?; 524 write!(f, ">")?;
511 } 525 }
512 } 526 }
513 } 527 }
514 Ty::Closure(.., substs) => { 528 TyKind::Closure(.., substs) => {
515 let sig = substs[0].callable_sig(f.db); 529 let sig = substs[0].callable_sig(f.db);
516 if let Some(sig) = sig { 530 if let Some(sig) = sig {
517 if sig.params().is_empty() { 531 if sig.params().is_empty() {
@@ -535,7 +549,8 @@ impl HirDisplay for Ty {
535 write!(f, "{{closure}}")?; 549 write!(f, "{{closure}}")?;
536 } 550 }
537 } 551 }
538 Ty::Placeholder(id) => { 552 TyKind::Placeholder(idx) => {
553 let id = from_placeholder_idx(f.db, *idx);
539 let generics = generics(f.db.upcast(), id.parent); 554 let generics = generics(f.db.upcast(), id.parent);
540 let param_data = &generics.params.types[id.local_id]; 555 let param_data = &generics.params.types[id.local_id];
541 match param_data.provenance { 556 match param_data.provenance {
@@ -543,8 +558,8 @@ impl HirDisplay for Ty {
543 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 558 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
544 } 559 }
545 TypeParamProvenance::ArgumentImplTrait => { 560 TypeParamProvenance::ArgumentImplTrait => {
546 let bounds = f.db.generic_predicates_for_param(*id); 561 let bounds = f.db.generic_predicates_for_param(id);
547 let substs = Substs::type_params_for_generics(&generics); 562 let substs = Substs::type_params_for_generics(f.db, &generics);
548 write_bounds_like_dyn_trait_with_prefix( 563 write_bounds_like_dyn_trait_with_prefix(
549 "impl", 564 "impl",
550 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), 565 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
@@ -553,28 +568,29 @@ impl HirDisplay for Ty {
553 } 568 }
554 } 569 }
555 } 570 }
556 Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 571 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
557 Ty::Dyn(predicates) => { 572 TyKind::Dyn(predicates) => {
558 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; 573 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
559 } 574 }
560 Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, 575 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
561 Ty::Alias(AliasTy::Opaque(opaque_ty)) => { 576 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
562 match opaque_ty.opaque_ty_id { 577 let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
563 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 578 match impl_trait_id {
579 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
564 let datas = 580 let datas =
565 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 581 f.db.return_type_impl_traits(func).expect("impl trait id without data");
566 let data = (*datas) 582 let data = (*datas)
567 .as_ref() 583 .as_ref()
568 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 584 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
569 let bounds = data.subst(&opaque_ty.parameters); 585 let bounds = data.subst(&opaque_ty.substitution);
570 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 586 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
571 } 587 }
572 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 588 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
573 write!(f, "{{async block}}")?; 589 write!(f, "{{async block}}")?;
574 } 590 }
575 }; 591 };
576 } 592 }
577 Ty::Unknown => { 593 TyKind::Unknown => {
578 if f.display_target.is_source_code() { 594 if f.display_target.is_source_code() {
579 return Err(HirDisplayError::DisplaySourceCodeError( 595 return Err(HirDisplayError::DisplaySourceCodeError(
580 DisplaySourceCodeError::UnknownType, 596 DisplaySourceCodeError::UnknownType,
@@ -582,7 +598,7 @@ impl HirDisplay for Ty {
582 } 598 }
583 write!(f, "{{unknown}}")?; 599 write!(f, "{{unknown}}")?;
584 } 600 }
585 Ty::InferenceVar(..) => write!(f, "_")?, 601 TyKind::InferenceVar(..) => write!(f, "_")?,
586 } 602 }
587 Ok(()) 603 Ok(())
588 } 604 }
@@ -695,7 +711,9 @@ fn write_bounds_like_dyn_trait(
695 write!(f, "<")?; 711 write!(f, "<")?;
696 angle_open = true; 712 angle_open = true;
697 } 713 }
698 let type_alias = f.db.type_alias_data(projection_pred.projection_ty.associated_ty); 714 let type_alias = f.db.type_alias_data(from_assoc_type_id(
715 projection_pred.projection_ty.associated_ty_id,
716 ));
699 write!(f, "{} = ", type_alias.name)?; 717 write!(f, "{} = ", type_alias.name)?;
700 projection_pred.ty.hir_fmt(f)?; 718 projection_pred.ty.hir_fmt(f)?;
701 } 719 }
@@ -766,7 +784,10 @@ impl HirDisplay for GenericPredicate {
766 write!( 784 write!(
767 f, 785 f,
768 ">::{} = ", 786 ">::{} = ",
769 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, 787 f.db.type_alias_data(from_assoc_type_id(
788 projection_pred.projection_ty.associated_ty_id
789 ))
790 .name,
770 )?; 791 )?;
771 projection_pred.ty.hir_fmt(f)?; 792 projection_pred.ty.hir_fmt(f)?;
772 } 793 }