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