diff options
Diffstat (limited to 'crates/hir_ty/src/display.rs')
-rw-r--r-- | crates/hir_ty/src/display.rs | 186 |
1 files changed, 102 insertions, 84 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index ab51cb0a6..e6473586b 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -11,9 +11,10 @@ use hir_def::{ | |||
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | 12 | ||
13 | use crate::{ | 13 | use 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 | ||
19 | pub struct HirFormatter<'a> { | 20 | pub struct HirFormatter<'a> { |
@@ -256,7 +257,7 @@ impl HirDisplay for ProjectionTy { | |||
256 | f.write_joined(&self.parameters[1..], ", ")?; | 257 | f.write_joined(&self.parameters[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)).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,26 @@ 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 { opaque_ty_id, ref parameters })) => { |
321 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), | 323 | let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty_id.into()); |
322 | ref parameters, | 324 | if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { |
323 | })) => { | 325 | datas = |
324 | datas = | 326 | f.db.return_type_impl_traits(func) |
325 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 327 | .expect("impl trait id without data"); |
326 | let data = (*datas) | 328 | let data = (*datas) |
327 | .as_ref() | 329 | .as_ref() |
328 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 330 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
329 | let bounds = data.subst(parameters); | 331 | let bounds = data.subst(parameters); |
330 | Cow::Owned(bounds.value) | 332 | Cow::Owned(bounds.value) |
333 | } else { | ||
334 | Cow::Borrowed(&[][..]) | ||
335 | } | ||
331 | } | 336 | } |
332 | _ => Cow::Borrowed(&[][..]), | 337 | _ => Cow::Borrowed(&[][..]), |
333 | }; | 338 | }; |
@@ -347,7 +352,7 @@ impl HirDisplay for Ty { | |||
347 | write!(f, "{}", ty_display)?; | 352 | write!(f, "{}", ty_display)?; |
348 | } | 353 | } |
349 | } | 354 | } |
350 | Ty::Tuple(_, substs) => { | 355 | TyKind::Tuple(_, substs) => { |
351 | if substs.len() == 1 { | 356 | if substs.len() == 1 { |
352 | write!(f, "(")?; | 357 | write!(f, "(")?; |
353 | substs[0].hir_fmt(f)?; | 358 | substs[0].hir_fmt(f)?; |
@@ -358,12 +363,12 @@ impl HirDisplay for Ty { | |||
358 | write!(f, ")")?; | 363 | write!(f, ")")?; |
359 | } | 364 | } |
360 | } | 365 | } |
361 | Ty::Function(fn_ptr) => { | 366 | TyKind::Function(fn_ptr) => { |
362 | let sig = CallableSig::from_fn_ptr(fn_ptr); | 367 | let sig = CallableSig::from_fn_ptr(fn_ptr); |
363 | sig.hir_fmt(f)?; | 368 | sig.hir_fmt(f)?; |
364 | } | 369 | } |
365 | Ty::FnDef(def, parameters) => { | 370 | TyKind::FnDef(def, parameters) => { |
366 | let def = *def; | 371 | let def = from_chalk(f.db, *def); |
367 | let sig = f.db.callable_item_signature(def).subst(parameters); | 372 | let sig = f.db.callable_item_signature(def).subst(parameters); |
368 | match def { | 373 | match def { |
369 | CallableDefId::FunctionId(ff) => { | 374 | CallableDefId::FunctionId(ff) => { |
@@ -401,7 +406,7 @@ impl HirDisplay for Ty { | |||
401 | write!(f, " -> {}", ret_display)?; | 406 | write!(f, " -> {}", ret_display)?; |
402 | } | 407 | } |
403 | } | 408 | } |
404 | Ty::Adt(AdtId(def_id), parameters) => { | 409 | TyKind::Adt(AdtId(def_id), parameters) => { |
405 | match f.display_target { | 410 | match f.display_target { |
406 | DisplayTarget::Diagnostics | DisplayTarget::Test => { | 411 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
407 | let name = match *def_id { | 412 | let name = match *def_id { |
@@ -427,37 +432,39 @@ impl HirDisplay for Ty { | |||
427 | } | 432 | } |
428 | 433 | ||
429 | if parameters.len() > 0 { | 434 | if parameters.len() > 0 { |
430 | let parameters_to_write = | 435 | let parameters_to_write = if f.display_target.is_source_code() |
431 | if f.display_target.is_source_code() || f.omit_verbose_types() { | 436 | || f.omit_verbose_types() |
432 | match self | 437 | { |
433 | .as_generic_def() | 438 | match self |
434 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 439 | .as_generic_def(f.db) |
435 | .filter(|defaults| !defaults.is_empty()) | 440 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
436 | { | 441 | .filter(|defaults| !defaults.is_empty()) |
437 | None => parameters.0.as_ref(), | 442 | { |
438 | Some(default_parameters) => { | 443 | None => parameters.0.as_ref(), |
439 | let mut default_from = 0; | 444 | Some(default_parameters) => { |
440 | for (i, parameter) in parameters.iter().enumerate() { | 445 | let mut default_from = 0; |
441 | match (parameter, default_parameters.get(i)) { | 446 | for (i, parameter) in parameters.iter().enumerate() { |
442 | (&Ty::Unknown, _) | (_, None) => { | 447 | match (parameter.interned(&Interner), default_parameters.get(i)) |
448 | { | ||
449 | (&TyKind::Unknown, _) | (_, None) => { | ||
450 | default_from = i + 1; | ||
451 | } | ||
452 | (_, Some(default_parameter)) => { | ||
453 | let actual_default = default_parameter | ||
454 | .clone() | ||
455 | .subst(¶meters.prefix(i)); | ||
456 | if parameter != &actual_default { | ||
443 | default_from = i + 1; | 457 | default_from = i + 1; |
444 | } | 458 | } |
445 | (_, Some(default_parameter)) => { | ||
446 | let actual_default = default_parameter | ||
447 | .clone() | ||
448 | .subst(¶meters.prefix(i)); | ||
449 | if parameter != &actual_default { | ||
450 | default_from = i + 1; | ||
451 | } | ||
452 | } | ||
453 | } | 459 | } |
454 | } | 460 | } |
455 | ¶meters.0[0..default_from] | ||
456 | } | 461 | } |
462 | ¶meters.0[0..default_from] | ||
457 | } | 463 | } |
458 | } else { | 464 | } |
459 | parameters.0.as_ref() | 465 | } else { |
460 | }; | 466 | parameters.0.as_ref() |
467 | }; | ||
461 | if !parameters_to_write.is_empty() { | 468 | if !parameters_to_write.is_empty() { |
462 | write!(f, "<")?; | 469 | write!(f, "<")?; |
463 | f.write_joined(parameters_to_write, ", ")?; | 470 | f.write_joined(parameters_to_write, ", ")?; |
@@ -465,13 +472,14 @@ impl HirDisplay for Ty { | |||
465 | } | 472 | } |
466 | } | 473 | } |
467 | } | 474 | } |
468 | Ty::AssociatedType(type_alias, parameters) => { | 475 | TyKind::AssociatedType(assoc_type_id, parameters) => { |
476 | let type_alias = from_assoc_type_id(*assoc_type_id); | ||
469 | let trait_ = match type_alias.lookup(f.db.upcast()).container { | 477 | let trait_ = match type_alias.lookup(f.db.upcast()).container { |
470 | AssocContainerId::TraitId(it) => it, | 478 | AssocContainerId::TraitId(it) => it, |
471 | _ => panic!("not an associated type"), | 479 | _ => panic!("not an associated type"), |
472 | }; | 480 | }; |
473 | let trait_ = f.db.trait_data(trait_); | 481 | let trait_ = f.db.trait_data(trait_); |
474 | let type_alias_data = f.db.type_alias_data(*type_alias); | 482 | let type_alias_data = f.db.type_alias_data(type_alias); |
475 | 483 | ||
476 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) | 484 | // 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() { | 485 | if f.display_target.is_test() { |
@@ -482,19 +490,22 @@ impl HirDisplay for Ty { | |||
482 | write!(f, ">")?; | 490 | write!(f, ">")?; |
483 | } | 491 | } |
484 | } else { | 492 | } else { |
485 | let projection_ty = | 493 | let projection_ty = ProjectionTy { |
486 | ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; | 494 | associated_ty: to_assoc_type_id(type_alias), |
495 | parameters: parameters.clone(), | ||
496 | }; | ||
487 | 497 | ||
488 | projection_ty.hir_fmt(f)?; | 498 | projection_ty.hir_fmt(f)?; |
489 | } | 499 | } |
490 | } | 500 | } |
491 | Ty::ForeignType(type_alias) => { | 501 | TyKind::ForeignType(type_alias) => { |
492 | let type_alias = f.db.type_alias_data(*type_alias); | 502 | let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias)); |
493 | write!(f, "{}", type_alias.name)?; | 503 | write!(f, "{}", type_alias.name)?; |
494 | } | 504 | } |
495 | Ty::OpaqueType(opaque_ty_id, parameters) => { | 505 | TyKind::OpaqueType(opaque_ty_id, parameters) => { |
496 | match opaque_ty_id { | 506 | let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into()); |
497 | &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 507 | match impl_trait_id { |
508 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||
498 | let datas = | 509 | let datas = |
499 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 510 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
500 | let data = (*datas) | 511 | let data = (*datas) |
@@ -504,14 +515,14 @@ impl HirDisplay for Ty { | |||
504 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 515 | 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 | 516 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution |
506 | } | 517 | } |
507 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 518 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { |
508 | write!(f, "impl Future<Output = ")?; | 519 | write!(f, "impl Future<Output = ")?; |
509 | parameters[0].hir_fmt(f)?; | 520 | parameters[0].hir_fmt(f)?; |
510 | write!(f, ">")?; | 521 | write!(f, ">")?; |
511 | } | 522 | } |
512 | } | 523 | } |
513 | } | 524 | } |
514 | Ty::Closure(.., substs) => { | 525 | TyKind::Closure(.., substs) => { |
515 | let sig = substs[0].callable_sig(f.db); | 526 | let sig = substs[0].callable_sig(f.db); |
516 | if let Some(sig) = sig { | 527 | if let Some(sig) = sig { |
517 | if sig.params().is_empty() { | 528 | if sig.params().is_empty() { |
@@ -535,7 +546,8 @@ impl HirDisplay for Ty { | |||
535 | write!(f, "{{closure}}")?; | 546 | write!(f, "{{closure}}")?; |
536 | } | 547 | } |
537 | } | 548 | } |
538 | Ty::Placeholder(id) => { | 549 | TyKind::Placeholder(idx) => { |
550 | let id = from_placeholder_idx(f.db, *idx); | ||
539 | let generics = generics(f.db.upcast(), id.parent); | 551 | let generics = generics(f.db.upcast(), id.parent); |
540 | let param_data = &generics.params.types[id.local_id]; | 552 | let param_data = &generics.params.types[id.local_id]; |
541 | match param_data.provenance { | 553 | match param_data.provenance { |
@@ -543,8 +555,8 @@ impl HirDisplay for Ty { | |||
543 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 555 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
544 | } | 556 | } |
545 | TypeParamProvenance::ArgumentImplTrait => { | 557 | TypeParamProvenance::ArgumentImplTrait => { |
546 | let bounds = f.db.generic_predicates_for_param(*id); | 558 | let bounds = f.db.generic_predicates_for_param(id); |
547 | let substs = Substs::type_params_for_generics(&generics); | 559 | let substs = Substs::type_params_for_generics(f.db, &generics); |
548 | write_bounds_like_dyn_trait_with_prefix( | 560 | write_bounds_like_dyn_trait_with_prefix( |
549 | "impl", | 561 | "impl", |
550 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 562 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), |
@@ -553,14 +565,15 @@ impl HirDisplay for Ty { | |||
553 | } | 565 | } |
554 | } | 566 | } |
555 | } | 567 | } |
556 | Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 568 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
557 | Ty::Dyn(predicates) => { | 569 | TyKind::Dyn(predicates) => { |
558 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 570 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; |
559 | } | 571 | } |
560 | Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 572 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
561 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | 573 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
562 | match opaque_ty.opaque_ty_id { | 574 | let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()); |
563 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 575 | match impl_trait_id { |
576 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||
564 | let datas = | 577 | let datas = |
565 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 578 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
566 | let data = (*datas) | 579 | let data = (*datas) |
@@ -569,12 +582,12 @@ impl HirDisplay for Ty { | |||
569 | let bounds = data.subst(&opaque_ty.parameters); | 582 | let bounds = data.subst(&opaque_ty.parameters); |
570 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 583 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; |
571 | } | 584 | } |
572 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 585 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { |
573 | write!(f, "{{async block}}")?; | 586 | write!(f, "{{async block}}")?; |
574 | } | 587 | } |
575 | }; | 588 | }; |
576 | } | 589 | } |
577 | Ty::Unknown => { | 590 | TyKind::Unknown => { |
578 | if f.display_target.is_source_code() { | 591 | if f.display_target.is_source_code() { |
579 | return Err(HirDisplayError::DisplaySourceCodeError( | 592 | return Err(HirDisplayError::DisplaySourceCodeError( |
580 | DisplaySourceCodeError::UnknownType, | 593 | DisplaySourceCodeError::UnknownType, |
@@ -582,7 +595,7 @@ impl HirDisplay for Ty { | |||
582 | } | 595 | } |
583 | write!(f, "{{unknown}}")?; | 596 | write!(f, "{{unknown}}")?; |
584 | } | 597 | } |
585 | Ty::InferenceVar(..) => write!(f, "_")?, | 598 | TyKind::InferenceVar(..) => write!(f, "_")?, |
586 | } | 599 | } |
587 | Ok(()) | 600 | Ok(()) |
588 | } | 601 | } |
@@ -695,7 +708,9 @@ fn write_bounds_like_dyn_trait( | |||
695 | write!(f, "<")?; | 708 | write!(f, "<")?; |
696 | angle_open = true; | 709 | angle_open = true; |
697 | } | 710 | } |
698 | let type_alias = f.db.type_alias_data(projection_pred.projection_ty.associated_ty); | 711 | let type_alias = f.db.type_alias_data(from_assoc_type_id( |
712 | projection_pred.projection_ty.associated_ty, | ||
713 | )); | ||
699 | write!(f, "{} = ", type_alias.name)?; | 714 | write!(f, "{} = ", type_alias.name)?; |
700 | projection_pred.ty.hir_fmt(f)?; | 715 | projection_pred.ty.hir_fmt(f)?; |
701 | } | 716 | } |
@@ -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 | ||
786 | )) | ||
787 | .name, | ||
770 | )?; | 788 | )?; |
771 | projection_pred.ty.hir_fmt(f)?; | 789 | projection_pred.ty.hir_fmt(f)?; |
772 | } | 790 | } |