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