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_hir_id, SaveContext};
30 use rls_data::{SigElement, Signature};
32 use rustc_ast::ast::Mutability;
34 use rustc_hir::def::{DefKind, Res};
35 use rustc_hir_pretty::id_to_string;
36 use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
37 use rustc_span::symbol::{Ident, Symbol};
39 pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
40 if !scx.config.signatures {
43 item.make(0, None, scx).ok()
46 pub fn foreign_item_signature(
47 item: &hir::ForeignItem<'_>,
48 scx: &SaveContext<'_>,
49 ) -> Option<Signature> {
50 if !scx.config.signatures {
53 item.make(0, None, scx).ok()
56 /// Signature for a struct or tuple field declaration.
57 /// Does not include a trailing comma.
58 pub fn field_signature(field: &hir::StructField<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
59 if !scx.config.signatures {
62 field.make(0, None, scx).ok()
65 /// Does not include a trailing comma.
66 pub fn variant_signature(variant: &hir::Variant<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
67 if !scx.config.signatures {
70 variant.make(0, None, scx).ok()
73 pub fn method_signature(
76 generics: &hir::Generics<'_>,
78 scx: &SaveContext<'_>,
79 ) -> Option<Signature> {
80 if !scx.config.signatures {
83 make_method_signature(id, ident, generics, m, scx).ok()
86 pub fn assoc_const_signature(
90 default: Option<&hir::Expr<'_>>,
91 scx: &SaveContext<'_>,
92 ) -> Option<Signature> {
93 if !scx.config.signatures {
96 make_assoc_const_signature(id, ident, ty, default, scx).ok()
99 pub fn assoc_type_signature(
102 bounds: Option<hir::GenericBounds<'_>>,
103 default: Option<&hir::Ty<'_>>,
104 scx: &SaveContext<'_>,
105 ) -> Option<Signature> {
106 if !scx.config.signatures {
109 make_assoc_type_signature(id, ident, bounds, default, scx).ok()
112 type Result = std::result::Result<Signature, &'static str>;
115 fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result;
121 defs: Vec<SigElement>,
122 refs: Vec<SigElement>,
125 sig.defs.extend(defs.into_iter());
126 sig.refs.extend(refs.into_iter());
130 fn replace_text(mut sig: Signature, text: String) -> Signature {
135 fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
136 let mut result = Signature { text, defs: vec![], refs: vec![] };
138 let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
140 result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
141 result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
146 fn text_sig(text: String) -> Signature {
147 Signature { text, defs: vec![], refs: vec![] }
150 impl<'hir> Sig for hir::Ty<'hir> {
151 fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
152 let id = Some(self.hir_id);
154 hir::TyKind::Slice(ref ty) => {
155 let nested = ty.make(offset + 1, id, scx)?;
156 let text = format!("[{}]", nested.text);
157 Ok(replace_text(nested, text))
159 hir::TyKind::Ptr(ref mt) => {
160 let prefix = match mt.mutbl {
161 hir::Mutability::Mut => "*mut ",
162 hir::Mutability::Not => "*const ",
164 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
165 let text = format!("{}{}", prefix, nested.text);
166 Ok(replace_text(nested, text))
168 hir::TyKind::Rptr(ref lifetime, ref mt) => {
169 let mut prefix = "&".to_owned();
170 prefix.push_str(&lifetime.name.ident().to_string());
172 if let hir::Mutability::Mut = mt.mutbl {
173 prefix.push_str("mut ");
176 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
177 let text = format!("{}{}", prefix, nested.text);
178 Ok(replace_text(nested, text))
180 hir::TyKind::Never => Ok(text_sig("!".to_owned())),
181 hir::TyKind::Tup(ts) => {
182 let mut text = "(".to_owned();
183 let mut defs = vec![];
184 let mut refs = vec![];
186 let nested = t.make(offset + text.len(), id, scx)?;
187 text.push_str(&nested.text);
189 defs.extend(nested.defs.into_iter());
190 refs.extend(nested.refs.into_iter());
193 Ok(Signature { text, defs, refs })
195 hir::TyKind::BareFn(ref f) => {
196 let mut text = String::new();
197 if !f.generic_params.is_empty() {
198 // FIXME defs, bounds on lifetimes
199 text.push_str("for<");
203 .filter_map(|param| match param.kind {
204 hir::GenericParamKind::Lifetime { .. } => {
205 Some(param.name.ident().to_string())
215 if let hir::Unsafety::Unsafe = f.unsafety {
216 text.push_str("unsafe ");
218 text.push_str("fn(");
220 let mut defs = vec![];
221 let mut refs = vec![];
222 for i in f.decl.inputs {
223 let nested = i.make(offset + text.len(), Some(i.hir_id), scx)?;
224 text.push_str(&nested.text);
226 defs.extend(nested.defs.into_iter());
227 refs.extend(nested.refs.into_iter());
230 if let hir::FnRetTy::Return(ref t) = f.decl.output {
231 text.push_str(" -> ");
232 let nested = t.make(offset + text.len(), None, scx)?;
233 text.push_str(&nested.text);
235 defs.extend(nested.defs.into_iter());
236 refs.extend(nested.refs.into_iter());
239 Ok(Signature { text, defs, refs })
241 hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.make(offset, id, scx),
242 hir::TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref path)) => {
243 let nested_ty = qself.make(offset + 1, id, scx)?;
244 let prefix = format!(
247 path_segment_to_string(&path.segments[0])
250 let name = path_segment_to_string(path.segments.last().ok_or("Bad path")?);
251 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
252 let id = id_from_def_id(res.def_id());
253 if path.segments.len() == 2 {
254 let start = offset + prefix.len();
255 let end = start + name.len();
258 text: prefix + &name,
260 refs: vec![SigElement { id, start, end }],
263 let start = offset + prefix.len() + 5;
264 let end = start + name.len();
265 // FIXME should put the proper path in there, not elipses.
267 text: prefix + "...::" + &name,
269 refs: vec![SigElement { id, start, end }],
273 hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
274 let nested_ty = ty.make(offset + 1, id, scx)?;
275 let prefix = format!("<{}>::", nested_ty.text,);
277 let name = path_segment_to_string(segment);
278 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
279 let id = id_from_def_id(res.def_id());
281 let start = offset + prefix.len();
282 let end = start + name.len();
284 text: prefix + &name,
286 refs: vec![SigElement { id, start, end }],
289 hir::TyKind::TraitObject(bounds, ..) => {
290 // FIXME recurse into bounds
291 let bounds: Vec<hir::GenericBound<'_>> = bounds
293 .map(|hir::PolyTraitRef { bound_generic_params, trait_ref, span }| {
294 hir::GenericBound::Trait(
296 bound_generic_params,
297 trait_ref: hir::TraitRef {
298 path: trait_ref.path,
299 hir_ref_id: trait_ref.hir_ref_id,
303 hir::TraitBoundModifier::None,
307 let nested = bounds_to_string(&bounds);
310 hir::TyKind::Array(ref ty, ref anon_const) => {
311 let nested_ty = ty.make(offset + 1, id, scx)?;
312 let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " ");
313 let text = format!("[{}; {}]", nested_ty.text, expr);
314 Ok(replace_text(nested_ty, text))
316 hir::TyKind::OpaqueDef(item_id, _) => {
317 let item = scx.tcx.hir().item(item_id.id);
318 item.make(offset, Some(item_id.id), scx)
320 hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
325 impl<'hir> Sig for hir::Item<'hir> {
326 fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
327 let id = Some(self.hir_id);
330 hir::ItemKind::Static(ref ty, m, ref body) => {
331 let mut text = "static ".to_owned();
332 if m == hir::Mutability::Mut {
333 text.push_str("mut ");
335 let name = self.ident.to_string();
336 let defs = vec![SigElement {
337 id: id_from_hir_id(self.hir_id, scx),
338 start: offset + text.len(),
339 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);
347 text.push_str(" = ");
348 let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
349 text.push_str(&expr);
353 Ok(extend_sig(ty, text, defs, vec![]))
355 hir::ItemKind::Const(ref ty, ref body) => {
356 let mut text = "const ".to_owned();
357 let name = self.ident.to_string();
358 let defs = vec![SigElement {
359 id: id_from_hir_id(self.hir_id, scx),
360 start: offset + text.len(),
361 end: offset + text.len() + name.len(),
363 text.push_str(&name);
366 let ty = ty.make(offset + text.len(), id, scx)?;
367 text.push_str(&ty.text);
369 text.push_str(" = ");
370 let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
371 text.push_str(&expr);
375 Ok(extend_sig(ty, text, defs, vec![]))
377 hir::ItemKind::Fn(hir::FnSig { ref decl, header }, ref generics, _) => {
378 let mut text = String::new();
379 if let hir::Constness::Const = header.constness {
380 text.push_str("const ");
382 if hir::IsAsync::Async == header.asyncness {
383 text.push_str("async ");
385 if let hir::Unsafety::Unsafe = header.unsafety {
386 text.push_str("unsafe ");
388 text.push_str("fn ");
391 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
394 for i in decl.inputs {
395 // FIXME should descend into patterns to add defs.
396 sig.text.push_str(": ");
397 let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
398 sig.text.push_str(&nested.text);
400 sig.defs.extend(nested.defs.into_iter());
401 sig.refs.extend(nested.refs.into_iter());
405 if let hir::FnRetTy::Return(ref t) = decl.output {
406 sig.text.push_str(" -> ");
407 let nested = t.make(offset + sig.text.len(), None, scx)?;
408 sig.text.push_str(&nested.text);
409 sig.defs.extend(nested.defs.into_iter());
410 sig.refs.extend(nested.refs.into_iter());
412 sig.text.push_str(" {}");
416 hir::ItemKind::Mod(ref _mod) => {
417 let mut text = "mod ".to_owned();
418 let name = self.ident.to_string();
419 let defs = vec![SigElement {
420 id: id_from_hir_id(self.hir_id, scx),
421 start: offset + text.len(),
422 end: offset + text.len() + name.len(),
424 text.push_str(&name);
425 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
428 Ok(Signature { text, defs, refs: vec![] })
430 hir::ItemKind::TyAlias(ref ty, ref generics) => {
431 let text = "type ".to_owned();
433 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
435 sig.text.push_str(" = ");
436 let ty = ty.make(offset + sig.text.len(), id, scx)?;
437 sig.text.push_str(&ty.text);
440 Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
442 hir::ItemKind::Enum(_, ref generics) => {
443 let text = "enum ".to_owned();
445 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
446 sig.text.push_str(" {}");
449 hir::ItemKind::Struct(_, ref generics) => {
450 let text = "struct ".to_owned();
452 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
453 sig.text.push_str(" {}");
456 hir::ItemKind::Union(_, ref generics) => {
457 let text = "union ".to_owned();
459 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
460 sig.text.push_str(" {}");
463 hir::ItemKind::Trait(is_auto, unsafety, ref generics, bounds, _) => {
464 let mut text = String::new();
466 if is_auto == hir::IsAuto::Yes {
467 text.push_str("auto ");
470 if let hir::Unsafety::Unsafe = unsafety {
471 text.push_str("unsafe ");
473 text.push_str("trait ");
475 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
477 if !bounds.is_empty() {
478 sig.text.push_str(": ");
479 sig.text.push_str(&bounds_to_string(bounds));
481 // FIXME where clause
482 sig.text.push_str(" {}");
486 hir::ItemKind::TraitAlias(ref generics, bounds) => {
487 let mut text = String::new();
488 text.push_str("trait ");
490 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
492 if !bounds.is_empty() {
493 sig.text.push_str(" = ");
494 sig.text.push_str(&bounds_to_string(bounds));
496 // FIXME where clause
497 sig.text.push_str(";");
501 hir::ItemKind::Impl {
512 let mut text = String::new();
513 if let hir::Defaultness::Default { .. } = defaultness {
514 text.push_str("default ");
516 if let hir::Unsafety::Unsafe = unsafety {
517 text.push_str("unsafe ");
519 text.push_str("impl");
520 if let hir::Constness::Const = constness {
521 text.push_str(" const");
524 let generics_sig = generics.make(offset + text.len(), id, scx)?;
525 text.push_str(&generics_sig.text);
529 let trait_sig = if let Some(ref t) = *of_trait {
530 if let hir::ImplPolarity::Negative(_) = polarity {
533 let trait_sig = t.path.make(offset + text.len(), id, scx)?;
534 text.push_str(&trait_sig.text);
535 text.push_str(" for ");
538 text_sig(String::new())
541 let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
542 text.push_str(&ty_sig.text);
544 text.push_str(" {}");
546 Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
548 // FIXME where clause
550 hir::ItemKind::ForeignMod(_) => Err("extern mod"),
551 hir::ItemKind::GlobalAsm(_) => Err("glboal asm"),
552 hir::ItemKind::ExternCrate(_) => Err("extern crate"),
553 hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
554 // FIXME should implement this (e.g., pub use).
555 hir::ItemKind::Use(..) => Err("import"),
560 impl<'hir> Sig for hir::Path<'hir> {
561 fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
562 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
564 let (name, start, end) = match res {
565 Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => {
566 return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
568 Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
569 let len = self.segments.len();
571 return Err("Bad path");
573 // FIXME: really we should descend into the generics here and add SigElements for
575 // FIXME: would be nice to have a def for the first path segment.
576 let seg1 = path_segment_to_string(&self.segments[len - 2]);
577 let seg2 = path_segment_to_string(&self.segments[len - 1]);
578 let start = offset + seg1.len() + 2;
579 (format!("{}::{}", seg1, seg2), start, start + seg2.len())
582 let name = path_segment_to_string(self.segments.last().ok_or("Bad path")?);
583 let end = offset + name.len();
588 let id = id_from_def_id(res.def_id());
589 Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }] })
593 // This does not cover the where clause, which must be processed separately.
594 impl<'hir> Sig for hir::Generics<'hir> {
595 fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
596 if self.params.is_empty() {
597 return Ok(text_sig(String::new()));
600 let mut text = "<".to_owned();
602 let mut defs = Vec::with_capacity(self.params.len());
603 for param in self.params {
604 let mut param_text = String::new();
605 if let hir::GenericParamKind::Const { .. } = param.kind {
606 param_text.push_str("const ");
608 param_text.push_str(¶m.name.ident().as_str());
609 defs.push(SigElement {
610 id: id_from_hir_id(param.hir_id, scx),
611 start: offset + text.len(),
612 end: offset + text.len() + param_text.as_str().len(),
614 if let hir::GenericParamKind::Const { ref ty } = param.kind {
615 param_text.push_str(": ");
616 param_text.push_str(&ty_to_string(&ty));
618 if !param.bounds.is_empty() {
619 param_text.push_str(": ");
621 hir::GenericParamKind::Lifetime { .. } => {
625 .map(|bound| match bound {
626 hir::GenericBound::Outlives(lt) => lt.name.ident().to_string(),
631 param_text.push_str(&bounds);
632 // FIXME add lifetime bounds refs.
634 hir::GenericParamKind::Type { .. } => {
635 param_text.push_str(&bounds_to_string(param.bounds));
636 // FIXME descend properly into bounds.
638 hir::GenericParamKind::Const { .. } => {
639 // Const generics cannot contain bounds.
643 text.push_str(¶m_text);
648 Ok(Signature { text, defs, refs: vec![] })
652 impl<'hir> Sig for hir::StructField<'hir> {
653 fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
654 let mut text = String::new();
656 text.push_str(&self.ident.to_string());
657 let defs = Some(SigElement {
658 id: id_from_hir_id(self.hir_id, scx),
660 end: offset + text.len(),
664 let mut ty_sig = self.ty.make(offset + text.len(), Some(self.hir_id), scx)?;
665 text.push_str(&ty_sig.text);
667 ty_sig.defs.extend(defs.into_iter());
672 impl<'hir> Sig for hir::Variant<'hir> {
673 fn make(&self, offset: usize, parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
674 let mut text = self.ident.to_string();
676 hir::VariantData::Struct(fields, r) => {
677 let id = parent_id.unwrap();
678 let name_def = SigElement {
679 id: id_from_hir_id(id, scx),
681 end: offset + text.len(),
683 text.push_str(" { ");
684 let mut defs = vec![name_def];
685 let mut refs = vec![];
687 text.push_str("/* parse error */ ");
690 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
691 text.push_str(&field_sig.text);
693 defs.extend(field_sig.defs.into_iter());
694 refs.extend(field_sig.refs.into_iter());
698 Ok(Signature { text, defs, refs })
700 hir::VariantData::Tuple(fields, id) => {
701 let name_def = SigElement {
702 id: id_from_hir_id(id, scx),
704 end: offset + text.len(),
707 let mut defs = vec![name_def];
708 let mut refs = vec![];
710 let field_sig = f.make(offset + text.len(), Some(id), scx)?;
711 text.push_str(&field_sig.text);
713 defs.extend(field_sig.defs.into_iter());
714 refs.extend(field_sig.refs.into_iter());
717 Ok(Signature { text, defs, refs })
719 hir::VariantData::Unit(id) => {
720 let name_def = SigElement {
721 id: id_from_hir_id(id, scx),
723 end: offset + text.len(),
725 Ok(Signature { text, defs: vec![name_def], refs: vec![] })
731 impl<'hir> Sig for hir::ForeignItem<'hir> {
732 fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
733 let id = Some(self.hir_id);
735 hir::ForeignItemKind::Fn(decl, _, ref generics) => {
736 let mut text = String::new();
737 text.push_str("fn ");
740 name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
743 for i in decl.inputs {
744 sig.text.push_str(": ");
745 let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
746 sig.text.push_str(&nested.text);
748 sig.defs.extend(nested.defs.into_iter());
749 sig.refs.extend(nested.refs.into_iter());
753 if let hir::FnRetTy::Return(ref t) = decl.output {
754 sig.text.push_str(" -> ");
755 let nested = t.make(offset + sig.text.len(), None, scx)?;
756 sig.text.push_str(&nested.text);
757 sig.defs.extend(nested.defs.into_iter());
758 sig.refs.extend(nested.refs.into_iter());
764 hir::ForeignItemKind::Static(ref ty, m) => {
765 let mut text = "static ".to_owned();
766 if m == Mutability::Mut {
767 text.push_str("mut ");
769 let name = self.ident.to_string();
770 let defs = vec![SigElement {
771 id: id_from_hir_id(self.hir_id, scx),
772 start: offset + text.len(),
773 end: offset + text.len() + name.len(),
775 text.push_str(&name);
778 let ty_sig = ty.make(offset + text.len(), id, scx)?;
781 Ok(extend_sig(ty_sig, text, defs, vec![]))
783 hir::ForeignItemKind::Type => {
784 let mut text = "type ".to_owned();
785 let name = self.ident.to_string();
786 let defs = vec![SigElement {
787 id: id_from_hir_id(self.hir_id, scx),
788 start: offset + text.len(),
789 end: offset + text.len() + name.len(),
791 text.push_str(&name);
794 Ok(Signature { text, defs, refs: vec![] })
800 fn name_and_generics(
803 generics: &hir::Generics<'_>,
806 scx: &SaveContext<'_>,
808 let name = name.to_string();
809 let def = SigElement {
810 id: id_from_hir_id(id, scx),
811 start: offset + text.len(),
812 end: offset + text.len() + name.len(),
814 text.push_str(&name);
815 let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
816 // FIXME where clause
817 let text = format!("{}{}", text, generics.text);
818 Ok(extend_sig(generics, text, vec![def], vec![]))
821 fn make_assoc_type_signature(
824 bounds: Option<hir::GenericBounds<'_>>,
825 default: Option<&hir::Ty<'_>>,
826 scx: &SaveContext<'_>,
828 let mut text = "type ".to_owned();
829 let name = ident.to_string();
830 let mut defs = vec![SigElement {
831 id: id_from_hir_id(id, scx),
833 end: text.len() + name.len(),
835 let mut refs = vec![];
836 text.push_str(&name);
837 if let Some(bounds) = bounds {
839 // FIXME should descend into bounds
840 text.push_str(&bounds_to_string(bounds));
842 if let Some(default) = default {
843 text.push_str(" = ");
844 let ty_sig = default.make(text.len(), Some(id), scx)?;
845 text.push_str(&ty_sig.text);
846 defs.extend(ty_sig.defs.into_iter());
847 refs.extend(ty_sig.refs.into_iter());
850 Ok(Signature { text, defs, refs })
853 fn make_assoc_const_signature(
857 default: Option<&hir::Expr<'_>>,
858 scx: &SaveContext<'_>,
860 let mut text = "const ".to_owned();
861 let name = ident.to_string();
862 let mut defs = vec![SigElement {
863 id: id_from_hir_id(id, scx),
865 end: text.len() + name.len(),
867 let mut refs = vec![];
868 text.push_str(&name);
871 let ty_sig = ty.make(text.len(), Some(id), scx)?;
872 text.push_str(&ty_sig.text);
873 defs.extend(ty_sig.defs.into_iter());
874 refs.extend(ty_sig.refs.into_iter());
876 if let Some(default) = default {
877 text.push_str(" = ");
878 text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
881 Ok(Signature { text, defs, refs })
884 fn make_method_signature(
887 generics: &hir::Generics<'_>,
889 scx: &SaveContext<'_>,
891 // FIXME code dup with function signature
892 let mut text = String::new();
893 if let hir::Constness::Const = m.header.constness {
894 text.push_str("const ");
896 if hir::IsAsync::Async == m.header.asyncness {
897 text.push_str("async ");
899 if let hir::Unsafety::Unsafe = m.header.unsafety {
900 text.push_str("unsafe ");
902 text.push_str("fn ");
904 let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
907 for i in m.decl.inputs {
908 sig.text.push_str(": ");
909 let nested = i.make(sig.text.len(), Some(i.hir_id), scx)?;
910 sig.text.push_str(&nested.text);
912 sig.defs.extend(nested.defs.into_iter());
913 sig.refs.extend(nested.refs.into_iter());
917 if let hir::FnRetTy::Return(ref t) = m.decl.output {
918 sig.text.push_str(" -> ");
919 let nested = t.make(sig.text.len(), None, scx)?;
920 sig.text.push_str(&nested.text);
921 sig.defs.extend(nested.defs.into_iter());
922 sig.refs.extend(nested.refs.into_iter());
924 sig.text.push_str(" {}");