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.rs237
1 files changed, 122 insertions, 115 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index d2f1b4014..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 {
240 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
241 if f.should_truncate() {
242 return write!(f, "{}", TYPE_HINT_TRUNCATION);
243 }
244
245 let trait_ = f.db.trait_data(self.trait_(f.db));
246 let first_parameter = self.parameters[0].into_displayable(
247 f.db,
248 f.max_size,
249 f.omit_verbose_types,
250 f.display_target,
251 );
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 {
238 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 264 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
239 if f.should_truncate() { 265 if f.should_truncate() {
240 return write!(f, "{}", TYPE_HINT_TRUNCATION); 266 return write!(f, "{}", TYPE_HINT_TRUNCATION);
241 } 267 }
242 268
243 match self.ctor { 269 match self {
244 TypeCtor::Bool => write!(f, "bool")?, 270 Ty::Never => write!(f, "!")?,
245 TypeCtor::Char => write!(f, "char")?, 271 Ty::Str => write!(f, "str")?,
246 TypeCtor::Int(t) => write!(f, "{}", t)?, 272 Ty::Scalar(Scalar::Bool) => write!(f, "bool")?,
247 TypeCtor::Float(t) => write!(f, "{}", t)?, 273 Ty::Scalar(Scalar::Char) => write!(f, "char")?,
248 TypeCtor::Str => write!(f, "str")?, 274 &Ty::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
249 TypeCtor::Slice => { 275 &Ty::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
250 let t = self.parameters.as_single(); 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,62 +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!(f, "impl ")?; 503 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
471 write_bounds_like_dyn_trait(&bounds.value, f)?;
472 // 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
473 } 505 }
474 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 506 OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
475 write!(f, "impl Future<Output = ")?; 507 write!(f, "impl Future<Output = ")?;
476 self.parameters[0].hir_fmt(f)?; 508 parameters[0].hir_fmt(f)?;
477 write!(f, ">")?; 509 write!(f, ">")?;
478 } 510 }
479 } 511 }
480 } 512 }
481 TypeCtor::Closure { .. } => { 513 Ty::Closure(.., substs) => {
482 let sig = self.parameters[0].callable_sig(f.db); 514 let sig = substs[0].callable_sig(f.db);
483 if let Some(sig) = sig { 515 if let Some(sig) = sig {
484 if sig.params().is_empty() { 516 if sig.params().is_empty() {
485 write!(f, "||")?; 517 write!(f, "||")?;
@@ -502,44 +534,6 @@ impl HirDisplay for ApplicationTy {
502 write!(f, "{{closure}}")?; 534 write!(f, "{{closure}}")?;
503 } 535 }
504 } 536 }
505 }
506 Ok(())
507 }
508}
509
510impl HirDisplay for ProjectionTy {
511 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
512 if f.should_truncate() {
513 return write!(f, "{}", TYPE_HINT_TRUNCATION);
514 }
515
516 let trait_ = f.db.trait_data(self.trait_(f.db));
517 let first_parameter = self.parameters[0].into_displayable(
518 f.db,
519 f.max_size,
520 f.omit_verbose_types,
521 f.display_target,
522 );
523 write!(f, "<{} as {}", first_parameter, trait_.name)?;
524 if self.parameters.len() > 1 {
525 write!(f, "<")?;
526 f.write_joined(&self.parameters[1..], ", ")?;
527 write!(f, ">")?;
528 }
529 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
530 Ok(())
531 }
532}
533
534impl HirDisplay for Ty {
535 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
536 if f.should_truncate() {
537 return write!(f, "{}", TYPE_HINT_TRUNCATION);
538 }
539
540 match self {
541 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
542 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
543 Ty::Placeholder(id) => { 537 Ty::Placeholder(id) => {
544 let generics = generics(f.db.upcast(), id.parent); 538 let generics = generics(f.db.upcast(), id.parent);
545 let param_data = &generics.params.types[id.local_id]; 539 let param_data = &generics.params.types[id.local_id];
@@ -548,22 +542,22 @@ impl HirDisplay for Ty {
548 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 542 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
549 } 543 }
550 TypeParamProvenance::ArgumentImplTrait => { 544 TypeParamProvenance::ArgumentImplTrait => {
551 write!(f, "impl ")?;
552 let bounds = f.db.generic_predicates_for_param(*id); 545 let bounds = f.db.generic_predicates_for_param(*id);
553 let substs = Substs::type_params_for_generics(&generics); 546 let substs = Substs::type_params_for_generics(&generics);
554 write_bounds_like_dyn_trait( 547 write_bounds_like_dyn_trait_with_prefix(
548 "impl",
555 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), 549 &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
556 f, 550 f,
557 )?; 551 )?;
558 } 552 }
559 } 553 }
560 } 554 }
561 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 555 Ty::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
562 Ty::Dyn(predicates) => { 556 Ty::Dyn(predicates) => {
563 write!(f, "dyn ")?; 557 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?;
564 write_bounds_like_dyn_trait(predicates, f)?;
565 } 558 }
566 Ty::Opaque(opaque_ty) => { 559 Ty::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
560 Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
567 match opaque_ty.opaque_ty_id { 561 match opaque_ty.opaque_ty_id {
568 OpaqueTyId::ReturnTypeImplTrait(func, idx) => { 562 OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
569 let datas = 563 let datas =
@@ -572,8 +566,7 @@ impl HirDisplay for Ty {
572 .as_ref() 566 .as_ref()
573 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 567 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
574 let bounds = data.subst(&opaque_ty.parameters); 568 let bounds = data.subst(&opaque_ty.parameters);
575 write!(f, "impl ")?; 569 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?;
576 write_bounds_like_dyn_trait(&bounds.value, f)?;
577 } 570 }
578 OpaqueTyId::AsyncBlockTypeImplTrait(..) => { 571 OpaqueTyId::AsyncBlockTypeImplTrait(..) => {
579 write!(f, "{{async block}}")?; 572 write!(f, "{{async block}}")?;
@@ -588,13 +581,13 @@ impl HirDisplay for Ty {
588 } 581 }
589 write!(f, "{{unknown}}")?; 582 write!(f, "{{unknown}}")?;
590 } 583 }
591 Ty::Infer(..) => write!(f, "_")?, 584 Ty::InferenceVar(..) => write!(f, "_")?,
592 } 585 }
593 Ok(()) 586 Ok(())
594 } 587 }
595} 588}
596 589
597impl HirDisplay for FnSig { 590impl HirDisplay for CallableSig {
598 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 591 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
599 write!(f, "fn(")?; 592 write!(f, "fn(")?;
600 f.write_joined(self.params(), ", ")?; 593 f.write_joined(self.params(), ", ")?;
@@ -617,7 +610,7 @@ impl HirDisplay for FnSig {
617} 610}
618 611
619fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> { 612fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
620 let krate = trait_.lookup(db).container.module(db).krate; 613 let krate = trait_.lookup(db).container.module(db).krate();
621 let fn_traits = [ 614 let fn_traits = [
622 db.lang_item(krate, "fn".into()), 615 db.lang_item(krate, "fn".into()),
623 db.lang_item(krate, "fn_mut".into()), 616 db.lang_item(krate, "fn_mut".into()),
@@ -627,7 +620,21 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
627 ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait()) 620 ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
628} 621}
629 622
630pub fn write_bounds_like_dyn_trait( 623pub fn write_bounds_like_dyn_trait_with_prefix(
624 prefix: &str,
625 predicates: &[GenericPredicate],
626 f: &mut HirFormatter,
627) -> Result<(), HirDisplayError> {
628 write!(f, "{}", prefix)?;
629 if !predicates.is_empty() {
630 write!(f, " ")?;
631 write_bounds_like_dyn_trait(predicates, f)
632 } else {
633 Ok(())
634 }
635}
636
637fn write_bounds_like_dyn_trait(
631 predicates: &[GenericPredicate], 638 predicates: &[GenericPredicate],
632 f: &mut HirFormatter, 639 f: &mut HirFormatter,
633) -> Result<(), HirDisplayError> { 640) -> Result<(), HirDisplayError> {