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.node.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 impl Sig for ast::Ty {
161 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
162 let id = Some(self.id);
164 ast::TyKind::Slice(ref ty) => {
165 let nested = ty.make(offset + 1, id, scx)?;
166 let text = format!("[{}]", nested.text);
167 Ok(replace_text(nested, text))
169 ast::TyKind::Ptr(ref mt) => {
170 let prefix = match mt.mutbl {
171 ast::Mutability::Mutable => "*mut ",
172 ast::Mutability::Immutable => "*const ",
174 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
175 let text = format!("{}{}", prefix, nested.text);
176 Ok(replace_text(nested, text))
178 ast::TyKind::Rptr(ref lifetime, ref mt) => {
179 let mut prefix = "&".to_owned();
180 if let &Some(ref l) = lifetime {
181 prefix.push_str(&l.ident.to_string());
184 if let ast::Mutability::Mutable = mt.mutbl {
185 prefix.push_str("mut ");
188 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
189 let text = format!("{}{}", prefix, nested.text);
190 Ok(replace_text(nested, text))
192 ast::TyKind::Never => Ok(text_sig("!".to_owned())),
193 ast::TyKind::CVarArgs => Ok(text_sig("...".to_owned())),
194 ast::TyKind::Tup(ref ts) => {
195 let mut text = "(".to_owned();
196 let mut defs = vec![];
197 let mut refs = vec![];
199 let nested = t.make(offset + text.len(), id, scx)?;
200 text.push_str(&nested.text);
202 defs.extend(nested.defs.into_iter());
203 refs.extend(nested.refs.into_iter());
206 Ok(Signature { text, defs, refs })
208 ast::TyKind::Paren(ref ty) => {
209 let nested = ty.make(offset + 1, id, scx)?;
210 let text = format!("({})", nested.text);
211 Ok(replace_text(nested, text))
213 ast::TyKind::BareFn(ref f) => {
214 let mut text = String::new();
215 if !f.generic_params.is_empty() {
216 // FIXME defs, bounds on lifetimes
217 text.push_str("for<");
218 text.push_str(&f.generic_params
220 .filter_map(|param| match param.kind {
221 ast::GenericParamKind::Lifetime { .. } => {
222 Some(param.ident.to_string())
231 if f.unsafety == ast::Unsafety::Unsafe {
232 text.push_str("unsafe ");
234 if f.abi != rustc_target::spec::abi::Abi::Rust {
235 text.push_str("extern");
236 text.push_str(&f.abi.to_string());
239 text.push_str("fn(");
241 let mut defs = vec![];
242 let mut refs = vec![];
243 for i in &f.decl.inputs {
244 let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?;
245 text.push_str(&nested.text);
247 defs.extend(nested.defs.into_iter());
248 refs.extend(nested.refs.into_iter());
251 if let ast::FunctionRetTy::Ty(ref t) = f.decl.output {
252 text.push_str(" -> ");
253 let nested = t.make(offset + text.len(), None, scx)?;
254 text.push_str(&nested.text);
256 defs.extend(nested.defs.into_iter());
257 refs.extend(nested.refs.into_iter());
260 Ok(Signature { text, defs, refs })
262 ast::TyKind::Path(None, ref path) => path.make(offset, id, scx),
263 ast::TyKind::Path(Some(ref qself), ref path) => {
264 let nested_ty = qself.ty.make(offset + 1, id, scx)?;
265 let prefix = if qself.position == 0 {
266 format!("<{}>::", nested_ty.text)
267 } else if qself.position == 1 {
268 let first = pprust::path_segment_to_string(&path.segments[0]);
269 format!("<{} as {}>::", nested_ty.text, first)
271 // FIXME handle path instead of elipses.
272 format!("<{} as ...>::", nested_ty.text)
275 let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?);
276 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
277 let id = id_from_def_id(res.def_id());
278 if path.segments.len() - qself.position == 1 {
279 let start = offset + prefix.len();
280 let end = start + name.len();
283 text: prefix + &name,
285 refs: vec![SigElement { id, start, end }],
288 let start = offset + prefix.len() + 5;
289 let end = start + name.len();
290 // FIXME should put the proper path in there, not elipses.
292 text: prefix + "...::" + &name,
294 refs: vec![SigElement { id, start, end }],
298 ast::TyKind::TraitObject(ref bounds, ..) => {
299 // FIXME recurse into bounds
300 let nested = pprust::bounds_to_string(bounds);
303 ast::TyKind::ImplTrait(_, ref bounds) => {
304 // FIXME recurse into bounds
305 let nested = pprust::bounds_to_string(bounds);
306 Ok(text_sig(format!("impl {}", nested)))
308 ast::TyKind::Array(ref ty, ref v) => {
309 let nested_ty = ty.make(offset + 1, id, scx)?;
310 let expr = pprust::expr_to_string(&v.value).replace('\n', " ");
311 let text = format!("[{}; {}]", nested_ty.text, expr);
312 Ok(replace_text(nested_ty, text))
314 ast::TyKind::Typeof(_) |
317 ast::TyKind::ImplicitSelf |
318 ast::TyKind::Mac(_) => Err("Ty"),
323 impl Sig for ast::Item {
324 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
325 let id = Some(self.id);
328 ast::ItemKind::Static(ref ty, m, ref expr) => {
329 let mut text = "static ".to_owned();
330 if m == ast::Mutability::Mutable {
331 text.push_str("mut ");
333 let name = self.ident.to_string();
336 id: id_from_node_id(self.id, scx),
337 start: offset + text.len(),
338 end: offset + text.len() + name.len(),
341 text.push_str(&name);
344 let ty = ty.make(offset + text.len(), id, scx)?;
345 text.push_str(&ty.text);
346 text.push_str(" = ");
348 let expr = pprust::expr_to_string(expr).replace('\n', " ");
349 text.push_str(&expr);
352 Ok(extend_sig(ty, text, defs, vec![]))
354 ast::ItemKind::Const(ref ty, ref expr) => {
355 let mut text = "const ".to_owned();
356 let name = self.ident.to_string();
359 id: id_from_node_id(self.id, scx),
360 start: offset + text.len(),
361 end: offset + text.len() + name.len(),
364 text.push_str(&name);
367 let ty = ty.make(offset + text.len(), id, scx)?;
368 text.push_str(&ty.text);
369 text.push_str(" = ");
371 let expr = pprust::expr_to_string(expr).replace('\n', " ");
372 text.push_str(&expr);
375 Ok(extend_sig(ty, text, defs, vec![]))
377 ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
378 let mut text = String::new();
379 if header.constness.node == ast::Constness::Const {
380 text.push_str("const ");
382 if header.asyncness.node.is_async() {
383 text.push_str("async ");
385 if header.unsafety == ast::Unsafety::Unsafe {
386 text.push_str("unsafe ");
388 if header.abi != rustc_target::spec::abi::Abi::Rust {
389 text.push_str("extern");
390 text.push_str(&header.abi.to_string());
393 text.push_str("fn ");
395 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
398 for i in &decl.inputs {
399 // FIXME should descend into patterns to add defs.
400 sig.text.push_str(&pprust::pat_to_string(&i.pat));
401 sig.text.push_str(": ");
402 let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
403 sig.text.push_str(&nested.text);
405 sig.defs.extend(nested.defs.into_iter());
406 sig.refs.extend(nested.refs.into_iter());
410 if let ast::FunctionRetTy::Ty(ref t) = decl.output {
411 sig.text.push_str(" -> ");
412 let nested = t.make(offset + sig.text.len(), None, scx)?;
413 sig.text.push_str(&nested.text);
414 sig.defs.extend(nested.defs.into_iter());
415 sig.refs.extend(nested.refs.into_iter());
417 sig.text.push_str(" {}");
421 ast::ItemKind::Mod(ref _mod) => {
422 let mut text = "mod ".to_owned();
423 let name = self.ident.to_string();
426 id: id_from_node_id(self.id, scx),
427 start: offset + text.len(),
428 end: offset + text.len() + name.len(),
431 text.push_str(&name);
432 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
441 ast::ItemKind::Existential(ref bounds, ref generics) => {
442 let text = "existential type ".to_owned();
443 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
445 if !bounds.is_empty() {
446 sig.text.push_str(": ");
447 sig.text.push_str(&pprust::bounds_to_string(bounds));
453 ast::ItemKind::Ty(ref ty, ref generics) => {
454 let text = "type ".to_owned();
455 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
457 sig.text.push_str(" = ");
458 let ty = ty.make(offset + sig.text.len(), id, scx)?;
459 sig.text.push_str(&ty.text);
462 Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
464 ast::ItemKind::Enum(_, ref generics) => {
465 let text = "enum ".to_owned();
466 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
467 sig.text.push_str(" {}");
470 ast::ItemKind::Struct(_, ref generics) => {
471 let text = "struct ".to_owned();
472 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
473 sig.text.push_str(" {}");
476 ast::ItemKind::Union(_, ref generics) => {
477 let text = "union ".to_owned();
478 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
479 sig.text.push_str(" {}");
482 ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
483 let mut text = String::new();
485 if is_auto == ast::IsAuto::Yes {
486 text.push_str("auto ");
489 if unsafety == ast::Unsafety::Unsafe {
490 text.push_str("unsafe ");
492 text.push_str("trait ");
493 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
495 if !bounds.is_empty() {
496 sig.text.push_str(": ");
497 sig.text.push_str(&pprust::bounds_to_string(bounds));
499 // FIXME where clause
500 sig.text.push_str(" {}");
504 ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
505 let mut text = String::new();
506 text.push_str("trait ");
507 let mut sig = name_and_generics(text,
514 if !bounds.is_empty() {
515 sig.text.push_str(" = ");
516 sig.text.push_str(&pprust::bounds_to_string(bounds));
518 // FIXME where clause
519 sig.text.push_str(";");
532 let mut text = String::new();
533 if let ast::Defaultness::Default = defaultness {
534 text.push_str("default ");
536 if unsafety == ast::Unsafety::Unsafe {
537 text.push_str("unsafe ");
539 text.push_str("impl");
541 let generics_sig = generics.make(offset + text.len(), id, scx)?;
542 text.push_str(&generics_sig.text);
546 let trait_sig = if let Some(ref t) = *opt_trait {
547 if polarity == ast::ImplPolarity::Negative {
550 let trait_sig = t.path.make(offset + text.len(), id, scx)?;
551 text.push_str(&trait_sig.text);
552 text.push_str(" for ");
555 text_sig(String::new())
558 let ty_sig = ty.make(offset + text.len(), id, scx)?;
559 text.push_str(&ty_sig.text);
561 text.push_str(" {}");
563 Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
565 // FIXME where clause
567 ast::ItemKind::ForeignMod(_) => Err("extern mod"),
568 ast::ItemKind::GlobalAsm(_) => Err("glboal asm"),
569 ast::ItemKind::ExternCrate(_) => Err("extern crate"),
570 // FIXME should implement this (e.g., pub use).
571 ast::ItemKind::Use(_) => Err("import"),
572 ast::ItemKind::Mac(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
577 impl Sig for ast::Path {
578 fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
579 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
581 let (name, start, end) = match res {
582 Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => {
583 return Ok(Signature {
584 text: pprust::path_to_string(self),
589 Res::Def(DefKind::AssocConst, _)
590 | Res::Def(DefKind::Variant, _)
591 | Res::Def(DefKind::Ctor(..), _) => {
592 let len = self.segments.len();
594 return Err("Bad path");
596 // FIXME: really we should descend into the generics here and add SigElements for
598 // FIXME: would be nice to have a def for the first path segment.
599 let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]);
600 let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]);
601 let start = offset + seg1.len() + 2;
602 (format!("{}::{}", seg1, seg2), start, start + seg2.len())
605 let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?);
606 let end = offset + name.len();
611 let id = id_from_def_id(res.def_id());
615 refs: vec![SigElement { id, start, end }],
620 // This does not cover the where clause, which must be processed separately.
621 impl Sig for ast::Generics {
622 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
623 if self.params.is_empty() {
624 return Ok(text_sig(String::new()));
627 let mut text = "<".to_owned();
629 let mut defs = Vec::with_capacity(self.params.len());
630 for param in &self.params {
631 let mut param_text = String::new();
632 if let ast::GenericParamKind::Const { .. } = param.kind {
633 param_text.push_str("const ");
635 param_text.push_str(¶m.ident.as_str());
636 defs.push(SigElement {
637 id: id_from_node_id(param.id, scx),
638 start: offset + text.len(),
639 end: offset + text.len() + param_text.as_str().len(),
641 if let ast::GenericParamKind::Const { ref ty } = param.kind {
642 param_text.push_str(": ");
643 param_text.push_str(&pprust::ty_to_string(&ty));
645 if !param.bounds.is_empty() {
646 param_text.push_str(": ");
648 ast::GenericParamKind::Lifetime { .. } => {
649 let bounds = param.bounds.iter()
650 .map(|bound| match bound {
651 ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
656 param_text.push_str(&bounds);
657 // FIXME add lifetime bounds refs.
659 ast::GenericParamKind::Type { .. } => {
660 param_text.push_str(&pprust::bounds_to_string(¶m.bounds));
661 // FIXME descend properly into bounds.
663 ast::GenericParamKind::Const { .. } => {
664 // Const generics cannot contain bounds.
668 text.push_str(¶m_text);
681 impl Sig for ast::StructField {
682 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
683 let mut text = String::new();
685 if let Some(ident) = self.ident {
686 text.push_str(&ident.to_string());
687 defs = Some(SigElement {
688 id: id_from_node_id(self.id, scx),
690 end: offset + text.len(),
695 let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?;
696 text.push_str(&ty_sig.text);
698 ty_sig.defs.extend(defs.into_iter());
704 impl Sig for ast::Variant_ {
705 fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
706 let mut text = self.ident.to_string();
708 ast::VariantData::Struct(ref fields, r) => {
709 let id = parent_id.unwrap();
710 let name_def = SigElement {
711 id: id_from_node_id(id, scx),
713 end: offset + text.len(),
715 text.push_str(" { ");
716 let mut defs = vec![name_def];
717 let mut refs = vec![];
719 text.push_str("/* parse error */ ");
722 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
723 text.push_str(&field_sig.text);
725 defs.extend(field_sig.defs.into_iter());
726 refs.extend(field_sig.refs.into_iter());
730 Ok(Signature { text, defs, refs })
732 ast::VariantData::Tuple(ref fields, id) => {
733 let name_def = SigElement {
734 id: id_from_node_id(id, scx),
736 end: offset + text.len(),
739 let mut defs = vec![name_def];
740 let mut refs = vec![];
742 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
743 text.push_str(&field_sig.text);
745 defs.extend(field_sig.defs.into_iter());
746 refs.extend(field_sig.refs.into_iter());
749 Ok(Signature { text, defs, refs })
751 ast::VariantData::Unit(id) => {
752 let name_def = SigElement {
753 id: id_from_node_id(id, scx),
755 end: offset + text.len(),
759 defs: vec![name_def],
767 impl Sig for ast::ForeignItem {
768 fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
769 let id = Some(self.id);
771 ast::ForeignItemKind::Fn(ref decl, ref generics) => {
772 let mut text = String::new();
773 text.push_str("fn ");
775 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
778 for i in &decl.inputs {
779 // FIXME should descend into patterns to add defs.
780 sig.text.push_str(&pprust::pat_to_string(&i.pat));
781 sig.text.push_str(": ");
782 let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
783 sig.text.push_str(&nested.text);
785 sig.defs.extend(nested.defs.into_iter());
786 sig.refs.extend(nested.refs.into_iter());
790 if let ast::FunctionRetTy::Ty(ref t) = decl.output {
791 sig.text.push_str(" -> ");
792 let nested = t.make(offset + sig.text.len(), None, scx)?;
793 sig.text.push_str(&nested.text);
794 sig.defs.extend(nested.defs.into_iter());
795 sig.refs.extend(nested.refs.into_iter());
801 ast::ForeignItemKind::Static(ref ty, m) => {
802 let mut text = "static ".to_owned();
803 if m == ast::Mutability::Mutable {
804 text.push_str("mut ");
806 let name = self.ident.to_string();
809 id: id_from_node_id(self.id, scx),
810 start: offset + text.len(),
811 end: offset + text.len() + name.len(),
814 text.push_str(&name);
817 let ty_sig = ty.make(offset + text.len(), id, scx)?;
820 Ok(extend_sig(ty_sig, text, defs, vec![]))
822 ast::ForeignItemKind::Ty => {
823 let mut text = "type ".to_owned();
824 let name = self.ident.to_string();
827 id: id_from_node_id(self.id, scx),
828 start: offset + text.len(),
829 end: offset + text.len() + name.len(),
832 text.push_str(&name);
841 ast::ForeignItemKind::Macro(..) => Err("macro"),
846 fn name_and_generics(
849 generics: &ast::Generics,
852 scx: &SaveContext<'_, '_>,
854 let name = name.to_string();
855 let def = SigElement {
856 id: id_from_node_id(id, scx),
857 start: offset + text.len(),
858 end: offset + text.len() + name.len(),
860 text.push_str(&name);
861 let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
862 // FIXME where clause
863 let text = format!("{}{}", text, generics.text);
864 Ok(extend_sig(generics, text, vec![def], vec![]))
868 fn make_assoc_type_signature(
871 bounds: Option<&ast::GenericBounds>,
872 default: Option<&ast::Ty>,
873 scx: &SaveContext<'_, '_>,
875 let mut text = "type ".to_owned();
876 let name = ident.to_string();
879 id: id_from_node_id(id, scx),
881 end: text.len() + name.len(),
884 let mut refs = vec![];
885 text.push_str(&name);
886 if let Some(bounds) = bounds {
888 // FIXME should descend into bounds
889 text.push_str(&pprust::bounds_to_string(bounds));
891 if let Some(default) = default {
892 text.push_str(" = ");
893 let ty_sig = default.make(text.len(), Some(id), scx)?;
894 text.push_str(&ty_sig.text);
895 defs.extend(ty_sig.defs.into_iter());
896 refs.extend(ty_sig.refs.into_iter());
899 Ok(Signature { text, defs, refs })
902 fn make_assoc_const_signature(
906 default: Option<&ast::Expr>,
907 scx: &SaveContext<'_, '_>,
909 let mut text = "const ".to_owned();
910 let name = ident.to_string();
913 id: id_from_node_id(id, scx),
915 end: text.len() + name.len(),
918 let mut refs = vec![];
919 text.push_str(&name);
922 let ty_sig = ty.make(text.len(), Some(id), scx)?;
923 text.push_str(&ty_sig.text);
924 defs.extend(ty_sig.defs.into_iter());
925 refs.extend(ty_sig.refs.into_iter());
927 if let Some(default) = default {
928 text.push_str(" = ");
929 text.push_str(&pprust::expr_to_string(default));
932 Ok(Signature { text, defs, refs })
935 fn make_method_signature(
938 generics: &ast::Generics,
940 scx: &SaveContext<'_, '_>,
942 // FIXME code dup with function signature
943 let mut text = String::new();
944 if m.header.constness.node == ast::Constness::Const {
945 text.push_str("const ");
947 if m.header.asyncness.node.is_async() {
948 text.push_str("async ");
950 if m.header.unsafety == ast::Unsafety::Unsafe {
951 text.push_str("unsafe ");
953 if m.header.abi != rustc_target::spec::abi::Abi::Rust {
954 text.push_str("extern");
955 text.push_str(&m.header.abi.to_string());
958 text.push_str("fn ");
960 let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
963 for i in &m.decl.inputs {
964 // FIXME should descend into patterns to add defs.
965 sig.text.push_str(&pprust::pat_to_string(&i.pat));
966 sig.text.push_str(": ");
967 let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?;
968 sig.text.push_str(&nested.text);
970 sig.defs.extend(nested.defs.into_iter());
971 sig.refs.extend(nested.refs.into_iter());
975 if let ast::FunctionRetTy::Ty(ref t) = m.decl.output {
976 sig.text.push_str(" -> ");
977 let nested = t.make(sig.text.len(), None, scx)?;
978 sig.text.push_str(&nested.text);
979 sig.defs.extend(nested.defs.into_iter());
980 sig.refs.extend(nested.refs.into_iter());
982 sig.text.push_str(" {}");