1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // Type Names for Debug Info.
13 use super::namespace
::crate_root_namespace
;
15 use trans
::common
::CrateContext
;
16 use middle
::def_id
::DefId
;
18 use middle
::subst
::{self, Substs}
;
19 use middle
::ty
::{self, Ty}
;
24 // Compute the name of the type as it should be stored in debuginfo. Does not do
25 // any caching, i.e. calling the function twice with the same type will also do
26 // the work twice. The `qualified` parameter only affects the first level of the
27 // type name, further levels (i.e. type parameters) are always fully qualified.
28 pub fn compute_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
32 let mut result
= String
::with_capacity(64);
33 push_debuginfo_type_name(cx
, t
, qualified
, &mut result
);
37 // Pushes the name of the type as it should be stored in debuginfo on the
38 // `output` String. See also compute_debuginfo_type_name().
39 pub fn push_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
42 output
: &mut String
) {
44 ty
::TyBool
=> output
.push_str("bool"),
45 ty
::TyChar
=> output
.push_str("char"),
46 ty
::TyStr
=> output
.push_str("str"),
47 ty
::TyInt(int_ty
) => output
.push_str(ast_util
::int_ty_to_string(int_ty
)),
48 ty
::TyUint(uint_ty
) => output
.push_str(ast_util
::uint_ty_to_string(uint_ty
)),
49 ty
::TyFloat(float_ty
) => output
.push_str(ast_util
::float_ty_to_string(float_ty
)),
50 ty
::TyStruct(def
, substs
) |
51 ty
::TyEnum(def
, substs
) => {
52 push_item_name(cx
, def
.did
, qualified
, output
);
53 push_type_params(cx
, substs
, output
);
55 ty
::TyTuple(ref component_types
) => {
57 for &component_type
in component_types
{
58 push_debuginfo_type_name(cx
, component_type
, true, output
);
59 output
.push_str(", ");
61 if !component_types
.is_empty() {
67 ty
::TyBox(inner_type
) => {
68 output
.push_str("Box<");
69 push_debuginfo_type_name(cx
, inner_type
, true, output
);
72 ty
::TyRawPtr(ty
::TypeAndMut { ty: inner_type, mutbl }
) => {
75 hir
::MutImmutable
=> output
.push_str("const "),
76 hir
::MutMutable
=> output
.push_str("mut "),
79 push_debuginfo_type_name(cx
, inner_type
, true, output
);
81 ty
::TyRef(_
, ty
::TypeAndMut { ty: inner_type, mutbl }
) => {
83 if mutbl
== hir
::MutMutable
{
84 output
.push_str("mut ");
87 push_debuginfo_type_name(cx
, inner_type
, true, output
);
89 ty
::TyArray(inner_type
, len
) => {
91 push_debuginfo_type_name(cx
, inner_type
, true, output
);
92 output
.push_str(&format
!("; {}", len
));
95 ty
::TySlice(inner_type
) => {
97 push_debuginfo_type_name(cx
, inner_type
, true, output
);
100 ty
::TyTrait(ref trait_data
) => {
101 let principal
= cx
.tcx().erase_late_bound_regions(&trait_data
.principal
);
102 push_item_name(cx
, principal
.def_id
, false, output
);
103 push_type_params(cx
, principal
.substs
, output
);
105 ty
::TyBareFn(_
, &ty
::BareFnTy{ unsafety, abi, ref sig }
) => {
106 if unsafety
== hir
::Unsafety
::Unsafe
{
107 output
.push_str("unsafe ");
110 if abi
!= ::syntax
::abi
::Rust
{
111 output
.push_str("extern \"");
112 output
.push_str(abi
.name());
113 output
.push_str("\" ");
116 output
.push_str("fn(");
118 let sig
= cx
.tcx().erase_late_bound_regions(sig
);
119 let sig
= infer
::normalize_associated_type(cx
.tcx(), &sig
);
120 if !sig
.inputs
.is_empty() {
121 for ¶meter_type
in &sig
.inputs
{
122 push_debuginfo_type_name(cx
, parameter_type
, true, output
);
123 output
.push_str(", ");
130 if !sig
.inputs
.is_empty() {
131 output
.push_str(", ...");
133 output
.push_str("...");
140 ty
::FnConverging(result_type
) if result_type
.is_nil() => {}
141 ty
::FnConverging(result_type
) => {
142 output
.push_str(" -> ");
143 push_debuginfo_type_name(cx
, result_type
, true, output
);
146 output
.push_str(" -> !");
150 ty
::TyClosure(..) => {
151 output
.push_str("closure");
155 ty
::TyProjection(..) |
157 cx
.sess().bug(&format
!("debuginfo: Trying to create type name for \
158 unexpected type: {:?}", t
));
162 fn push_item_name(cx
: &CrateContext
,
165 output
: &mut String
) {
166 cx
.tcx().with_path(def_id
, |path
| {
168 if def_id
.is_local() {
169 output
.push_str(crate_root_namespace(cx
));
170 output
.push_str("::");
173 let mut path_element_count
= 0;
174 for path_element
in path
{
175 output
.push_str(&path_element
.name().as_str());
176 output
.push_str("::");
177 path_element_count
+= 1;
180 if path_element_count
== 0 {
181 cx
.sess().bug("debuginfo: Encountered empty item path!");
187 let name
= path
.last().expect("debuginfo: Empty item path?").name();
188 output
.push_str(&name
.as_str());
193 // Pushes the type parameters in the given `Substs` to the output string.
194 // This ignores region parameters, since they can't reliably be
195 // reconstructed for items from non-local crates. For local crates, this
196 // would be possible but with inlining and LTO we have to use the least
197 // common denominator - otherwise we would run into conflicts.
198 fn push_type_params
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
199 substs
: &subst
::Substs
<'tcx
>,
200 output
: &mut String
) {
201 if substs
.types
.is_empty() {
207 for &type_parameter
in &substs
.types
{
208 push_debuginfo_type_name(cx
, type_parameter
, true, output
);
209 output
.push_str(", ");