diff options
Diffstat (limited to 'crates/hir_ty/src/display.rs')
-rw-r--r-- | crates/hir_ty/src/display.rs | 401 |
1 files changed, 303 insertions, 98 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index ab51cb0a6..c572bb114 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -5,15 +5,22 @@ use std::{borrow::Cow, fmt}; | |||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, | 8 | db::DefDatabase, |
9 | find_path, | ||
10 | generics::TypeParamProvenance, | ||
11 | item_scope::ItemInNs, | ||
12 | path::{GenericArg, Path, PathKind}, | ||
13 | type_ref::{TypeBound, TypeRef}, | ||
14 | visibility::Visibility, | ||
9 | AssocContainerId, Lookup, ModuleId, TraitId, | 15 | AssocContainerId, Lookup, ModuleId, TraitId, |
10 | }; | 16 | }; |
11 | use hir_expand::name::Name; | 17 | use hir_expand::name::Name; |
12 | 18 | ||
13 | use crate::{ | 19 | use crate::{ |
14 | db::HirDatabase, primitive, utils::generics, AdtId, AliasTy, CallableDefId, CallableSig, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
15 | GenericPredicate, Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId, |
16 | TraitRef, Ty, | 22 | CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, |
23 | ProjectionTy, Scalar, Substs, TraitRef, Ty, TyKind, | ||
17 | }; | 24 | }; |
18 | 25 | ||
19 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -231,7 +238,7 @@ where | |||
231 | 238 | ||
232 | const TYPE_HINT_TRUNCATION: &str = "…"; | 239 | const TYPE_HINT_TRUNCATION: &str = "…"; |
233 | 240 | ||
234 | impl HirDisplay for &Ty { | 241 | impl<T: HirDisplay> HirDisplay for &'_ T { |
235 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 242 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
236 | HirDisplay::hir_fmt(*self, f) | 243 | HirDisplay::hir_fmt(*self, f) |
237 | } | 244 | } |
@@ -244,19 +251,19 @@ impl HirDisplay for ProjectionTy { | |||
244 | } | 251 | } |
245 | 252 | ||
246 | let trait_ = f.db.trait_data(self.trait_(f.db)); | 253 | let trait_ = f.db.trait_data(self.trait_(f.db)); |
247 | let first_parameter = self.parameters[0].into_displayable( | 254 | let first_parameter = self.substitution[0].into_displayable( |
248 | f.db, | 255 | f.db, |
249 | f.max_size, | 256 | f.max_size, |
250 | f.omit_verbose_types, | 257 | f.omit_verbose_types, |
251 | f.display_target, | 258 | f.display_target, |
252 | ); | 259 | ); |
253 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | 260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; |
254 | if self.parameters.len() > 1 { | 261 | if self.substitution.len() > 1 { |
255 | write!(f, "<")?; | 262 | write!(f, "<")?; |
256 | f.write_joined(&self.parameters[1..], ", ")?; | 263 | f.write_joined(&self.substitution[1..], ", ")?; |
257 | write!(f, ">")?; | 264 | write!(f, ">")?; |
258 | } | 265 | } |
259 | write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?; | 266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; |
260 | Ok(()) | 267 | Ok(()) |
261 | } | 268 | } |
262 | } | 269 | } |
@@ -267,32 +274,29 @@ impl HirDisplay for Ty { | |||
267 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 274 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
268 | } | 275 | } |
269 | 276 | ||
270 | match self { | 277 | match self.interned(&Interner) { |
271 | Ty::Never => write!(f, "!")?, | 278 | TyKind::Never => write!(f, "!")?, |
272 | Ty::Str => write!(f, "str")?, | 279 | TyKind::Str => write!(f, "str")?, |
273 | Ty::Scalar(Scalar::Bool) => write!(f, "bool")?, | 280 | TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, |
274 | Ty::Scalar(Scalar::Char) => write!(f, "char")?, | 281 | TyKind::Scalar(Scalar::Char) => write!(f, "char")?, |
275 | &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, | 282 | &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))?, | 283 | &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))?, | 284 | &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, |
278 | Ty::Slice(parameters) => { | 285 | TyKind::Slice(t) => { |
279 | let t = parameters.as_single(); | ||
280 | write!(f, "[")?; | 286 | write!(f, "[")?; |
281 | t.hir_fmt(f)?; | 287 | t.hir_fmt(f)?; |
282 | write!(f, "]")?; | 288 | write!(f, "]")?; |
283 | } | 289 | } |
284 | Ty::Array(parameters) => { | 290 | TyKind::Array(t) => { |
285 | let t = parameters.as_single(); | ||
286 | write!(f, "[")?; | 291 | write!(f, "[")?; |
287 | t.hir_fmt(f)?; | 292 | t.hir_fmt(f)?; |
288 | write!(f, "; _]")?; | 293 | write!(f, "; _]")?; |
289 | } | 294 | } |
290 | Ty::Raw(m, parameters) | Ty::Ref(m, parameters) => { | 295 | TyKind::Raw(m, t) | TyKind::Ref(m, t) => { |
291 | let t = parameters.as_single(); | ||
292 | let ty_display = | 296 | let ty_display = |
293 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 297 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
294 | 298 | ||
295 | if matches!(self, Ty::Raw(..)) { | 299 | if matches!(self.interned(&Interner), TyKind::Raw(..)) { |
296 | write!( | 300 | write!( |
297 | f, | 301 | f, |
298 | "*{}", | 302 | "*{}", |
@@ -312,22 +316,29 @@ impl HirDisplay for Ty { | |||
312 | )?; | 316 | )?; |
313 | } | 317 | } |
314 | 318 | ||
319 | // FIXME: all this just to decide whether to use parentheses... | ||
315 | let datas; | 320 | let datas; |
316 | let predicates = match t { | 321 | let predicates = match t.interned(&Interner) { |
317 | Ty::Dyn(predicates) if predicates.len() > 1 => { | 322 | TyKind::Dyn(predicates) if predicates.len() > 1 => { |
318 | Cow::Borrowed(predicates.as_ref()) | 323 | Cow::Borrowed(predicates.as_ref()) |
319 | } | 324 | } |
320 | &Ty::Alias(AliasTy::Opaque(OpaqueTy { | 325 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
321 | opaque_ty_id: OpaqueTyId::ReturnTypeImplTrait(func, idx), | 326 | opaque_ty_id, |
322 | ref parameters, | 327 | substitution: ref parameters, |
323 | })) => { | 328 | })) => { |
324 | datas = | 329 | 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"); | 330 | if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { |
326 | let data = (*datas) | 331 | datas = |
327 | .as_ref() | 332 | f.db.return_type_impl_traits(func) |
328 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 333 | .expect("impl trait id without data"); |
329 | let bounds = data.subst(parameters); | 334 | let data = (*datas) |
330 | Cow::Owned(bounds.value) | 335 | .as_ref() |
336 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | ||
337 | let bounds = data.subst(parameters); | ||
338 | Cow::Owned(bounds.value) | ||
339 | } else { | ||
340 | Cow::Borrowed(&[][..]) | ||
341 | } | ||
331 | } | 342 | } |
332 | _ => Cow::Borrowed(&[][..]), | 343 | _ => Cow::Borrowed(&[][..]), |
333 | }; | 344 | }; |
@@ -347,7 +358,7 @@ impl HirDisplay for Ty { | |||
347 | write!(f, "{}", ty_display)?; | 358 | write!(f, "{}", ty_display)?; |
348 | } | 359 | } |
349 | } | 360 | } |
350 | Ty::Tuple(_, substs) => { | 361 | TyKind::Tuple(_, substs) => { |
351 | if substs.len() == 1 { | 362 | if substs.len() == 1 { |
352 | write!(f, "(")?; | 363 | write!(f, "(")?; |
353 | substs[0].hir_fmt(f)?; | 364 | substs[0].hir_fmt(f)?; |
@@ -358,12 +369,12 @@ impl HirDisplay for Ty { | |||
358 | write!(f, ")")?; | 369 | write!(f, ")")?; |
359 | } | 370 | } |
360 | } | 371 | } |
361 | Ty::Function(fn_ptr) => { | 372 | TyKind::Function(fn_ptr) => { |
362 | let sig = CallableSig::from_fn_ptr(fn_ptr); | 373 | let sig = CallableSig::from_fn_ptr(fn_ptr); |
363 | sig.hir_fmt(f)?; | 374 | sig.hir_fmt(f)?; |
364 | } | 375 | } |
365 | Ty::FnDef(def, parameters) => { | 376 | TyKind::FnDef(def, parameters) => { |
366 | let def = *def; | 377 | let def = from_chalk(f.db, *def); |
367 | let sig = f.db.callable_item_signature(def).subst(parameters); | 378 | let sig = f.db.callable_item_signature(def).subst(parameters); |
368 | match def { | 379 | match def { |
369 | CallableDefId::FunctionId(ff) => { | 380 | CallableDefId::FunctionId(ff) => { |
@@ -401,7 +412,7 @@ impl HirDisplay for Ty { | |||
401 | write!(f, " -> {}", ret_display)?; | 412 | write!(f, " -> {}", ret_display)?; |
402 | } | 413 | } |
403 | } | 414 | } |
404 | Ty::Adt(AdtId(def_id), parameters) => { | 415 | TyKind::Adt(AdtId(def_id), parameters) => { |
405 | match f.display_target { | 416 | match f.display_target { |
406 | DisplayTarget::Diagnostics | DisplayTarget::Test => { | 417 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
407 | let name = match *def_id { | 418 | let name = match *def_id { |
@@ -427,37 +438,39 @@ impl HirDisplay for Ty { | |||
427 | } | 438 | } |
428 | 439 | ||
429 | if parameters.len() > 0 { | 440 | if parameters.len() > 0 { |
430 | let parameters_to_write = | 441 | let parameters_to_write = if f.display_target.is_source_code() |
431 | if f.display_target.is_source_code() || f.omit_verbose_types() { | 442 | || f.omit_verbose_types() |
432 | match self | 443 | { |
433 | .as_generic_def() | 444 | match self |
434 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 445 | .as_generic_def(f.db) |
435 | .filter(|defaults| !defaults.is_empty()) | 446 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
436 | { | 447 | .filter(|defaults| !defaults.is_empty()) |
437 | None => parameters.0.as_ref(), | 448 | { |
438 | Some(default_parameters) => { | 449 | None => parameters.0.as_ref(), |
439 | let mut default_from = 0; | 450 | Some(default_parameters) => { |
440 | for (i, parameter) in parameters.iter().enumerate() { | 451 | let mut default_from = 0; |
441 | match (parameter, default_parameters.get(i)) { | 452 | for (i, parameter) in parameters.iter().enumerate() { |
442 | (&Ty::Unknown, _) | (_, None) => { | 453 | match (parameter.interned(&Interner), default_parameters.get(i)) |
454 | { | ||
455 | (&TyKind::Unknown, _) | (_, None) => { | ||
456 | default_from = i + 1; | ||
457 | } | ||
458 | (_, Some(default_parameter)) => { | ||
459 | let actual_default = default_parameter | ||
460 | .clone() | ||
461 | .subst(¶meters.prefix(i)); | ||
462 | if parameter != &actual_default { | ||
443 | default_from = i + 1; | 463 | default_from = i + 1; |
444 | } | 464 | } |
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 | } | 465 | } |
454 | } | 466 | } |
455 | ¶meters.0[0..default_from] | ||
456 | } | 467 | } |
468 | ¶meters.0[0..default_from] | ||
457 | } | 469 | } |
458 | } else { | 470 | } |
459 | parameters.0.as_ref() | 471 | } else { |
460 | }; | 472 | parameters.0.as_ref() |
473 | }; | ||
461 | if !parameters_to_write.is_empty() { | 474 | if !parameters_to_write.is_empty() { |
462 | write!(f, "<")?; | 475 | write!(f, "<")?; |
463 | f.write_joined(parameters_to_write, ", ")?; | 476 | f.write_joined(parameters_to_write, ", ")?; |
@@ -465,13 +478,14 @@ impl HirDisplay for Ty { | |||
465 | } | 478 | } |
466 | } | 479 | } |
467 | } | 480 | } |
468 | Ty::AssociatedType(type_alias, parameters) => { | 481 | TyKind::AssociatedType(assoc_type_id, parameters) => { |
482 | let type_alias = from_assoc_type_id(*assoc_type_id); | ||
469 | let trait_ = match type_alias.lookup(f.db.upcast()).container { | 483 | let trait_ = match type_alias.lookup(f.db.upcast()).container { |
470 | AssocContainerId::TraitId(it) => it, | 484 | AssocContainerId::TraitId(it) => it, |
471 | _ => panic!("not an associated type"), | 485 | _ => panic!("not an associated type"), |
472 | }; | 486 | }; |
473 | let trait_ = f.db.trait_data(trait_); | 487 | let trait_ = f.db.trait_data(trait_); |
474 | let type_alias_data = f.db.type_alias_data(*type_alias); | 488 | let type_alias_data = f.db.type_alias_data(type_alias); |
475 | 489 | ||
476 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) | 490 | // 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() { | 491 | if f.display_target.is_test() { |
@@ -482,19 +496,22 @@ impl HirDisplay for Ty { | |||
482 | write!(f, ">")?; | 496 | write!(f, ">")?; |
483 | } | 497 | } |
484 | } else { | 498 | } else { |
485 | let projection_ty = | 499 | let projection_ty = ProjectionTy { |
486 | ProjectionTy { associated_ty: *type_alias, parameters: parameters.clone() }; | 500 | associated_ty_id: to_assoc_type_id(type_alias), |
501 | substitution: parameters.clone(), | ||
502 | }; | ||
487 | 503 | ||
488 | projection_ty.hir_fmt(f)?; | 504 | projection_ty.hir_fmt(f)?; |
489 | } | 505 | } |
490 | } | 506 | } |
491 | Ty::ForeignType(type_alias) => { | 507 | TyKind::ForeignType(type_alias) => { |
492 | let type_alias = f.db.type_alias_data(*type_alias); | 508 | let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias)); |
493 | write!(f, "{}", type_alias.name)?; | 509 | write!(f, "{}", type_alias.name)?; |
494 | } | 510 | } |
495 | Ty::OpaqueType(opaque_ty_id, parameters) => { | 511 | TyKind::OpaqueType(opaque_ty_id, parameters) => { |
496 | match opaque_ty_id { | 512 | let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into()); |
497 | &OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 513 | match impl_trait_id { |
514 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||
498 | let datas = | 515 | let datas = |
499 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 516 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
500 | let data = (*datas) | 517 | let data = (*datas) |
@@ -504,14 +521,14 @@ impl HirDisplay for Ty { | |||
504 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 521 | 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 | 522 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution |
506 | } | 523 | } |
507 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 524 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { |
508 | write!(f, "impl Future<Output = ")?; | 525 | write!(f, "impl Future<Output = ")?; |
509 | parameters[0].hir_fmt(f)?; | 526 | parameters[0].hir_fmt(f)?; |
510 | write!(f, ">")?; | 527 | write!(f, ">")?; |
511 | } | 528 | } |
512 | } | 529 | } |
513 | } | 530 | } |
514 | Ty::Closure(.., substs) => { | 531 | TyKind::Closure(.., substs) => { |
515 | let sig = substs[0].callable_sig(f.db); | 532 | let sig = substs[0].callable_sig(f.db); |
516 | if let Some(sig) = sig { | 533 | if let Some(sig) = sig { |
517 | if sig.params().is_empty() { | 534 | if sig.params().is_empty() { |
@@ -535,7 +552,8 @@ impl HirDisplay for Ty { | |||
535 | write!(f, "{{closure}}")?; | 552 | write!(f, "{{closure}}")?; |
536 | } | 553 | } |
537 | } | 554 | } |
538 | Ty::Placeholder(id) => { | 555 | TyKind::Placeholder(idx) => { |
556 | let id = from_placeholder_idx(f.db, *idx); | ||
539 | let generics = generics(f.db.upcast(), id.parent); | 557 | let generics = generics(f.db.upcast(), id.parent); |
540 | let param_data = &generics.params.types[id.local_id]; | 558 | let param_data = &generics.params.types[id.local_id]; |
541 | match param_data.provenance { | 559 | match param_data.provenance { |
@@ -543,8 +561,8 @@ impl HirDisplay for Ty { | |||
543 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 561 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
544 | } | 562 | } |
545 | TypeParamProvenance::ArgumentImplTrait => { | 563 | TypeParamProvenance::ArgumentImplTrait => { |
546 | let bounds = f.db.generic_predicates_for_param(*id); | 564 | let bounds = f.db.generic_predicates_for_param(id); |
547 | let substs = Substs::type_params_for_generics(&generics); | 565 | let substs = Substs::type_params_for_generics(f.db, &generics); |
548 | write_bounds_like_dyn_trait_with_prefix( | 566 | write_bounds_like_dyn_trait_with_prefix( |
549 | "impl", | 567 | "impl", |
550 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 568 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), |
@@ -553,28 +571,29 @@ impl HirDisplay for Ty { | |||
553 | } | 571 | } |
554 | } | 572 | } |
555 | } | 573 | } |
556 | Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 574 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
557 | Ty::Dyn(predicates) => { | 575 | TyKind::Dyn(predicates) => { |
558 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 576 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; |
559 | } | 577 | } |
560 | Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 578 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
561 | Ty::Alias(AliasTy::Opaque(opaque_ty)) => { | 579 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
562 | match opaque_ty.opaque_ty_id { | 580 | let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()); |
563 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 581 | match impl_trait_id { |
582 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | ||
564 | let datas = | 583 | let datas = |
565 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 584 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
566 | let data = (*datas) | 585 | let data = (*datas) |
567 | .as_ref() | 586 | .as_ref() |
568 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 587 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
569 | let bounds = data.subst(&opaque_ty.parameters); | 588 | let bounds = data.subst(&opaque_ty.substitution); |
570 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; | 589 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; |
571 | } | 590 | } |
572 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | 591 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { |
573 | write!(f, "{{async block}}")?; | 592 | write!(f, "{{async block}}")?; |
574 | } | 593 | } |
575 | }; | 594 | }; |
576 | } | 595 | } |
577 | Ty::Unknown => { | 596 | TyKind::Unknown => { |
578 | if f.display_target.is_source_code() { | 597 | if f.display_target.is_source_code() { |
579 | return Err(HirDisplayError::DisplaySourceCodeError( | 598 | return Err(HirDisplayError::DisplaySourceCodeError( |
580 | DisplaySourceCodeError::UnknownType, | 599 | DisplaySourceCodeError::UnknownType, |
@@ -582,7 +601,7 @@ impl HirDisplay for Ty { | |||
582 | } | 601 | } |
583 | write!(f, "{{unknown}}")?; | 602 | write!(f, "{{unknown}}")?; |
584 | } | 603 | } |
585 | Ty::InferenceVar(..) => write!(f, "_")?, | 604 | TyKind::InferenceVar(..) => write!(f, "_")?, |
586 | } | 605 | } |
587 | Ok(()) | 606 | Ok(()) |
588 | } | 607 | } |
@@ -695,7 +714,9 @@ fn write_bounds_like_dyn_trait( | |||
695 | write!(f, "<")?; | 714 | write!(f, "<")?; |
696 | angle_open = true; | 715 | angle_open = true; |
697 | } | 716 | } |
698 | let type_alias = f.db.type_alias_data(projection_pred.projection_ty.associated_ty); | 717 | let type_alias = f.db.type_alias_data(from_assoc_type_id( |
718 | projection_pred.projection_ty.associated_ty_id, | ||
719 | )); | ||
699 | write!(f, "{} = ", type_alias.name)?; | 720 | write!(f, "{} = ", type_alias.name)?; |
700 | projection_pred.ty.hir_fmt(f)?; | 721 | projection_pred.ty.hir_fmt(f)?; |
701 | } | 722 | } |
@@ -746,12 +767,6 @@ impl HirDisplay for TraitRef { | |||
746 | } | 767 | } |
747 | } | 768 | } |
748 | 769 | ||
749 | impl HirDisplay for &GenericPredicate { | ||
750 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
751 | HirDisplay::hir_fmt(*self, f) | ||
752 | } | ||
753 | } | ||
754 | |||
755 | impl HirDisplay for GenericPredicate { | 770 | impl HirDisplay for GenericPredicate { |
756 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 771 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
757 | if f.should_truncate() { | 772 | if f.should_truncate() { |
@@ -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_id | ||
786 | )) | ||
787 | .name, | ||
770 | )?; | 788 | )?; |
771 | projection_pred.ty.hir_fmt(f)?; | 789 | projection_pred.ty.hir_fmt(f)?; |
772 | } | 790 | } |
@@ -807,3 +825,190 @@ impl HirDisplay for Obligation { | |||
807 | } | 825 | } |
808 | } | 826 | } |
809 | } | 827 | } |
828 | |||
829 | pub fn write_visibility( | ||
830 | module_id: ModuleId, | ||
831 | vis: Visibility, | ||
832 | f: &mut HirFormatter, | ||
833 | ) -> Result<(), HirDisplayError> { | ||
834 | match vis { | ||
835 | Visibility::Public => write!(f, "pub "), | ||
836 | Visibility::Module(vis_id) => { | ||
837 | let def_map = module_id.def_map(f.db.upcast()); | ||
838 | let root_module_id = def_map.module_id(def_map.root()); | ||
839 | if vis_id == module_id { | ||
840 | // pub(self) or omitted | ||
841 | Ok(()) | ||
842 | } else if root_module_id == vis_id { | ||
843 | write!(f, "pub(crate) ") | ||
844 | } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) { | ||
845 | write!(f, "pub(super) ") | ||
846 | } else { | ||
847 | write!(f, "pub(in ...) ") | ||
848 | } | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | |||
853 | impl HirDisplay for TypeRef { | ||
854 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
855 | match self { | ||
856 | TypeRef::Never => write!(f, "!")?, | ||
857 | TypeRef::Placeholder => write!(f, "_")?, | ||
858 | TypeRef::Tuple(elems) => { | ||
859 | write!(f, "(")?; | ||
860 | f.write_joined(elems, ", ")?; | ||
861 | if elems.len() == 1 { | ||
862 | write!(f, ",")?; | ||
863 | } | ||
864 | write!(f, ")")?; | ||
865 | } | ||
866 | TypeRef::Path(path) => path.hir_fmt(f)?, | ||
867 | TypeRef::RawPtr(inner, mutability) => { | ||
868 | let mutability = match mutability { | ||
869 | hir_def::type_ref::Mutability::Shared => "*const ", | ||
870 | hir_def::type_ref::Mutability::Mut => "*mut ", | ||
871 | }; | ||
872 | write!(f, "{}", mutability)?; | ||
873 | inner.hir_fmt(f)?; | ||
874 | } | ||
875 | TypeRef::Reference(inner, lifetime, mutability) => { | ||
876 | let mutability = match mutability { | ||
877 | hir_def::type_ref::Mutability::Shared => "", | ||
878 | hir_def::type_ref::Mutability::Mut => "mut ", | ||
879 | }; | ||
880 | write!(f, "&")?; | ||
881 | if let Some(lifetime) = lifetime { | ||
882 | write!(f, "{} ", lifetime.name)?; | ||
883 | } | ||
884 | write!(f, "{}", mutability)?; | ||
885 | inner.hir_fmt(f)?; | ||
886 | } | ||
887 | TypeRef::Array(inner) => { | ||
888 | write!(f, "[")?; | ||
889 | inner.hir_fmt(f)?; | ||
890 | // FIXME: Array length? | ||
891 | write!(f, "; _]")?; | ||
892 | } | ||
893 | TypeRef::Slice(inner) => { | ||
894 | write!(f, "[")?; | ||
895 | inner.hir_fmt(f)?; | ||
896 | write!(f, "]")?; | ||
897 | } | ||
898 | TypeRef::Fn(tys, is_varargs) => { | ||
899 | // FIXME: Function pointer qualifiers. | ||
900 | write!(f, "fn(")?; | ||
901 | f.write_joined(&tys[..tys.len() - 1], ", ")?; | ||
902 | if *is_varargs { | ||
903 | write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?; | ||
904 | } | ||
905 | write!(f, ")")?; | ||
906 | let ret_ty = tys.last().unwrap(); | ||
907 | match ret_ty { | ||
908 | TypeRef::Tuple(tup) if tup.is_empty() => {} | ||
909 | _ => { | ||
910 | write!(f, " -> ")?; | ||
911 | ret_ty.hir_fmt(f)?; | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | TypeRef::ImplTrait(bounds) => { | ||
916 | write!(f, "impl ")?; | ||
917 | f.write_joined(bounds, " + ")?; | ||
918 | } | ||
919 | TypeRef::DynTrait(bounds) => { | ||
920 | write!(f, "dyn ")?; | ||
921 | f.write_joined(bounds, " + ")?; | ||
922 | } | ||
923 | TypeRef::Error => write!(f, "{{error}}")?, | ||
924 | } | ||
925 | Ok(()) | ||
926 | } | ||
927 | } | ||
928 | |||
929 | impl HirDisplay for TypeBound { | ||
930 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
931 | match self { | ||
932 | TypeBound::Path(path) => path.hir_fmt(f), | ||
933 | TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name), | ||
934 | TypeBound::Error => write!(f, "{{error}}"), | ||
935 | } | ||
936 | } | ||
937 | } | ||
938 | |||
939 | impl HirDisplay for Path { | ||
940 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
941 | match (self.type_anchor(), self.kind()) { | ||
942 | (Some(anchor), _) => { | ||
943 | write!(f, "<")?; | ||
944 | anchor.hir_fmt(f)?; | ||
945 | write!(f, ">")?; | ||
946 | } | ||
947 | (_, PathKind::Plain) => {} | ||
948 | (_, PathKind::Abs) => write!(f, "::")?, | ||
949 | (_, PathKind::Crate) => write!(f, "crate")?, | ||
950 | (_, PathKind::Super(0)) => write!(f, "self")?, | ||
951 | (_, PathKind::Super(n)) => { | ||
952 | write!(f, "super")?; | ||
953 | for _ in 0..*n { | ||
954 | write!(f, "::super")?; | ||
955 | } | ||
956 | } | ||
957 | (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?, | ||
958 | } | ||
959 | |||
960 | for (seg_idx, segment) in self.segments().iter().enumerate() { | ||
961 | if seg_idx != 0 { | ||
962 | write!(f, "::")?; | ||
963 | } | ||
964 | write!(f, "{}", segment.name)?; | ||
965 | if let Some(generic_args) = segment.args_and_bindings { | ||
966 | // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`. | ||
967 | // Do we actually format expressions? | ||
968 | write!(f, "<")?; | ||
969 | let mut first = true; | ||
970 | for arg in &generic_args.args { | ||
971 | if first { | ||
972 | first = false; | ||
973 | if generic_args.has_self_type { | ||
974 | // FIXME: Convert to `<Ty as Trait>` form. | ||
975 | write!(f, "Self = ")?; | ||
976 | } | ||
977 | } else { | ||
978 | write!(f, ", ")?; | ||
979 | } | ||
980 | arg.hir_fmt(f)?; | ||
981 | } | ||
982 | for binding in &generic_args.bindings { | ||
983 | if first { | ||
984 | first = false; | ||
985 | } else { | ||
986 | write!(f, ", ")?; | ||
987 | } | ||
988 | write!(f, "{}", binding.name)?; | ||
989 | match &binding.type_ref { | ||
990 | Some(ty) => { | ||
991 | write!(f, " = ")?; | ||
992 | ty.hir_fmt(f)? | ||
993 | } | ||
994 | None => { | ||
995 | write!(f, ": ")?; | ||
996 | f.write_joined(&binding.bounds, " + ")?; | ||
997 | } | ||
998 | } | ||
999 | } | ||
1000 | write!(f, ">")?; | ||
1001 | } | ||
1002 | } | ||
1003 | Ok(()) | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | impl HirDisplay for GenericArg { | ||
1008 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
1009 | match self { | ||
1010 | GenericArg::Type(ty) => ty.hir_fmt(f), | ||
1011 | GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), | ||
1012 | } | ||
1013 | } | ||
1014 | } | ||