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