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 common
::CrateContext
;
14 use rustc
::hir
::def_id
::DefId
;
15 use rustc
::ty
::subst
::Substs
;
16 use rustc
::ty
::{self, Ty}
;
20 // Compute the name of the type as it should be stored in debuginfo. Does not do
21 // any caching, i.e. calling the function twice with the same type will also do
22 // the work twice. The `qualified` parameter only affects the first level of the
23 // type name, further levels (i.e. type parameters) are always fully qualified.
24 pub fn compute_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
28 let mut result
= String
::with_capacity(64);
29 push_debuginfo_type_name(cx
, t
, qualified
, &mut result
);
33 // Pushes the name of the type as it should be stored in debuginfo on the
34 // `output` String. See also compute_debuginfo_type_name().
35 pub fn push_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
38 output
: &mut String
) {
39 // When targeting MSVC, emit C++ style type names for compatibility with
40 // .natvis visualizers (and perhaps other existing native debuggers?)
41 let cpp_like_names
= cx
.sess().target
.target
.options
.is_like_msvc
;
44 ty
::TyBool
=> output
.push_str("bool"),
45 ty
::TyChar
=> output
.push_str("char"),
46 ty
::TyStr
=> output
.push_str("str"),
47 ty
::TyNever
=> output
.push_str("!"),
48 ty
::TyInt(int_ty
) => output
.push_str(int_ty
.ty_to_string()),
49 ty
::TyUint(uint_ty
) => output
.push_str(uint_ty
.ty_to_string()),
50 ty
::TyFloat(float_ty
) => output
.push_str(float_ty
.ty_to_string()),
51 ty
::TyAdt(def
, substs
) => {
52 push_item_name(cx
, def
.did
, qualified
, output
);
53 push_type_params(cx
, substs
, output
);
55 ty
::TyTuple(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
::TyRawPtr(ty
::TypeAndMut { ty: inner_type, mutbl }
) => {
72 hir
::MutImmutable
=> output
.push_str("const "),
73 hir
::MutMutable
=> output
.push_str("mut "),
76 push_debuginfo_type_name(cx
, inner_type
, true, output
);
82 ty
::TyRef(_
, ty
::TypeAndMut { ty: inner_type, mutbl }
) => {
86 if mutbl
== hir
::MutMutable
{
87 output
.push_str("mut ");
90 push_debuginfo_type_name(cx
, inner_type
, true, output
);
96 ty
::TyArray(inner_type
, len
) => {
98 push_debuginfo_type_name(cx
, inner_type
, true, output
);
99 output
.push_str(&format
!("; {}", len
));
102 ty
::TySlice(inner_type
) => {
104 output
.push_str("slice<");
109 push_debuginfo_type_name(cx
, inner_type
, true, output
);
117 ty
::TyDynamic(ref trait_data
, ..) => {
118 if let Some(principal
) = trait_data
.principal() {
119 let principal
= cx
.tcx().erase_late_bound_regions_and_normalize(
121 push_item_name(cx
, principal
.def_id
, false, output
);
122 push_type_params(cx
, principal
.substs
, output
);
125 ty
::TyFnDef(..) | ty
::TyFnPtr(_
) => {
126 let sig
= t
.fn_sig(cx
.tcx());
127 if sig
.unsafety() == hir
::Unsafety
::Unsafe
{
128 output
.push_str("unsafe ");
132 if abi
!= ::abi
::Abi
::Rust
{
133 output
.push_str("extern \"");
134 output
.push_str(abi
.name());
135 output
.push_str("\" ");
138 output
.push_str("fn(");
140 let sig
= cx
.tcx().erase_late_bound_regions_and_normalize(&sig
);
141 if !sig
.inputs().is_empty() {
142 for ¶meter_type
in sig
.inputs() {
143 push_debuginfo_type_name(cx
, parameter_type
, true, output
);
144 output
.push_str(", ");
151 if !sig
.inputs().is_empty() {
152 output
.push_str(", ...");
154 output
.push_str("...");
160 if !sig
.output().is_nil() {
161 output
.push_str(" -> ");
162 push_debuginfo_type_name(cx
, sig
.output(), true, output
);
165 ty
::TyClosure(..) => {
166 output
.push_str("closure");
170 ty
::TyProjection(..) |
173 bug
!("debuginfo: Trying to create type name for \
174 unexpected type: {:?}", t
);
178 fn push_item_name(cx
: &CrateContext
,
181 output
: &mut String
) {
183 output
.push_str(&cx
.tcx().crate_name(def_id
.krate
).as_str());
184 for path_element
in cx
.tcx().def_path(def_id
).data
{
185 output
.push_str("::");
186 output
.push_str(&path_element
.data
.as_interned_str());
189 output
.push_str(&cx
.tcx().item_name(def_id
).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
: &Substs
<'tcx
>,
200 output
: &mut String
) {
201 if substs
.types().next().is_none() {
207 for type_parameter
in substs
.types() {
208 push_debuginfo_type_name(cx
, type_parameter
, true, output
);
209 output
.push_str(", ");