1 //! HTML formatting module
3 //! This module contains a large number of `fmt::Display` implementations for
4 //! various types in `rustdoc::clean`. These implementations all currently
5 //! assume that HTML output is desired, although it may be possible to redesign
6 //! them in the future to instead emit any format desired.
11 use rustc
::hir
::def_id
::DefId
;
12 use rustc_target
::spec
::abi
::Abi
;
15 use crate::clean
::{self, PrimitiveType}
;
16 use crate::core
::DocAccessLevels
;
17 use crate::html
::item_type
::ItemType
;
18 use crate::html
::render
::{self, cache, CURRENT_LOCATION_KEY}
;
21 /// Helper to render an optional visibility with a space after it (if the
22 /// visibility is preset)
23 #[derive(Copy, Clone)]
24 pub struct VisSpace
<'a
>(pub &'a Option
<clean
::Visibility
>);
25 /// Similarly to VisSpace, this structure is used to render a function style with a
27 #[derive(Copy, Clone)]
28 pub struct UnsafetySpace(pub hir
::Unsafety
);
29 /// Similarly to VisSpace, this structure is used to render a function constness
30 /// with a space after it.
31 #[derive(Copy, Clone)]
32 pub struct ConstnessSpace(pub hir
::Constness
);
33 /// Similarly to VisSpace, this structure is used to render a function asyncness
34 /// with a space after it.
35 #[derive(Copy, Clone)]
36 pub struct AsyncSpace(pub hir
::IsAsync
);
37 /// Similar to VisSpace, but used for mutability
38 #[derive(Copy, Clone)]
39 pub struct MutableSpace(pub clean
::Mutability
);
40 /// Similar to VisSpace, but used for mutability
41 #[derive(Copy, Clone)]
42 pub struct RawMutableSpace(pub clean
::Mutability
);
43 /// Wrapper struct for emitting type parameter bounds.
44 pub struct GenericBounds
<'a
>(pub &'a
[clean
::GenericBound
]);
45 /// Wrapper struct for emitting a comma-separated list of items
46 pub struct CommaSep
<'a
, T
>(pub &'a
[T
]);
47 pub struct AbiSpace(pub Abi
);
49 /// Wrapper struct for properly emitting a function or method declaration.
50 pub struct Function
<'a
> {
51 /// The declaration to emit.
52 pub decl
: &'a clean
::FnDecl
,
53 /// The length of the function header and name. In other words, the number of characters in the
54 /// function declaration up to but not including the parentheses.
56 /// Used to determine line-wrapping.
57 pub header_len
: usize,
58 /// The number of spaces to indent each successive line with, if line-wrapping is necessary.
60 /// Whether the function is async or not.
61 pub asyncness
: hir
::IsAsync
,
64 /// Wrapper struct for emitting a where-clause from Generics.
65 pub struct WhereClause
<'a
>{
66 /// The Generics from which to emit a where-clause.
67 pub gens
: &'a clean
::Generics
,
68 /// The number of spaces to indent each line with.
70 /// Whether the where-clause needs to add a comma and newline after the last bound.
71 pub end_newline
: bool
,
79 impl<'a
> VisSpace
<'a
> {
80 pub fn get(self) -> &'a Option
<clean
::Visibility
> {
81 let VisSpace(v
) = self; v
86 pub fn get(&self) -> hir
::Unsafety
{
87 let UnsafetySpace(v
) = *self; v
92 pub fn get(&self) -> hir
::Constness
{
93 let ConstnessSpace(v
) = *self; v
97 impl<'a
, T
: fmt
::Display
> fmt
::Display
for CommaSep
<'a
, T
> {
98 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
99 for (i
, item
) in self.0.iter
().enumerate() {
100 if i
!= 0 { write!(f, ", ")?; }
101 fmt
::Display
::fmt(item
, f
)?
;
107 impl<'a
> fmt
::Display
for GenericBounds
<'a
> {
108 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
109 let &GenericBounds(bounds
) = self;
110 for (i
, bound
) in bounds
.iter().enumerate() {
114 fmt
::Display
::fmt(bound
, f
)?
;
120 impl fmt
::Display
for clean
::GenericParamDef
{
121 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
123 clean
::GenericParamDefKind
::Lifetime
=> write
!(f
, "{}", self.name
),
124 clean
::GenericParamDefKind
::Type { ref bounds, ref default, .. }
=> {
125 f
.write_str(&self.name
)?
;
127 if !bounds
.is_empty() {
129 write
!(f
, ": {:#}", GenericBounds(bounds
))?
;
131 write
!(f
, ": {}", GenericBounds(bounds
))?
;
135 if let Some(ref ty
) = default {
137 write
!(f
, " = {:#}", ty
)?
;
139 write
!(f
, " = {}", ty
)?
;
145 clean
::GenericParamDefKind
::Const { ref ty, .. }
=> {
146 f
.write_str("const ")?
;
147 f
.write_str(&self.name
)?
;
150 write
!(f
, ": {:#}", ty
)
152 write
!(f
, ": {}", ty
)
159 impl fmt
::Display
for clean
::Generics
{
160 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
161 let real_params
= self.params
163 .filter(|p
| !p
.is_synthetic_type_param())
164 .collect
::<Vec
<_
>>();
165 if real_params
.is_empty() {
169 write
!(f
, "<{:#}>", CommaSep(&real_params
))
171 write
!(f
, "<{}>", CommaSep(&real_params
))
176 impl<'a
> fmt
::Display
for WhereClause
<'a
> {
177 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
178 let &WhereClause { gens, indent, end_newline }
= self;
179 if gens
.where_predicates
.is_empty() {
182 let mut clause
= String
::new();
184 clause
.push_str(" where");
187 clause
.push_str(" <span class=\"where fmt-newline\">where");
189 clause
.push_str(" <span class=\"where\">where");
192 for (i
, pred
) in gens
.where_predicates
.iter().enumerate() {
196 clause
.push_str("<br>");
200 &clean
::WherePredicate
::BoundPredicate { ref ty, ref bounds }
=> {
203 clause
.push_str(&format
!("{:#}: {:#}", ty
, GenericBounds(bounds
)));
205 clause
.push_str(&format
!("{}: {}", ty
, GenericBounds(bounds
)));
208 &clean
::WherePredicate
::RegionPredicate
{ ref lifetime
,
210 clause
.push_str(&format
!("{}: ", lifetime
));
211 for (i
, lifetime
) in bounds
.iter().enumerate() {
213 clause
.push_str(" + ");
216 clause
.push_str(&lifetime
.to_string());
219 &clean
::WherePredicate
::EqPredicate { ref lhs, ref rhs }
=> {
221 clause
.push_str(&format
!("{:#} == {:#}", lhs
, rhs
));
223 clause
.push_str(&format
!("{} == {}", lhs
, rhs
));
228 if i
< gens
.where_predicates
.len() - 1 || end_newline
{
234 // add a space so stripping <br> tags and breaking spaces still renders properly
238 clause
.push_str(" ");
243 clause
.push_str("</span>");
244 let padding
= " ".repeat(indent
+ 4);
245 clause
= clause
.replace("<br>", &format
!("<br>{}", padding
));
246 clause
.insert_str(0, &" ".repeat(indent
.saturating_sub(1)));
248 clause
.insert_str(0, "<br>");
251 write
!(f
, "{}", clause
)
255 impl fmt
::Display
for clean
::Lifetime
{
256 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
257 f
.write_str(self.get_ref())?
;
262 impl fmt
::Display
for clean
::PolyTrait
{
263 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
264 if !self.generic_params
.is_empty() {
266 write
!(f
, "for<{:#}> ", CommaSep(&self.generic_params
))?
;
268 write
!(f
, "for<{}> ", CommaSep(&self.generic_params
))?
;
272 write
!(f
, "{:#}", self.trait_
)
274 write
!(f
, "{}", self.trait_
)
279 impl fmt
::Display
for clean
::GenericBound
{
280 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
282 clean
::GenericBound
::Outlives(ref lt
) => {
285 clean
::GenericBound
::TraitBound(ref ty
, modifier
) => {
286 let modifier_str
= match modifier
{
287 hir
::TraitBoundModifier
::None
=> "",
288 hir
::TraitBoundModifier
::Maybe
=> "?",
291 write
!(f
, "{}{:#}", modifier_str
, *ty
)
293 write
!(f
, "{}{}", modifier_str
, *ty
)
300 impl fmt
::Display
for clean
::GenericArgs
{
301 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
303 clean
::GenericArgs
::AngleBracketed
{
304 ref lifetimes
, ref types
, ref bindings
306 if !lifetimes
.is_empty() || !types
.is_empty() || !bindings
.is_empty() {
310 f
.write_str("<")?
;
312 let mut comma
= false;
313 for lifetime
in lifetimes
{
318 write
!(f
, "{}", *lifetime
)?
;
326 write
!(f
, "{:#}", *ty
)?
;
328 write
!(f
, "{}", *ty
)?
;
331 for binding
in bindings
{
337 write
!(f
, "{:#}", *binding
)?
;
339 write
!(f
, "{}", *binding
)?
;
345 f
.write_str(">")?
;
349 clean
::GenericArgs
::Parenthesized { ref inputs, ref output }
=> {
351 let mut comma
= false;
358 write
!(f
, "{:#}", *ty
)?
;
360 write
!(f
, "{}", *ty
)?
;
364 if let Some(ref ty
) = *output
{
366 write
!(f
, " -> {:#}", ty
)?
;
368 write
!(f
, " -> {}", ty
)?
;
377 impl fmt
::Display
for clean
::PathSegment
{
378 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
379 f
.write_str(&self.name
)?
;
381 write
!(f
, "{:#}", self.args
)
383 write
!(f
, "{}", self.args
)
388 impl fmt
::Display
for clean
::Path
{
389 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
394 for (i
, seg
) in self.segments
.iter().enumerate() {
399 write
!(f
, "{:#}", seg
)?
;
401 write
!(f
, "{}", seg
)?
;
408 pub fn href(did
: DefId
) -> Option
<(String
, ItemType
, Vec
<String
>)> {
410 if !did
.is_local() && !cache
.access_levels
.is_doc_reachable(did
) {
414 let loc
= CURRENT_LOCATION_KEY
.with(|l
| l
.borrow().clone());
415 let (fqp
, shortty
, mut url
) = match cache
.paths
.get(&did
) {
416 Some(&(ref fqp
, shortty
)) => {
417 (fqp
, shortty
, "../".repeat(loc
.len()))
420 let &(ref fqp
, shortty
) = cache
.external_paths
.get(&did
)?
;
421 (fqp
, shortty
, match cache
.extern_locations
[&did
.krate
] {
422 (.., render
::Remote(ref s
)) => s
.to_string(),
423 (.., render
::Local
) => "../".repeat(loc
.len()),
424 (.., render
::Unknown
) => return None
,
428 for component
in &fqp
[..fqp
.len() - 1] {
429 url
.push_str(component
);
433 ItemType
::Module
=> {
434 url
.push_str(fqp
.last().unwrap());
435 url
.push_str("/index.html");
438 url
.push_str(shortty
.css_class());
440 url
.push_str(fqp
.last().unwrap());
441 url
.push_str(".html");
444 Some((url
, shortty
, fqp
.to_vec()))
447 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
448 /// rendering function with the necessary arguments for linking to a local path.
449 fn resolved_path(w
: &mut fmt
::Formatter
<'_
>, did
: DefId
, path
: &clean
::Path
,
450 print_all
: bool
, use_absolute
: bool
) -> fmt
::Result
{
451 let last
= path
.segments
.last().unwrap();
454 for seg
in &path
.segments
[..path
.segments
.len() - 1] {
455 write
!(w
, "{}::", seg
.name
)?
;
459 write
!(w
, "{:#}{:#}", HRef
::new(did
, &last
.name
), last
.args
)?
;
461 let path
= if use_absolute
{
463 Some((_
, _
, fqp
)) => {
465 fqp
[..fqp
.len() - 1].join("::"),
466 HRef
::new(did
, fqp
.last().unwrap()))
468 None
=> HRef
::new(did
, &last
.name
).to_string(),
471 HRef
::new(did
, &last
.name
).to_string()
473 write
!(w
, "{}{}", path
, last
.args
)?
;
478 fn primitive_link(f
: &mut fmt
::Formatter
<'_
>,
479 prim
: clean
::PrimitiveType
,
480 name
: &str) -> fmt
::Result
{
482 let mut needs_termination
= false;
484 match m
.primitive_locations
.get(&prim
) {
485 Some(&def_id
) if def_id
.is_local() => {
486 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
487 let len
= if len
== 0 {0}
else {len - 1}
;
488 write
!(f
, "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
491 needs_termination
= true;
494 let loc
= match m
.extern_locations
[&def_id
.krate
] {
495 (ref cname
, _
, render
::Remote(ref s
)) => {
496 Some((cname
, s
.to_string()))
498 (ref cname
, _
, render
::Local
) => {
499 let len
= CURRENT_LOCATION_KEY
.with(|s
| s
.borrow().len());
500 Some((cname
, "../".repeat(len
)))
502 (.., render
::Unknown
) => None
,
504 if let Some((cname
, root
)) = loc
{
505 write
!(f
, "<a class=\"primitive\" href=\"{}{}/primitive.{}.html\">",
509 needs_termination
= true;
515 write
!(f
, "{}", name
)?
;
516 if needs_termination
{
522 /// Helper to render type parameters
523 fn tybounds(w
: &mut fmt
::Formatter
<'_
>,
524 typarams
: &Option
<Vec
<clean
::GenericBound
>>) -> fmt
::Result
{
526 Some(ref params
) => {
527 for param
in params
{
529 fmt
::Display
::fmt(param
, w
)?
;
538 pub fn new(did
: DefId
, text
: &'a
str) -> HRef
<'a
> {
539 HRef { did: did, text: text }
543 impl<'a
> fmt
::Display
for HRef
<'a
> {
544 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
545 match href(self.did
) {
546 Some((url
, shortty
, fqp
)) => if !f
.alternate() {
547 write
!(f
, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>",
548 shortty
, url
, shortty
, fqp
.join("::"), self.text
)
550 write
!(f
, "{}", self.text
)
552 _
=> write
!(f
, "{}", self.text
),
557 fn fmt_type(t
: &clean
::Type
, f
: &mut fmt
::Formatter
<'_
>, use_absolute
: bool
) -> fmt
::Result
{
559 clean
::Generic(ref name
) => {
562 clean
::ResolvedPath{ did, ref typarams, ref path, is_generic }
=> {
563 if typarams
.is_some() {
564 f
.write_str("dyn ")?
;
566 // Paths like T::Output and Self::Output should be rendered with all segments
567 resolved_path(f
, did
, path
, is_generic
, use_absolute
)?
;
568 tybounds(f
, typarams
)
570 clean
::Infer
=> write
!(f
, "_"),
571 clean
::Primitive(prim
) => primitive_link(f
, prim
, prim
.as_str()),
572 clean
::BareFunction(ref decl
) => {
574 write
!(f
, "{}{:#}fn{:#}{:#}",
575 UnsafetySpace(decl
.unsafety
),
577 CommaSep(&decl
.generic_params
),
580 write
!(f
, "{}{}", UnsafetySpace(decl
.unsafety
), AbiSpace(decl
.abi
))?
;
581 primitive_link(f
, PrimitiveType
::Fn
, "fn")?
;
582 write
!(f
, "{}{}", CommaSep(&decl
.generic_params
), decl
.decl
)
585 clean
::Tuple(ref typs
) => {
587 &[] => primitive_link(f
, PrimitiveType
::Unit
, "()"),
589 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
590 //carry f.alternate() into this display w/o branching manually
591 fmt
::Display
::fmt(one
, f
)?
;
592 primitive_link(f
, PrimitiveType
::Tuple
, ",)")
595 primitive_link(f
, PrimitiveType
::Tuple
, "(")?
;
596 fmt
::Display
::fmt(&CommaSep(many
), f
)?
;
597 primitive_link(f
, PrimitiveType
::Tuple
, ")")
601 clean
::Slice(ref t
) => {
602 primitive_link(f
, PrimitiveType
::Slice
, "[")?
;
603 fmt
::Display
::fmt(t
, f
)?
;
604 primitive_link(f
, PrimitiveType
::Slice
, "]")
606 clean
::Array(ref t
, ref n
) => {
607 primitive_link(f
, PrimitiveType
::Array
, "[")?
;
608 fmt
::Display
::fmt(t
, f
)?
;
609 primitive_link(f
, PrimitiveType
::Array
, &format
!("; {}]", n
))
611 clean
::Never
=> primitive_link(f
, PrimitiveType
::Never
, "!"),
612 clean
::RawPointer(m
, ref t
) => {
614 clean
::Generic(_
) | clean
::ResolvedPath {is_generic: true, ..}
=> {
616 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
617 &format
!("*{}{:#}", RawMutableSpace(m
), t
))
619 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
620 &format
!("*{}{}", RawMutableSpace(m
), t
))
624 primitive_link(f
, clean
::PrimitiveType
::RawPointer
,
625 &format
!("*{}", RawMutableSpace(m
)))?
;
626 fmt
::Display
::fmt(t
, f
)
630 clean
::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty}
=> {
632 Some(ref l
) => format
!("{} ", *l
),
635 let m
= MutableSpace(mutability
);
636 let amp
= if f
.alternate() {
642 clean
::Slice(ref bt
) => { // BorrowedRef{ ... Slice(T) } is
&[T
]
644 clean
::Generic(_
) => {
646 primitive_link(f
, PrimitiveType
::Slice
,
647 &format
!("{}{}{}[{:#}]", amp
, lt
, m
, **bt
))
649 primitive_link(f
, PrimitiveType
::Slice
,
650 &format
!("{}{}{}[{}]", amp
, lt
, m
, **bt
))
654 primitive_link(f
, PrimitiveType
::Slice
,
655 &format
!("{}{}{}[", amp
, lt
, m
))?
;
657 write
!(f
, "{:#}", **bt
)?
;
659 write
!(f
, "{}", **bt
)?
;
661 primitive_link(f
, PrimitiveType
::Slice
, "]")
665 clean
::ResolvedPath { typarams: Some(ref v), .. }
if !v
.is_empty() => {
666 write
!(f
, "{}{}{}(", amp
, lt
, m
)?
;
667 fmt_type(&ty
, f
, use_absolute
)?
;
670 clean
::Generic(..) => {
671 primitive_link(f
, PrimitiveType
::Reference
,
672 &format
!("{}{}{}", amp
, lt
, m
))?
;
673 fmt_type(&ty
, f
, use_absolute
)
676 write
!(f
, "{}{}{}", amp
, lt
, m
)?
;
677 fmt_type(&ty
, f
, use_absolute
)
681 clean
::ImplTrait(ref bounds
) => {
683 write
!(f
, "impl {:#}", GenericBounds(bounds
))
685 write
!(f
, "impl {}", GenericBounds(bounds
))
688 clean
::QPath { ref name, ref self_type, ref trait_ }
=> {
689 let should_show_cast
= match *trait_
{
690 box clean
::ResolvedPath { ref path, .. }
=> {
691 !path
.segments
.is_empty() && !self_type
.is_self_type()
696 if should_show_cast
{
697 write
!(f
, "<{:#} as {:#}>::", self_type
, trait_
)?
699 write
!(f
, "{:#}::", self_type
)?
702 if should_show_cast
{
703 write
!(f
, "<{} as {}>::", self_type
, trait_
)?
705 write
!(f
, "{}::", self_type
)?
709 // It's pretty unsightly to look at `<A as B>::C` in output, and
710 // we've got hyperlinking on our side, so try to avoid longer
711 // notation as much as possible by making `C` a hyperlink to trait
712 // `B` to disambiguate.
714 // FIXME: this is still a lossy conversion and there should probably
715 // be a better way of representing this in general? Most of
716 // the ugliness comes from inlining across crates where
717 // everything comes in as a fully resolved QPath (hard to
719 box clean
::ResolvedPath { did, ref typarams, .. }
=> {
721 Some((ref url
, _
, ref path
)) if !f
.alternate() => {
723 "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
724 title=\"type {path}::{name}\">{name}</a>",
726 shortty
= ItemType
::AssociatedType
,
728 path
= path
.join("::"))?
;
730 _
=> write
!(f
, "{}", name
)?
,
733 // FIXME: `typarams` are not rendered, and this seems bad?
738 write
!(f
, "{}", name
)
742 clean
::Unique(..) => {
743 panic
!("should have been cleaned")
748 impl fmt
::Display
for clean
::Type
{
749 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
750 fmt_type(self, f
, false)
754 fn fmt_impl(i
: &clean
::Impl
,
755 f
: &mut fmt
::Formatter
<'_
>,
757 use_absolute
: bool
) -> fmt
::Result
{
759 write
!(f
, "impl{:#} ", i
.generics
)?
;
761 write
!(f
, "impl{} ", i
.generics
)?
;
764 if let Some(ref ty
) = i
.trait_
{
765 if i
.polarity
== Some(clean
::ImplPolarity
::Negative
) {
770 fmt
::Display
::fmt(ty
, f
)?
;
773 clean
::ResolvedPath { typarams: None, ref path, is_generic: false, .. }
=> {
774 let last
= path
.segments
.last().unwrap();
775 fmt
::Display
::fmt(&last
.name
, f
)?
;
776 fmt
::Display
::fmt(&last
.args
, f
)?
;
784 if let Some(ref ty
) = i
.blanket_impl
{
785 fmt_type(ty
, f
, use_absolute
)?
;
787 fmt_type(&i
.for_
, f
, use_absolute
)?
;
790 fmt
::Display
::fmt(&WhereClause { gens: &i.generics, indent: 0, end_newline: true }
, f
)?
;
794 impl fmt
::Display
for clean
::Impl
{
795 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
796 fmt_impl(self, f
, true, false)
800 // The difference from above is that trait is not hyperlinked.
801 pub fn fmt_impl_for_trait_page(i
: &clean
::Impl
,
802 f
: &mut fmt
::Formatter
<'_
>,
803 use_absolute
: bool
) -> fmt
::Result
{
804 fmt_impl(i
, f
, false, use_absolute
)
807 impl fmt
::Display
for clean
::Arguments
{
808 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
809 for (i
, input
) in self.values
.iter().enumerate() {
810 if !input
.name
.is_empty() {
811 write
!(f
, "{}: ", input
.name
)?
;
814 write
!(f
, "{:#}", input
.type_
)?
;
816 write
!(f
, "{}", input
.type_
)?
;
818 if i
+ 1 < self.values
.len() { write!(f, ", ")?; }
824 impl fmt
::Display
for clean
::FunctionRetTy
{
825 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
827 clean
::Return(clean
::Tuple(ref tys
)) if tys
.is_empty() => Ok(()),
828 clean
::Return(ref ty
) if f
.alternate() => write
!(f
, " -> {:#}", ty
),
829 clean
::Return(ref ty
) => write
!(f
, " -> {}", ty
),
830 clean
::DefaultReturn
=> Ok(()),
835 impl fmt
::Display
for clean
::FnDecl
{
836 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
839 write
!(f
, "({args:#}, ...){arrow:#}", args
= self.inputs
, arrow
= self.output
)
841 write
!(f
, "({args}, ...){arrow}", args
= self.inputs
, arrow
= self.output
)
845 write
!(f
, "({args:#}){arrow:#}", args
= self.inputs
, arrow
= self.output
)
847 write
!(f
, "({args}){arrow}", args
= self.inputs
, arrow
= self.output
)
853 impl<'a
> fmt
::Display
for Function
<'a
> {
854 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
855 let &Function { decl, header_len, indent, asyncness }
= self;
856 let amp
= if f
.alternate() { "&" }
else { "&" }
;
857 let mut args
= String
::new();
858 let mut args_plain
= String
::new();
859 for (i
, input
) in decl
.inputs
.values
.iter().enumerate() {
861 args
.push_str("<br>");
864 if let Some(selfty
) = input
.to_self() {
866 clean
::SelfValue
=> {
867 args
.push_str("self");
868 args_plain
.push_str("self");
870 clean
::SelfBorrowed(Some(ref lt
), mtbl
) => {
871 args
.push_str(&format
!("{}{} {}self", amp
, *lt
, MutableSpace(mtbl
)));
872 args_plain
.push_str(&format
!("&{} {}self", *lt
, MutableSpace(mtbl
)));
874 clean
::SelfBorrowed(None
, mtbl
) => {
875 args
.push_str(&format
!("{}{}self", amp
, MutableSpace(mtbl
)));
876 args_plain
.push_str(&format
!("&{}self", MutableSpace(mtbl
)));
878 clean
::SelfExplicit(ref typ
) => {
880 args
.push_str(&format
!("self: {:#}", *typ
));
882 args
.push_str(&format
!("self: {}", *typ
));
884 args_plain
.push_str(&format
!("self: {:#}", *typ
));
889 args
.push_str(" <br>");
890 args_plain
.push_str(" ");
892 if !input
.name
.is_empty() {
893 args
.push_str(&format
!("{}: ", input
.name
));
894 args_plain
.push_str(&format
!("{}: ", input
.name
));
898 args
.push_str(&format
!("{:#}", input
.type_
));
900 args
.push_str(&input
.type_
.to_string());
902 args_plain
.push_str(&format
!("{:#}", input
.type_
));
904 if i
+ 1 < decl
.inputs
.values
.len() {
906 args_plain
.push('
,'
);
910 let mut args_plain
= format
!("({})", args_plain
);
913 args
.push_str(",<br> ...");
914 args_plain
.push_str(", ...");
917 let output
= if let hir
::IsAsync
::Async
= asyncness
{
918 Cow
::Owned(decl
.sugared_async_return_type())
920 Cow
::Borrowed(&decl
.output
)
923 let arrow_plain
= format
!("{:#}", &output
);
924 let arrow
= if f
.alternate() {
925 format
!("{:#}", &output
)
930 let declaration_len
= header_len
+ args_plain
.len() + arrow_plain
.len();
931 let output
= if declaration_len
> 80 {
932 let full_pad
= format
!("<br>{}", " ".repeat(indent
+ 4));
933 let close_pad
= format
!("<br>{}", " ".repeat(indent
));
934 format
!("({args}{close}){arrow}",
935 args
= args
.replace("<br>", &full_pad
),
939 format
!("({args}){arrow}", args
= args
.replace("<br>", ""), arrow
= arrow
)
943 write
!(f
, "{}", output
.replace("<br>", "\n"))
945 write
!(f
, "{}", output
)
950 impl<'a
> fmt
::Display
for VisSpace
<'a
> {
951 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
953 Some(clean
::Public
) => f
.write_str("pub "),
954 Some(clean
::Inherited
) | None
=> Ok(()),
955 Some(clean
::Visibility
::Crate
) => write
!(f
, "pub(crate) "),
956 Some(clean
::Visibility
::Restricted(did
, ref path
)) => {
957 f
.write_str("pub(")?
;
958 if path
.segments
.len() != 1
959 || (path
.segments
[0].name
!= "self" && path
.segments
[0].name
!= "super")
963 resolved_path(f
, did
, path
, true, false)?
;
970 impl fmt
::Display
for UnsafetySpace
{
971 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
973 hir
::Unsafety
::Unsafe
=> write
!(f
, "unsafe "),
974 hir
::Unsafety
::Normal
=> Ok(())
979 impl fmt
::Display
for ConstnessSpace
{
980 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
982 hir
::Constness
::Const
=> write
!(f
, "const "),
983 hir
::Constness
::NotConst
=> Ok(())
988 impl fmt
::Display
for AsyncSpace
{
989 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
991 hir
::IsAsync
::Async
=> write
!(f
, "async "),
992 hir
::IsAsync
::NotAsync
=> Ok(()),
997 impl fmt
::Display
for clean
::Import
{
998 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1000 clean
::Import
::Simple(ref name
, ref src
) => {
1001 if *name
== src
.path
.last_name() {
1002 write
!(f
, "use {};", *src
)
1004 write
!(f
, "use {} as {};", *src
, *name
)
1007 clean
::Import
::Glob(ref src
) => {
1008 if src
.path
.segments
.is_empty() {
1011 write
!(f
, "use {}::*;", *src
)
1018 impl fmt
::Display
for clean
::ImportSource
{
1019 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1021 Some(did
) => resolved_path(f
, did
, &self.path
, true, false),
1023 for (i
, seg
) in self.path
.segments
.iter().enumerate() {
1027 write
!(f
, "{}", seg
.name
)?
;
1035 impl fmt
::Display
for clean
::TypeBinding
{
1036 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1038 write
!(f
, "{} = {:#}", self.name
, self.ty
)
1040 write
!(f
, "{} = {}", self.name
, self.ty
)
1045 impl fmt
::Display
for MutableSpace
{
1046 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1048 MutableSpace(clean
::Immutable
) => Ok(()),
1049 MutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1054 impl fmt
::Display
for RawMutableSpace
{
1055 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1057 RawMutableSpace(clean
::Immutable
) => write
!(f
, "const "),
1058 RawMutableSpace(clean
::Mutable
) => write
!(f
, "mut "),
1063 impl fmt
::Display
for AbiSpace
{
1064 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1065 let quot
= if f
.alternate() { "\"" }
else { """ }
;
1067 Abi
::Rust
=> Ok(()),
1068 abi
=> write
!(f
, "extern {0}{1}{0} ", quot
, abi
.name()),