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.rs178
1 files changed, 77 insertions, 101 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index b4801cb21..179f7ff44 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -3,9 +3,8 @@
3use std::{borrow::Cow, fmt}; 3use std::{borrow::Cow, fmt};
4 4
5use crate::{ 5use crate::{
6 db::HirDatabase, primitive, utils::generics, ApplicationTy, CallableDefId, FnSig, 6 db::HirDatabase, primitive, utils::generics, CallableDefId, CallableSig, GenericPredicate,
7 GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, 7 Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, TraitRef, Ty,
8 TraitRef, Ty, TypeCtor,
9}; 8};
10use arrayvec::ArrayVec; 9use arrayvec::ArrayVec;
11use hir_def::{ 10use hir_def::{
@@ -235,39 +234,62 @@ impl HirDisplay for &Ty {
235 } 234 }
236} 235}
237 236
238impl HirDisplay for ApplicationTy { 237impl HirDisplay for ProjectionTy {
239 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 238 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
240 if f.should_truncate() { 239 if f.should_truncate() {
241 return write!(f, "{}", TYPE_HINT_TRUNCATION); 240 return write!(f, "{}", TYPE_HINT_TRUNCATION);
242 } 241 }
243 242
244 match self.ctor { 243 let trait_ = f.db.trait_data(self.trait_(f.db));
245 TypeCtor::Scalar(Scalar::Bool) => write!(f, "bool")?, 244 let first_parameter = self.parameters[0].into_displayable(
246 TypeCtor::Scalar(Scalar::Char) => write!(f, "char")?, 245 f.db,
247 TypeCtor::Scalar(Scalar::Float(t)) => { 246 f.max_size,
248 write!(f, "{}", primitive::float_ty_to_string(t))? 247 f.omit_verbose_types,
249 } 248 f.display_target,
250 TypeCtor::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, 249 );
251 TypeCtor::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, 250 write!(f, "<{} as {}", first_parameter, trait_.name)?;
252 TypeCtor::Str => write!(f, "str")?, 251 if self.parameters.len() > 1 {
253 TypeCtor::Slice => { 252 write!(f, "<")?;
254 let t = self.parameters.as_single(); 253 f.write_joined(&self.parameters[1..], ", ")?;
254 write!(f, ">")?;
255 }
256 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
257 Ok(())
258 }
259}
260
261impl HirDisplay for Ty {
262 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
263 if f.should_truncate() {
264 return write!(f, "{}", TYPE_HINT_TRUNCATION);
265 }
266
267 match self {
268 Ty::Never => write!(f, "!")?,
269 Ty::Str => write!(f, "str")?,
270 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?,
271 Ty::Scalar(Scalar::Char) => write!(f, "char")?,
272 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
273 &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
274 &Ty::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
275 Ty::Slice(parameters) => {
276 let t = parameters.as_single();
255 write!(f, "[")?; 277 write!(f, "[")?;
256 t.hir_fmt(f)?; 278 t.hir_fmt(f)?;
257 write!(f, "]")?; 279 write!(f, "]")?;
258 } 280 }
259 TypeCtor::Array => { 281 Ty::Array(parameters) => {
260 let t = self.parameters.as_single(); 282 let t = parameters.as_single();
261 write!(f, "[")?; 283 write!(f, "[")?;
262 t.hir_fmt(f)?; 284 t.hir_fmt(f)?;
263 write!(f, "; _]")?; 285 write!(f, "; _]")?;
264 } 286 }
265 TypeCtor::RawPtr(m) | TypeCtor::Ref(m) => { 287 Ty::RawPtr(m, parameters) | Ty::Ref(m, parameters) => {
266 let t = self.parameters.as_single(); 288 let t = parameters.as_single();
267 let ty_display = 289 let ty_display =
268 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 290 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
269 291
270 if matches!(self.ctor, TypeCtor::RawPtr(_)) { 292 if matches!(self, Ty::RawPtr(..)) {
271 write!(f, "*{}", m.as_keyword_for_ptr())?; 293 write!(f, "*{}", m.as_keyword_for_ptr())?;
272 } else { 294 } else {
273 write!(f, "&{}", m.as_keyword_for_ref())?; 295 write!(f, "&{}", m.as_keyword_for_ref())?;
@@ -308,25 +330,24 @@ impl HirDisplay for ApplicationTy {
308 write!(f, "{}", ty_display)?; 330 write!(f, "{}", ty_display)?;
309 } 331 }
310 } 332 }
311 TypeCtor::Never => write!(f, "!")?, 333 Ty::Tuple(_, substs) => {
312 TypeCtor::Tuple { .. } => { 334 if substs.len() == 1 {
313 let ts = &self.parameters;
314 if ts.len() == 1 {
315 write!(f, "(")?; 335 write!(f, "(")?;
316 ts[0].hir_fmt(f)?; 336 substs[0].hir_fmt(f)?;
317 write!(f, ",)")?; 337 write!(f, ",)")?;
318 } else { 338 } else {
319 write!(f, "(")?; 339 write!(f, "(")?;
320 f.write_joined(&*ts.0, ", ")?; 340 f.write_joined(&*substs.0, ", ")?;
321 write!(f, ")")?; 341 write!(f, ")")?;
322 } 342 }
323 } 343 }
324 TypeCtor::FnPtr { is_varargs, .. } => { 344 Ty::Function(fn_ptr) => {
325 let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs); 345 let sig = CallableSig::from_fn_ptr(fn_ptr);
326 sig.hir_fmt(f)?; 346 sig.hir_fmt(f)?;
327 } 347 }
328 TypeCtor::FnDef(def) => { 348 Ty::FnDef(def, parameters) => {
329 let sig = f.db.callable_item_signature(def).subst(&self.parameters); 349 let def = *def;
350 let sig = f.db.callable_item_signature(def).subst(parameters);
330 match def { 351 match def {
331 CallableDefId::FunctionId(ff) => { 352 CallableDefId::FunctionId(ff) => {
332 write!(f, "fn {}", f.db.function_data(ff).name)? 353 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -336,7 +357,7 @@ impl HirDisplay for ApplicationTy {
336 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 357 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
337 } 358 }
338 }; 359 };
339 if self.parameters.len() > 0 { 360 if parameters.len() > 0 {
340 let generics = generics(f.db.upcast(), def.into()); 361 let generics = generics(f.db.upcast(), def.into());
341 let (parent_params, self_param, type_params, _impl_trait_params) = 362 let (parent_params, self_param, type_params, _impl_trait_params) =
342 generics.provenance_split(); 363 generics.provenance_split();
@@ -344,7 +365,7 @@ impl HirDisplay for ApplicationTy {
344 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 365 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
345 if total_len > 0 { 366 if total_len > 0 {
346 write!(f, "<")?; 367 write!(f, "<")?;
347 f.write_joined(&self.parameters.0[..total_len], ", ")?; 368 f.write_joined(&parameters.0[..total_len], ", ")?;
348 write!(f, ">")?; 369 write!(f, ">")?;
349 } 370 }
350 } 371 }
@@ -363,10 +384,10 @@ impl HirDisplay for ApplicationTy {
363 write!(f, " -> {}", ret_display)?; 384 write!(f, " -> {}", ret_display)?;
364 } 385 }
365 } 386 }
366 TypeCtor::Adt(def_id) => { 387 Ty::Adt(def_id, parameters) => {
367 match f.display_target { 388 match f.display_target {
368 DisplayTarget::Diagnostics | DisplayTarget::Test => { 389 DisplayTarget::Diagnostics | DisplayTarget::Test => {
369 let name = match def_id { 390 let name = match *def_id {
370 AdtId::StructId(it) => f.db.struct_data(it).name.clone(), 391 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
371 AdtId::UnionId(it) => f.db.union_data(it).name.clone(), 392 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
372 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), 393 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
@@ -376,7 +397,7 @@ impl HirDisplay for ApplicationTy {
376 DisplayTarget::SourceCode { module_id } => { 397 DisplayTarget::SourceCode { module_id } => {
377 if let Some(path) = find_path::find_path( 398 if let Some(path) = find_path::find_path(
378 f.db.upcast(), 399 f.db.upcast(),
379 ItemInNs::Types(def_id.into()), 400 ItemInNs::Types((*def_id).into()),
380 module_id, 401 module_id,
381 ) { 402 ) {
382 write!(f, "{}", path)?; 403 write!(f, "{}", path)?;
@@ -388,19 +409,18 @@ impl HirDisplay for ApplicationTy {
388 } 409 }
389 } 410 }
390 411
391 if self.parameters.len() > 0 { 412 if parameters.len() > 0 {
392 let parameters_to_write = 413 let parameters_to_write =
393 if f.display_target.is_source_code() || f.omit_verbose_types() { 414 if f.display_target.is_source_code() || f.omit_verbose_types() {
394 match self 415 match self
395 .ctor
396 .as_generic_def() 416 .as_generic_def()
397 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 417 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
398 .filter(|defaults| !defaults.is_empty()) 418 .filter(|defaults| !defaults.is_empty())
399 { 419 {
400 None => self.parameters.0.as_ref(), 420 None => parameters.0.as_ref(),
401 Some(default_parameters) => { 421 Some(default_parameters) => {
402 let mut default_from = 0; 422 let mut default_from = 0;
403 for (i, parameter) in self.parameters.iter().enumerate() { 423 for (i, parameter) in parameters.iter().enumerate() {
404 match (parameter, default_parameters.get(i)) { 424 match (parameter, default_parameters.get(i)) {
405 (&Ty::Unknown, _) | (_, None) => { 425 (&Ty::Unknown, _) | (_, None) => {
406 default_from = i + 1; 426 default_from = i + 1;
@@ -408,18 +428,18 @@ impl HirDisplay for ApplicationTy {
408 (_, Some(default_parameter)) => { 428 (_, Some(default_parameter)) => {
409 let actual_default = default_parameter 429 let actual_default = default_parameter
410 .clone() 430 .clone()
411 .subst(&self.parameters.prefix(i)); 431 .subst(&parameters.prefix(i));
412 if parameter != &actual_default { 432 if parameter != &actual_default {
413 default_from = i + 1; 433 default_from = i + 1;
414 } 434 }
415 } 435 }
416 } 436 }
417 } 437 }
418 &self.parameters.0[0..default_from] 438 &parameters.0[0..default_from]
419 } 439 }
420 } 440 }
421 } else { 441 } else {
422 self.parameters.0.as_ref() 442 parameters.0.as_ref()
423 }; 443 };
424 if !parameters_to_write.is_empty() { 444 if !parameters_to_write.is_empty() {
425 write!(f, "<")?; 445 write!(f, "<")?;
@@ -428,61 +448,54 @@ impl HirDisplay for ApplicationTy {
428 } 448 }
429 } 449 }
430 } 450 }
431 TypeCtor::AssociatedType(type_alias) => { 451 Ty::AssociatedType(type_alias, parameters) => {
432 let trait_ = match type_alias.lookup(f.db.upcast()).container { 452 let trait_ = match type_alias.lookup(f.db.upcast()).container {
433 AssocContainerId::TraitId(it) => it, 453 AssocContainerId::TraitId(it) => it,
434 _ => panic!("not an associated type"), 454 _ => panic!("not an associated type"),
435 }; 455 };
436 let trait_ = f.db.trait_data(trait_); 456 let trait_ = f.db.trait_data(trait_);
437 let type_alias_data = f.db.type_alias_data(type_alias); 457 let type_alias_data = f.db.type_alias_data(*type_alias);
438 458
439 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 459 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
440 if f.display_target.is_test() { 460 if f.display_target.is_test() {
441 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 461 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
442 if self.parameters.len() > 0 { 462 if parameters.len() > 0 {
443 write!(f, "<")?; 463 write!(f, "<")?;
444 f.write_joined(&*self.parameters.0, ", ")?; 464 f.write_joined(&*parameters.0, ", ")?;
445 write!(f, ">")?; 465 write!(f, ">")?;
446 } 466 }
447 } else { 467 } else {
448 let projection_ty = ProjectionTy { 468 let projection_ty =
449 associated_ty: type_alias, 469 ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() };
450 parameters: self.parameters.clone(),
451 };
452 470
453 projection_ty.hir_fmt(f)?; 471 projection_ty.hir_fmt(f)?;
454 } 472 }
455 } 473 }
456 TypeCtor::ForeignType(type_alias) => { 474 Ty::ForeignType(type_alias) => {
457 let type_alias = f.db.type_alias_data(type_alias); 475 let type_alias = f.db.type_alias_data(*type_alias);
458 write!(f, "{}", type_alias.name)?; 476 write!(f, "{}", type_alias.name)?;
459 if self.parameters.len() > 0 {
460 write!(f, "<")?;
461 f.write_joined(&*self.parameters.0, ", ")?;
462 write!(f, ">")?;
463 }
464 } 477 }
465 TypeCtor::OpaqueType(opaque_ty_id) => { 478 Ty::OpaqueType(opaque_ty_id, parameters) => {
466 match opaque_ty_id { 479 match opaque_ty_id {
467 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 480 &OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
468 let datas = 481 let datas =
469 f.db.return_type_impl_traits(func).expect("impl trait id without data"); 482 f.db.return_type_impl_traits(func).expect("impl trait id without data");
470 let data = (*datas) 483 let data = (*datas)
471 .as_ref() 484 .as_ref()
472 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 485 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
473 let bounds = data.subst(&self.parameters); 486 let bounds = data.subst(&parameters);
474 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 487 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
475 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 488 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
476 } 489 }
477 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 490 OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
478 write!(f, "impl Future<Output = ")?; 491 write!(f, "impl Future<Output = ")?;
479 self.parameters[0].hir_fmt(f)?; 492 parameters[0].hir_fmt(f)?;
480 write!(f, ">")?; 493 write!(f, ">")?;
481 } 494 }
482 } 495 }
483 } 496 }
484 TypeCtor::Closure { .. } => { 497 Ty::Closure(.., substs) => {
485 let sig = self.parameters[0].callable_sig(f.db); 498 let sig = substs[0].callable_sig(f.db);
486 if let Some(sig) = sig { 499 if let Some(sig) = sig {
487 if sig.params().is_empty() { 500 if sig.params().is_empty() {
488 write!(f, "||")?; 501 write!(f, "||")?;
@@ -505,43 +518,6 @@ impl HirDisplay for ApplicationTy {
505 write!(f, "{{closure}}")?; 518 write!(f, "{{closure}}")?;
506 } 519 }
507 } 520 }
508 }
509 Ok(())
510 }
511}
512
513impl HirDisplay for ProjectionTy {
514 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
515 if f.should_truncate() {
516 return write!(f, "{}", TYPE_HINT_TRUNCATION);
517 }
518
519 let trait_ = f.db.trait_data(self.trait_(f.db));
520 let first_parameter = self.parameters[0].into_displayable(
521 f.db,
522 f.max_size,
523 f.omit_verbose_types,
524 f.display_target,
525 );
526 write!(f, "<{} as {}", first_parameter, trait_.name)?;
527 if self.parameters.len() > 1 {
528 write!(f, "<")?;
529 f.write_joined(&self.parameters[1..], ", ")?;
530 write!(f, ">")?;
531 }
532 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
533 Ok(())
534 }
535}
536
537impl HirDisplay for Ty {
538 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
539 if f.should_truncate() {
540 return write!(f, "{}", TYPE_HINT_TRUNCATION);
541 }
542
543 match self {
544 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
545 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, 521 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
546 Ty::Placeholder(id) => { 522 Ty::Placeholder(id) => {
547 let generics = generics(f.db.upcast(), id.parent); 523 let generics = generics(f.db.upcast(), id.parent);
@@ -595,7 +571,7 @@ impl HirDisplay for Ty {
595 } 571 }
596} 572}
597 573
598impl HirDisplay for FnSig { 574impl HirDisplay for CallableSig {
599 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 575 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
600 write!(f, "fn(")?; 576 write!(f, "fn(")?;
601 f.write_joined(self.params(), ", ")?; 577 f.write_joined(self.params(), ", ")?;