1 //! Display and pretty printing routines.
3 use std
::fmt
::{self, Write}
;
5 use hir_expand
::mod_path
::PathKind
;
7 use itertools
::Itertools
;
10 path
::{GenericArg, GenericArgs, Path}
,
11 type_ref
::{Mutability, TraitBoundModifier, TypeBound, TypeRef}
,
14 pub(crate) fn print_path(path
: &Path
, buf
: &mut dyn Write
) -> fmt
::Result
{
15 match path
.type_anchor() {
18 print_type_ref(anchor
, buf
)?
;
21 None
=> match path
.kind() {
23 PathKind
::Super(0) => write
!(buf
, "self")?
,
24 PathKind
::Super(n
) => {
27 buf
.write_str("super")?
;
29 buf
.write_str("::super")?
;
33 PathKind
::Crate
=> write
!(buf
, "crate")?
,
35 PathKind
::DollarCrate(_
) => write
!(buf
, "$crate")?
,
39 for (i
, segment
) in path
.segments().iter().enumerate() {
40 if i
!= 0 || !matches
!(path
.kind(), PathKind
::Plain
) {
44 write
!(buf
, "{}", segment
.name
)?
;
45 if let Some(generics
) = segment
.args_and_bindings
{
47 print_generic_args(generics
, buf
)?
;
56 pub(crate) fn print_generic_args(generics
: &GenericArgs
, buf
: &mut dyn Write
) -> fmt
::Result
{
58 let args
= if generics
.has_self_type
{
59 let (self_ty
, args
) = generics
.args
.split_first().unwrap();
60 write
!(buf
, "Self=")?
;
61 print_generic_arg(self_ty
, buf
)?
;
72 print_generic_arg(arg
, buf
)?
;
74 for binding
in generics
.bindings
.iter() {
79 write
!(buf
, "{}", binding
.name
)?
;
80 if !binding
.bounds
.is_empty() {
82 print_type_bounds(&binding
.bounds
, buf
)?
;
84 if let Some(ty
) = &binding
.type_ref
{
86 print_type_ref(ty
, buf
)?
;
92 pub(crate) fn print_generic_arg(arg
: &GenericArg
, buf
: &mut dyn Write
) -> fmt
::Result
{
94 GenericArg
::Type(ty
) => print_type_ref(ty
, buf
),
95 GenericArg
::Const(c
) => write
!(buf
, "{c}"),
96 GenericArg
::Lifetime(lt
) => write
!(buf
, "{}", lt
.name
),
100 pub(crate) fn print_type_ref(type_ref
: &TypeRef
, buf
: &mut dyn Write
) -> fmt
::Result
{
101 // FIXME: deduplicate with `HirDisplay` impl
103 TypeRef
::Never
=> write
!(buf
, "!")?
,
104 TypeRef
::Placeholder
=> write
!(buf
, "_")?
,
105 TypeRef
::Tuple(fields
) => {
107 for (i
, field
) in fields
.iter().enumerate() {
111 print_type_ref(field
, buf
)?
;
115 TypeRef
::Path(path
) => print_path(path
, buf
)?
,
116 TypeRef
::RawPtr(pointee
, mtbl
) => {
117 let mtbl
= match mtbl
{
118 Mutability
::Shared
=> "*const",
119 Mutability
::Mut
=> "*mut",
121 write
!(buf
, "{mtbl} ")?
;
122 print_type_ref(pointee
, buf
)?
;
124 TypeRef
::Reference(pointee
, lt
, mtbl
) => {
125 let mtbl
= match mtbl
{
126 Mutability
::Shared
=> "",
127 Mutability
::Mut
=> "mut ",
130 if let Some(lt
) = lt
{
131 write
!(buf
, "{} ", lt
.name
)?
;
133 write
!(buf
, "{mtbl}")?
;
134 print_type_ref(pointee
, buf
)?
;
136 TypeRef
::Array(elem
, len
) => {
138 print_type_ref(elem
, buf
)?
;
139 write
!(buf
, "; {len}]")?
;
141 TypeRef
::Slice(elem
) => {
143 print_type_ref(elem
, buf
)?
;
146 TypeRef
::Fn(args_and_ret
, varargs
, is_unsafe
) => {
147 let ((_
, return_type
), args
) =
148 args_and_ret
.split_last().expect("TypeRef::Fn is missing return type");
150 write
!(buf
, "unsafe ")?
;
153 for (i
, (_
, typeref
)) in args
.iter().enumerate() {
157 print_type_ref(typeref
, buf
)?
;
160 if !args
.is_empty() {
165 write
!(buf
, ") -> ")?
;
166 print_type_ref(return_type
, buf
)?
;
168 TypeRef
::Macro(_ast_id
) => {
169 write
!(buf
, "<macro>")?
;
171 TypeRef
::Error
=> write
!(buf
, "{{unknown}}")?
,
172 TypeRef
::ImplTrait(bounds
) => {
173 write
!(buf
, "impl ")?
;
174 print_type_bounds(bounds
, buf
)?
;
176 TypeRef
::DynTrait(bounds
) => {
177 write
!(buf
, "dyn ")?
;
178 print_type_bounds(bounds
, buf
)?
;
185 pub(crate) fn print_type_bounds(
186 bounds
: &[Interned
<TypeBound
>],
189 for (i
, bound
) in bounds
.iter().enumerate() {
194 match bound
.as_ref() {
195 TypeBound
::Path(path
, modifier
) => {
197 TraitBoundModifier
::None
=> (),
198 TraitBoundModifier
::Maybe
=> write
!(buf
, "?")?
,
200 print_path(path
, buf
)?
;
202 TypeBound
::ForLifetime(lifetimes
, path
) => {
203 write
!(buf
, "for<{}> ", lifetimes
.iter().format(", "))?
;
204 print_path(path
, buf
)?
;
206 TypeBound
::Lifetime(lt
) => write
!(buf
, "{}", lt
.name
)?
,
207 TypeBound
::Error
=> write
!(buf
, "{{unknown}}")?
,