1 // A signature is a string representation of an item's type signature, excluding
2 // any body. It also includes ids for any defs or refs in the signature. For
10 // The signature string is something like "fn foo(x: String) {}" and the signature
11 // will have defs for `foo` and `x` and a ref for `String`.
13 // All signature text should parse in the correct context (i.e., in a module or
14 // impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a
15 // signature is not guaranteed to be stable (it may improve or change as the
16 // syntax changes, or whitespace or punctuation may change). It is also likely
17 // not to be pretty - no attempt is made to prettify the text. It is recommended
18 // that clients run the text through Rustfmt.
20 // This module generates Signatures for items by walking the AST and looking up
23 // Signatures do not include visibility info. I'm not sure if this is a feature
24 // or an ommission (FIXME).
26 // FIXME where clauses need implementing, defs/refs in generics are mostly missing.
28 use crate::{id_from_def_id, id_from_node_id, SaveContext};
30 use rls_data::{SigElement, Signature};
32 use rustc::hir::def::{Res, DefKind};
33 use syntax::ast::{self, NodeId};
34 use syntax::print::pprust;
37 pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
38 if !scx.config.signatures {
41 item.make(0, None, scx).ok()
44 pub fn foreign_item_signature(
45 item: &ast::ForeignItem,
46 scx: &SaveContext<'_, '_>
47 ) -> Option<Signature> {
48 if !scx.config.signatures {
51 item.make(0, None, scx).ok()
54 /// Signature for a struct or tuple field declaration.
55 /// Does not include a trailing comma.
56 pub fn field_signature(field: &ast::StructField, scx: &SaveContext<'_, '_>) -> Option<Signature> {
57 if !scx.config.signatures {
60 field.make(0, None, scx).ok()
63 /// Does not include a trailing comma.
64 pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> Option<Signature> {
65 if !scx.config.signatures {
68 variant.make(0, None, scx).ok()
71 pub fn method_signature(
74 generics: &ast::Generics,
76 scx: &SaveContext<'_, '_>,
77 ) -> Option<Signature> {
78 if !scx.config.signatures {
81 make_method_signature(id, ident, generics, m, scx).ok()
84 pub fn assoc_const_signature(
88 default: Option<&ast::Expr>,
89 scx: &SaveContext<'_, '_>,
90 ) -> Option<Signature> {
91 if !scx.config.signatures {
94 make_assoc_const_signature(id, ident, ty, default, scx).ok()
97 pub fn assoc_type_signature(
100 bounds: Option<&ast::GenericBounds>,
101 default: Option<&ast::Ty>,
102 scx: &SaveContext<'_, '_>,
103 ) -> Option<Signature> {
104 if !scx.config.signatures {
107 make_assoc_type_signature(id, ident, bounds, default, scx).ok()
110 type Result = std::result::Result<Signature, &'static str>;
113 fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result;
119 defs: Vec<SigElement>,
120 refs: Vec<SigElement>,
123 sig.defs.extend(defs.into_iter());
124 sig.refs.extend(refs.into_iter());
128 fn replace_text(mut sig: Signature, text: String) -> Signature {
133 fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
134 let mut result = Signature {
140 let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
144 .extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
147 .extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
152 fn text_sig(text: String) -> Signature {
160 fn push_abi(text: &mut String, abi: ast::Abi) {
161 if abi.symbol != sym::Rust {
162 text.push_str(&format!("extern \"{}\" ", abi.symbol));
166 impl Sig for ast::Ty {
167 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
168 let id = Some(self.id);
170 ast::TyKind::Slice(ref ty) => {
171 let nested = ty.make(offset + 1, id, scx)?;
172 let text = format!("[{}]", nested.text);
173 Ok(replace_text(nested, text))
175 ast::TyKind::Ptr(ref mt) => {
176 let prefix = match mt.mutbl {
177 ast::Mutability::Mutable => "*mut ",
178 ast::Mutability::Immutable => "*const ",
180 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
181 let text = format!("{}{}", prefix, nested.text);
182 Ok(replace_text(nested, text))
184 ast::TyKind::Rptr(ref lifetime, ref mt) => {
185 let mut prefix = "&".to_owned();
186 if let &Some(ref l) = lifetime {
187 prefix.push_str(&l.ident.to_string());
190 if let ast::Mutability::Mutable = mt.mutbl {
191 prefix.push_str("mut ");
194 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
195 let text = format!("{}{}", prefix, nested.text);
196 Ok(replace_text(nested, text))
198 ast::TyKind::Never => Ok(text_sig("!".to_owned())),
199 ast::TyKind::CVarArgs => Ok(text_sig("...".to_owned())),
200 ast::TyKind::Tup(ref ts) => {
201 let mut text = "(".to_owned();
202 let mut defs = vec![];
203 let mut refs = vec![];
205 let nested = t.make(offset + text.len(), id, scx)?;
206 text.push_str(&nested.text);
208 defs.extend(nested.defs.into_iter());
209 refs.extend(nested.refs.into_iter());
212 Ok(Signature { text, defs, refs })
214 ast::TyKind::Paren(ref ty) => {
215 let nested = ty.make(offset + 1, id, scx)?;
216 let text = format!("({})", nested.text);
217 Ok(replace_text(nested, text))
219 ast::TyKind::BareFn(ref f) => {
220 let mut text = String::new();
221 if !f.generic_params.is_empty() {
222 // FIXME defs, bounds on lifetimes
223 text.push_str("for<");
224 text.push_str(&f.generic_params
226 .filter_map(|param| match param.kind {
227 ast::GenericParamKind::Lifetime { .. } => {
228 Some(param.ident.to_string())
237 if f.unsafety == ast::Unsafety::Unsafe {
238 text.push_str("unsafe ");
240 push_abi(&mut text, f.abi);
241 text.push_str("fn(");
243 let mut defs = vec![];
244 let mut refs = vec![];
245 for i in &f.decl.inputs {
246 let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?;
247 text.push_str(&nested.text);
249 defs.extend(nested.defs.into_iter());
250 refs.extend(nested.refs.into_iter());
253 if let ast::FunctionRetTy::Ty(ref t) = f.decl.output {
254 text.push_str(" -> ");
255 let nested = t.make(offset + text.len(), None, scx)?;
256 text.push_str(&nested.text);
258 defs.extend(nested.defs.into_iter());
259 refs.extend(nested.refs.into_iter());
262 Ok(Signature { text, defs, refs })
264 ast::TyKind::Path(None, ref path) => path.make(offset, id, scx),
265 ast::TyKind::Path(Some(ref qself), ref path) => {
266 let nested_ty = qself.ty.make(offset + 1, id, scx)?;
267 let prefix = if qself.position == 0 {
268 format!("<{}>::", nested_ty.text)
269 } else if qself.position == 1 {
270 let first = pprust::path_segment_to_string(&path.segments[0]);
271 format!("<{} as {}>::", nested_ty.text, first)
273 // FIXME handle path instead of elipses.
274 format!("<{} as ...>::", nested_ty.text)
277 let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?);
278 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
279 let id = id_from_def_id(res.def_id());
280 if path.segments.len() - qself.position == 1 {
281 let start = offset + prefix.len();
282 let end = start + name.len();
285 text: prefix + &name,
287 refs: vec![SigElement { id, start, end }],
290 let start = offset + prefix.len() + 5;
291 let end = start + name.len();
292 // FIXME should put the proper path in there, not elipses.
294 text: prefix + "...::" + &name,
296 refs: vec![SigElement { id, start, end }],
300 ast::TyKind::TraitObject(ref bounds, ..) => {
301 // FIXME recurse into bounds
302 let nested = pprust::bounds_to_string(bounds);
305 ast::TyKind::ImplTrait(_, ref bounds) => {
306 // FIXME recurse into bounds
307 let nested = pprust::bounds_to_string(bounds);
308 Ok(text_sig(format!("impl {}", nested)))
310 ast::TyKind::Array(ref ty, ref v) => {
311 let nested_ty = ty.make(offset + 1, id, scx)?;
312 let expr = pprust::expr_to_string(&v.value).replace('\n', " ");
313 let text = format!("[{}; {}]", nested_ty.text, expr);
314 Ok(replace_text(nested_ty, text))
316 ast::TyKind::Typeof(_) |
319 ast::TyKind::ImplicitSelf |
320 ast::TyKind::Mac(_) => Err("Ty"),
325 impl Sig for ast::Item {
326 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
327 let id = Some(self.id);
330 ast::ItemKind::Static(ref ty, m, ref expr) => {
331 let mut text = "static ".to_owned();
332 if m == ast::Mutability::Mutable {
333 text.push_str("mut ");
335 let name = self.ident.to_string();
338 id: id_from_node_id(self.id, scx),
339 start: offset + text.len(),
340 end: offset + text.len() + name.len(),
343 text.push_str(&name);
346 let ty = ty.make(offset + text.len(), id, scx)?;
347 text.push_str(&ty.text);
348 text.push_str(" = ");
350 let expr = pprust::expr_to_string(expr).replace('\n', " ");
351 text.push_str(&expr);
354 Ok(extend_sig(ty, text, defs, vec![]))
356 ast::ItemKind::Const(ref ty, ref expr) => {
357 let mut text = "const ".to_owned();
358 let name = self.ident.to_string();
361 id: id_from_node_id(self.id, scx),
362 start: offset + text.len(),
363 end: offset + text.len() + name.len(),
366 text.push_str(&name);
369 let ty = ty.make(offset + text.len(), id, scx)?;
370 text.push_str(&ty.text);
371 text.push_str(" = ");
373 let expr = pprust::expr_to_string(expr).replace('\n', " ");
374 text.push_str(&expr);
377 Ok(extend_sig(ty, text, defs, vec![]))
379 ast::ItemKind::Fn(ast::FnSig { ref decl, header }, ref generics, _) => {
380 let mut text = String::new();
381 if header.constness.node == ast::Constness::Const {
382 text.push_str("const ");
384 if header.asyncness.node.is_async() {
385 text.push_str("async ");
387 if header.unsafety == ast::Unsafety::Unsafe {
388 text.push_str("unsafe ");
390 push_abi(&mut text, header.abi);
391 text.push_str("fn ");
393 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
396 for i in &decl.inputs {
397 // FIXME should descend into patterns to add defs.
398 sig.text.push_str(&pprust::pat_to_string(&i.pat));
399 sig.text.push_str(": ");
400 let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
401 sig.text.push_str(&nested.text);
403 sig.defs.extend(nested.defs.into_iter());
404 sig.refs.extend(nested.refs.into_iter());
408 if let ast::FunctionRetTy::Ty(ref t) = decl.output {
409 sig.text.push_str(" -> ");
410 let nested = t.make(offset + sig.text.len(), None, scx)?;
411 sig.text.push_str(&nested.text);
412 sig.defs.extend(nested.defs.into_iter());
413 sig.refs.extend(nested.refs.into_iter());
415 sig.text.push_str(" {}");
419 ast::ItemKind::Mod(ref _mod) => {
420 let mut text = "mod ".to_owned();
421 let name = self.ident.to_string();
424 id: id_from_node_id(self.id, scx),
425 start: offset + text.len(),
426 end: offset + text.len() + name.len(),
429 text.push_str(&name);
430 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
439 ast::ItemKind::TyAlias(ref ty, ref generics) => {
440 let text = "type ".to_owned();
441 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
443 sig.text.push_str(" = ");
444 let ty = ty.make(offset + sig.text.len(), id, scx)?;
445 sig.text.push_str(&ty.text);
448 Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
450 ast::ItemKind::Enum(_, ref generics) => {
451 let text = "enum ".to_owned();
452 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
453 sig.text.push_str(" {}");
456 ast::ItemKind::Struct(_, ref generics) => {
457 let text = "struct ".to_owned();
458 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
459 sig.text.push_str(" {}");
462 ast::ItemKind::Union(_, ref generics) => {
463 let text = "union ".to_owned();
464 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
465 sig.text.push_str(" {}");
468 ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
469 let mut text = String::new();
471 if is_auto == ast::IsAuto::Yes {
472 text.push_str("auto ");
475 if unsafety == ast::Unsafety::Unsafe {
476 text.push_str("unsafe ");
478 text.push_str("trait ");
479 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
481 if !bounds.is_empty() {
482 sig.text.push_str(": ");
483 sig.text.push_str(&pprust::bounds_to_string(bounds));
485 // FIXME where clause
486 sig.text.push_str(" {}");
490 ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
491 let mut text = String::new();
492 text.push_str("trait ");
493 let mut sig = name_and_generics(text,
500 if !bounds.is_empty() {
501 sig.text.push_str(" = ");
502 sig.text.push_str(&pprust::bounds_to_string(bounds));
504 // FIXME where clause
505 sig.text.push_str(";");
518 let mut text = String::new();
519 if let ast::Defaultness::Default = defaultness {
520 text.push_str("default ");
522 if unsafety == ast::Unsafety::Unsafe {
523 text.push_str("unsafe ");
525 text.push_str("impl");
527 let generics_sig = generics.make(offset + text.len(), id, scx)?;
528 text.push_str(&generics_sig.text);
532 let trait_sig = if let Some(ref t) = *opt_trait {
533 if polarity == ast::ImplPolarity::Negative {
536 let trait_sig = t.path.make(offset + text.len(), id, scx)?;
537 text.push_str(&trait_sig.text);
538 text.push_str(" for ");
541 text_sig(String::new())
544 let ty_sig = ty.make(offset + text.len(), id, scx)?;
545 text.push_str(&ty_sig.text);
547 text.push_str(" {}");
549 Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
551 // FIXME where clause
553 ast::ItemKind::ForeignMod(_) => Err("extern mod"),
554 ast::ItemKind::GlobalAsm(_) => Err("glboal asm"),
555 ast::ItemKind::ExternCrate(_) => Err("extern crate"),
556 // FIXME should implement this (e.g., pub use).
557 ast::ItemKind::Use(_) => Err("import"),
558 ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
563 impl Sig for ast::Path {
564 fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
565 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
567 let (name, start, end) = match res {
568 Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => {
569 return Ok(Signature {
570 text: pprust::path_to_string(self),
575 Res::Def(DefKind::AssocConst, _)
576 | Res::Def(DefKind::Variant, _)
577 | Res::Def(DefKind::Ctor(..), _) => {
578 let len = self.segments.len();
580 return Err("Bad path");
582 // FIXME: really we should descend into the generics here and add SigElements for
584 // FIXME: would be nice to have a def for the first path segment.
585 let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]);
586 let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]);
587 let start = offset + seg1.len() + 2;
588 (format!("{}::{}", seg1, seg2), start, start + seg2.len())
591 let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?);
592 let end = offset + name.len();
597 let id = id_from_def_id(res.def_id());
601 refs: vec![SigElement { id, start, end }],
606 // This does not cover the where clause, which must be processed separately.
607 impl Sig for ast::Generics {
608 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
609 if self.params.is_empty() {
610 return Ok(text_sig(String::new()));
613 let mut text = "<".to_owned();
615 let mut defs = Vec::with_capacity(self.params.len());
616 for param in &self.params {
617 let mut param_text = String::new();
618 if let ast::GenericParamKind::Const { .. } = param.kind {
619 param_text.push_str("const ");
621 param_text.push_str(¶m.ident.as_str());
622 defs.push(SigElement {
623 id: id_from_node_id(param.id, scx),
624 start: offset + text.len(),
625 end: offset + text.len() + param_text.as_str().len(),
627 if let ast::GenericParamKind::Const { ref ty } = param.kind {
628 param_text.push_str(": ");
629 param_text.push_str(&pprust::ty_to_string(&ty));
631 if !param.bounds.is_empty() {
632 param_text.push_str(": ");
634 ast::GenericParamKind::Lifetime { .. } => {
635 let bounds = param.bounds.iter()
636 .map(|bound| match bound {
637 ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
642 param_text.push_str(&bounds);
643 // FIXME add lifetime bounds refs.
645 ast::GenericParamKind::Type { .. } => {
646 param_text.push_str(&pprust::bounds_to_string(¶m.bounds));
647 // FIXME descend properly into bounds.
649 ast::GenericParamKind::Const { .. } => {
650 // Const generics cannot contain bounds.
654 text.push_str(¶m_text);
667 impl Sig for ast::StructField {
668 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
669 let mut text = String::new();
671 if let Some(ident) = self.ident {
672 text.push_str(&ident.to_string());
673 defs = Some(SigElement {
674 id: id_from_node_id(self.id, scx),
676 end: offset + text.len(),
681 let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?;
682 text.push_str(&ty_sig.text);
684 ty_sig.defs.extend(defs.into_iter());
690 impl Sig for ast::Variant {
691 fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
692 let mut text = self.ident.to_string();
694 ast::VariantData::Struct(ref fields, r) => {
695 let id = parent_id.unwrap();
696 let name_def = SigElement {
697 id: id_from_node_id(id, scx),
699 end: offset + text.len(),
701 text.push_str(" { ");
702 let mut defs = vec![name_def];
703 let mut refs = vec![];
705 text.push_str("/* parse error */ ");
708 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
709 text.push_str(&field_sig.text);
711 defs.extend(field_sig.defs.into_iter());
712 refs.extend(field_sig.refs.into_iter());
716 Ok(Signature { text, defs, refs })
718 ast::VariantData::Tuple(ref fields, id) => {
719 let name_def = SigElement {
720 id: id_from_node_id(id, scx),
722 end: offset + text.len(),
725 let mut defs = vec![name_def];
726 let mut refs = vec![];
728 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
729 text.push_str(&field_sig.text);
731 defs.extend(field_sig.defs.into_iter());
732 refs.extend(field_sig.refs.into_iter());
735 Ok(Signature { text, defs, refs })
737 ast::VariantData::Unit(id) => {
738 let name_def = SigElement {
739 id: id_from_node_id(id, scx),
741 end: offset + text.len(),
745 defs: vec![name_def],
753 impl Sig for ast::ForeignItem {
754 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
755 let id = Some(self.id);
757 ast::ForeignItemKind::Fn(ref decl, ref generics) => {
758 let mut text = String::new();
759 text.push_str("fn ");
761 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
764 for i in &decl.inputs {
765 // FIXME should descend into patterns to add defs.
766 sig.text.push_str(&pprust::pat_to_string(&i.pat));
767 sig.text.push_str(": ");
768 let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
769 sig.text.push_str(&nested.text);
771 sig.defs.extend(nested.defs.into_iter());
772 sig.refs.extend(nested.refs.into_iter());
776 if let ast::FunctionRetTy::Ty(ref t) = decl.output {
777 sig.text.push_str(" -> ");
778 let nested = t.make(offset + sig.text.len(), None, scx)?;
779 sig.text.push_str(&nested.text);
780 sig.defs.extend(nested.defs.into_iter());
781 sig.refs.extend(nested.refs.into_iter());
787 ast::ForeignItemKind::Static(ref ty, m) => {
788 let mut text = "static ".to_owned();
789 if m == ast::Mutability::Mutable {
790 text.push_str("mut ");
792 let name = self.ident.to_string();
795 id: id_from_node_id(self.id, scx),
796 start: offset + text.len(),
797 end: offset + text.len() + name.len(),
800 text.push_str(&name);
803 let ty_sig = ty.make(offset + text.len(), id, scx)?;
806 Ok(extend_sig(ty_sig, text, defs, vec![]))
808 ast::ForeignItemKind::Ty => {
809 let mut text = "type ".to_owned();
810 let name = self.ident.to_string();
813 id: id_from_node_id(self.id, scx),
814 start: offset + text.len(),
815 end: offset + text.len() + name.len(),
818 text.push_str(&name);
827 ast::ForeignItemKind::Macro(..) => Err("macro"),
832 fn name_and_generics(
835 generics: &ast::Generics,
838 scx: &SaveContext<'_, '_>,
840 let name = name.to_string();
841 let def = SigElement {
842 id: id_from_node_id(id, scx),
843 start: offset + text.len(),
844 end: offset + text.len() + name.len(),
846 text.push_str(&name);
847 let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
848 // FIXME where clause
849 let text = format!("{}{}", text, generics.text);
850 Ok(extend_sig(generics, text, vec![def], vec![]))
854 fn make_assoc_type_signature(
857 bounds: Option<&ast::GenericBounds>,
858 default: Option<&ast::Ty>,
859 scx: &SaveContext<'_, '_>,
861 let mut text = "type ".to_owned();
862 let name = ident.to_string();
865 id: id_from_node_id(id, scx),
867 end: text.len() + name.len(),
870 let mut refs = vec![];
871 text.push_str(&name);
872 if let Some(bounds) = bounds {
874 // FIXME should descend into bounds
875 text.push_str(&pprust::bounds_to_string(bounds));
877 if let Some(default) = default {
878 text.push_str(" = ");
879 let ty_sig = default.make(text.len(), Some(id), scx)?;
880 text.push_str(&ty_sig.text);
881 defs.extend(ty_sig.defs.into_iter());
882 refs.extend(ty_sig.refs.into_iter());
885 Ok(Signature { text, defs, refs })
888 fn make_assoc_const_signature(
892 default: Option<&ast::Expr>,
893 scx: &SaveContext<'_, '_>,
895 let mut text = "const ".to_owned();
896 let name = ident.to_string();
899 id: id_from_node_id(id, scx),
901 end: text.len() + name.len(),
904 let mut refs = vec![];
905 text.push_str(&name);
908 let ty_sig = ty.make(text.len(), Some(id), scx)?;
909 text.push_str(&ty_sig.text);
910 defs.extend(ty_sig.defs.into_iter());
911 refs.extend(ty_sig.refs.into_iter());
913 if let Some(default) = default {
914 text.push_str(" = ");
915 text.push_str(&pprust::expr_to_string(default));
918 Ok(Signature { text, defs, refs })
921 fn make_method_signature(
924 generics: &ast::Generics,
926 scx: &SaveContext<'_, '_>,
928 // FIXME code dup with function signature
929 let mut text = String::new();
930 if m.header.constness.node == ast::Constness::Const {
931 text.push_str("const ");
933 if m.header.asyncness.node.is_async() {
934 text.push_str("async ");
936 if m.header.unsafety == ast::Unsafety::Unsafe {
937 text.push_str("unsafe ");
939 push_abi(&mut text, m.header.abi);
940 text.push_str("fn ");
942 let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
945 for i in &m.decl.inputs {
946 // FIXME should descend into patterns to add defs.
947 sig.text.push_str(&pprust::pat_to_string(&i.pat));
948 sig.text.push_str(": ");
949 let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?;
950 sig.text.push_str(&nested.text);
952 sig.defs.extend(nested.defs.into_iter());
953 sig.refs.extend(nested.refs.into_iter());
957 if let ast::FunctionRetTy::Ty(ref t) = m.decl.output {
958 sig.text.push_str(" -> ");
959 let nested = t.make(sig.text.len(), None, scx)?;
960 sig.text.push_str(&nested.text);
961 sig.defs.extend(nested.defs.into_iter());
962 sig.refs.extend(nested.refs.into_iter());
964 sig.text.push_str(" {}");