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::OpaqueTy(ref bounds, ref generics) => {
451 let text = "type ".to_owned();
452 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
454 sig.text.push_str(" = impl ");
455 sig.text.push_str(&pprust::bounds_to_string(bounds));
460 ast::ItemKind::Enum(_, ref generics) => {
461 let text = "enum ".to_owned();
462 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
463 sig.text.push_str(" {}");
466 ast::ItemKind::Struct(_, ref generics) => {
467 let text = "struct ".to_owned();
468 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
469 sig.text.push_str(" {}");
472 ast::ItemKind::Union(_, ref generics) => {
473 let text = "union ".to_owned();
474 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
475 sig.text.push_str(" {}");
478 ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
479 let mut text = String::new();
481 if is_auto == ast::IsAuto::Yes {
482 text.push_str("auto ");
485 if unsafety == ast::Unsafety::Unsafe {
486 text.push_str("unsafe ");
488 text.push_str("trait ");
489 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
491 if !bounds.is_empty() {
492 sig.text.push_str(": ");
493 sig.text.push_str(&pprust::bounds_to_string(bounds));
495 // FIXME where clause
496 sig.text.push_str(" {}");
500 ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
501 let mut text = String::new();
502 text.push_str("trait ");
503 let mut sig = name_and_generics(text,
510 if !bounds.is_empty() {
511 sig.text.push_str(" = ");
512 sig.text.push_str(&pprust::bounds_to_string(bounds));
514 // FIXME where clause
515 sig.text.push_str(";");
528 let mut text = String::new();
529 if let ast::Defaultness::Default = defaultness {
530 text.push_str("default ");
532 if unsafety == ast::Unsafety::Unsafe {
533 text.push_str("unsafe ");
535 text.push_str("impl");
537 let generics_sig = generics.make(offset + text.len(), id, scx)?;
538 text.push_str(&generics_sig.text);
542 let trait_sig = if let Some(ref t) = *opt_trait {
543 if polarity == ast::ImplPolarity::Negative {
546 let trait_sig = t.path.make(offset + text.len(), id, scx)?;
547 text.push_str(&trait_sig.text);
548 text.push_str(" for ");
551 text_sig(String::new())
554 let ty_sig = ty.make(offset + text.len(), id, scx)?;
555 text.push_str(&ty_sig.text);
557 text.push_str(" {}");
559 Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
561 // FIXME where clause
563 ast::ItemKind::ForeignMod(_) => Err("extern mod"),
564 ast::ItemKind::GlobalAsm(_) => Err("glboal asm"),
565 ast::ItemKind::ExternCrate(_) => Err("extern crate"),
566 // FIXME should implement this (e.g., pub use).
567 ast::ItemKind::Use(_) => Err("import"),
568 ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
573 impl Sig for ast::Path {
574 fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
575 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
577 let (name, start, end) = match res {
578 Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => {
579 return Ok(Signature {
580 text: pprust::path_to_string(self),
585 Res::Def(DefKind::AssocConst, _)
586 | Res::Def(DefKind::Variant, _)
587 | Res::Def(DefKind::Ctor(..), _) => {
588 let len = self.segments.len();
590 return Err("Bad path");
592 // FIXME: really we should descend into the generics here and add SigElements for
594 // FIXME: would be nice to have a def for the first path segment.
595 let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]);
596 let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]);
597 let start = offset + seg1.len() + 2;
598 (format!("{}::{}", seg1, seg2), start, start + seg2.len())
601 let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?);
602 let end = offset + name.len();
607 let id = id_from_def_id(res.def_id());
611 refs: vec![SigElement { id, start, end }],
616 // This does not cover the where clause, which must be processed separately.
617 impl Sig for ast::Generics {
618 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
619 if self.params.is_empty() {
620 return Ok(text_sig(String::new()));
623 let mut text = "<".to_owned();
625 let mut defs = Vec::with_capacity(self.params.len());
626 for param in &self.params {
627 let mut param_text = String::new();
628 if let ast::GenericParamKind::Const { .. } = param.kind {
629 param_text.push_str("const ");
631 param_text.push_str(¶m.ident.as_str());
632 defs.push(SigElement {
633 id: id_from_node_id(param.id, scx),
634 start: offset + text.len(),
635 end: offset + text.len() + param_text.as_str().len(),
637 if let ast::GenericParamKind::Const { ref ty } = param.kind {
638 param_text.push_str(": ");
639 param_text.push_str(&pprust::ty_to_string(&ty));
641 if !param.bounds.is_empty() {
642 param_text.push_str(": ");
644 ast::GenericParamKind::Lifetime { .. } => {
645 let bounds = param.bounds.iter()
646 .map(|bound| match bound {
647 ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
652 param_text.push_str(&bounds);
653 // FIXME add lifetime bounds refs.
655 ast::GenericParamKind::Type { .. } => {
656 param_text.push_str(&pprust::bounds_to_string(¶m.bounds));
657 // FIXME descend properly into bounds.
659 ast::GenericParamKind::Const { .. } => {
660 // Const generics cannot contain bounds.
664 text.push_str(¶m_text);
677 impl Sig for ast::StructField {
678 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
679 let mut text = String::new();
681 if let Some(ident) = self.ident {
682 text.push_str(&ident.to_string());
683 defs = Some(SigElement {
684 id: id_from_node_id(self.id, scx),
686 end: offset + text.len(),
691 let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?;
692 text.push_str(&ty_sig.text);
694 ty_sig.defs.extend(defs.into_iter());
700 impl Sig for ast::Variant {
701 fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
702 let mut text = self.ident.to_string();
704 ast::VariantData::Struct(ref fields, r) => {
705 let id = parent_id.unwrap();
706 let name_def = SigElement {
707 id: id_from_node_id(id, scx),
709 end: offset + text.len(),
711 text.push_str(" { ");
712 let mut defs = vec![name_def];
713 let mut refs = vec![];
715 text.push_str("/* parse error */ ");
718 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
719 text.push_str(&field_sig.text);
721 defs.extend(field_sig.defs.into_iter());
722 refs.extend(field_sig.refs.into_iter());
726 Ok(Signature { text, defs, refs })
728 ast::VariantData::Tuple(ref fields, id) => {
729 let name_def = SigElement {
730 id: id_from_node_id(id, scx),
732 end: offset + text.len(),
735 let mut defs = vec![name_def];
736 let mut refs = vec![];
738 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
739 text.push_str(&field_sig.text);
741 defs.extend(field_sig.defs.into_iter());
742 refs.extend(field_sig.refs.into_iter());
745 Ok(Signature { text, defs, refs })
747 ast::VariantData::Unit(id) => {
748 let name_def = SigElement {
749 id: id_from_node_id(id, scx),
751 end: offset + text.len(),
755 defs: vec![name_def],
763 impl Sig for ast::ForeignItem {
764 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
765 let id = Some(self.id);
767 ast::ForeignItemKind::Fn(ref decl, ref generics) => {
768 let mut text = String::new();
769 text.push_str("fn ");
771 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
774 for i in &decl.inputs {
775 // FIXME should descend into patterns to add defs.
776 sig.text.push_str(&pprust::pat_to_string(&i.pat));
777 sig.text.push_str(": ");
778 let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
779 sig.text.push_str(&nested.text);
781 sig.defs.extend(nested.defs.into_iter());
782 sig.refs.extend(nested.refs.into_iter());
786 if let ast::FunctionRetTy::Ty(ref t) = decl.output {
787 sig.text.push_str(" -> ");
788 let nested = t.make(offset + sig.text.len(), None, scx)?;
789 sig.text.push_str(&nested.text);
790 sig.defs.extend(nested.defs.into_iter());
791 sig.refs.extend(nested.refs.into_iter());
797 ast::ForeignItemKind::Static(ref ty, m) => {
798 let mut text = "static ".to_owned();
799 if m == ast::Mutability::Mutable {
800 text.push_str("mut ");
802 let name = self.ident.to_string();
805 id: id_from_node_id(self.id, scx),
806 start: offset + text.len(),
807 end: offset + text.len() + name.len(),
810 text.push_str(&name);
813 let ty_sig = ty.make(offset + text.len(), id, scx)?;
816 Ok(extend_sig(ty_sig, text, defs, vec![]))
818 ast::ForeignItemKind::Ty => {
819 let mut text = "type ".to_owned();
820 let name = self.ident.to_string();
823 id: id_from_node_id(self.id, scx),
824 start: offset + text.len(),
825 end: offset + text.len() + name.len(),
828 text.push_str(&name);
837 ast::ForeignItemKind::Macro(..) => Err("macro"),
842 fn name_and_generics(
845 generics: &ast::Generics,
848 scx: &SaveContext<'_, '_>,
850 let name = name.to_string();
851 let def = SigElement {
852 id: id_from_node_id(id, scx),
853 start: offset + text.len(),
854 end: offset + text.len() + name.len(),
856 text.push_str(&name);
857 let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
858 // FIXME where clause
859 let text = format!("{}{}", text, generics.text);
860 Ok(extend_sig(generics, text, vec![def], vec![]))
864 fn make_assoc_type_signature(
867 bounds: Option<&ast::GenericBounds>,
868 default: Option<&ast::Ty>,
869 scx: &SaveContext<'_, '_>,
871 let mut text = "type ".to_owned();
872 let name = ident.to_string();
875 id: id_from_node_id(id, scx),
877 end: text.len() + name.len(),
880 let mut refs = vec![];
881 text.push_str(&name);
882 if let Some(bounds) = bounds {
884 // FIXME should descend into bounds
885 text.push_str(&pprust::bounds_to_string(bounds));
887 if let Some(default) = default {
888 text.push_str(" = ");
889 let ty_sig = default.make(text.len(), Some(id), scx)?;
890 text.push_str(&ty_sig.text);
891 defs.extend(ty_sig.defs.into_iter());
892 refs.extend(ty_sig.refs.into_iter());
895 Ok(Signature { text, defs, refs })
898 fn make_assoc_const_signature(
902 default: Option<&ast::Expr>,
903 scx: &SaveContext<'_, '_>,
905 let mut text = "const ".to_owned();
906 let name = ident.to_string();
909 id: id_from_node_id(id, scx),
911 end: text.len() + name.len(),
914 let mut refs = vec![];
915 text.push_str(&name);
918 let ty_sig = ty.make(text.len(), Some(id), scx)?;
919 text.push_str(&ty_sig.text);
920 defs.extend(ty_sig.defs.into_iter());
921 refs.extend(ty_sig.refs.into_iter());
923 if let Some(default) = default {
924 text.push_str(" = ");
925 text.push_str(&pprust::expr_to_string(default));
928 Ok(Signature { text, defs, refs })
931 fn make_method_signature(
934 generics: &ast::Generics,
936 scx: &SaveContext<'_, '_>,
938 // FIXME code dup with function signature
939 let mut text = String::new();
940 if m.header.constness.node == ast::Constness::Const {
941 text.push_str("const ");
943 if m.header.asyncness.node.is_async() {
944 text.push_str("async ");
946 if m.header.unsafety == ast::Unsafety::Unsafe {
947 text.push_str("unsafe ");
949 push_abi(&mut text, m.header.abi);
950 text.push_str("fn ");
952 let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
955 for i in &m.decl.inputs {
956 // FIXME should descend into patterns to add defs.
957 sig.text.push_str(&pprust::pat_to_string(&i.pat));
958 sig.text.push_str(": ");
959 let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?;
960 sig.text.push_str(&nested.text);
962 sig.defs.extend(nested.defs.into_iter());
963 sig.refs.extend(nested.refs.into_iter());
967 if let ast::FunctionRetTy::Ty(ref t) = m.decl.output {
968 sig.text.push_str(" -> ");
969 let nested = t.make(sig.text.len(), None, scx)?;
970 sig.text.push_str(&nested.text);
971 sig.defs.extend(nested.defs.into_iter());
972 sig.refs.extend(nested.refs.into_iter());
974 sig.text.push_str(" {}");