1 //! Display and pretty printing routines.
3 use std::fmt::{self, Write};
5 use hir_expand::mod_path::PathKind;
6 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 {
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) => {
147 let ((_, return_type), args) =
148 args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
150 for (i, (_, typeref)) in args.iter().enumerate() {
154 print_type_ref(typeref, buf)?;
157 if !args.is_empty() {
162 write!(buf, ") -> ")?;
163 print_type_ref(return_type, buf)?;
165 TypeRef::Macro(_ast_id) => {
166 write!(buf, "<macro>")?;
168 TypeRef::Error => write!(buf, "{{unknown}}")?,
169 TypeRef::ImplTrait(bounds) => {
170 write!(buf, "impl ")?;
171 print_type_bounds(bounds, buf)?;
173 TypeRef::DynTrait(bounds) => {
174 write!(buf, "dyn ")?;
175 print_type_bounds(bounds, buf)?;
182 pub(crate) fn print_type_bounds(
183 bounds: &[Interned<TypeBound>],
186 for (i, bound) in bounds.iter().enumerate() {
191 match bound.as_ref() {
192 TypeBound::Path(path, modifier) => {
194 TraitBoundModifier::None => (),
195 TraitBoundModifier::Maybe => write!(buf, "?")?,
197 print_path(path, buf)?;
199 TypeBound::ForLifetime(lifetimes, path) => {
200 write!(buf, "for<{}> ", lifetimes.iter().format(", "))?;
201 print_path(path, buf)?;
203 TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name)?,
204 TypeBound::Error => write!(buf, "{{unknown}}")?,