@@ -13,14 +13,16 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
13
13
use ty:: { self , Ty , TyCtxt } ;
14
14
use middle:: cstore:: { ExternCrate , ExternCrateSource } ;
15
15
use syntax:: ast;
16
- use syntax:: symbol:: Symbol ;
17
- use syntax :: symbol :: LocalInternedString ;
16
+ use syntax:: symbol:: { keywords , LocalInternedString , Symbol } ;
17
+ use syntax_pos :: edition :: Edition ;
18
18
19
19
use std:: cell:: Cell ;
20
+ use std:: fmt:: Debug ;
20
21
21
22
thread_local ! {
22
23
static FORCE_ABSOLUTE : Cell <bool > = Cell :: new( false ) ;
23
24
static FORCE_IMPL_FILENAME_LINE : Cell <bool > = Cell :: new( false ) ;
25
+ static SHOULD_PREFIX_WITH_CRATE : Cell <bool > = Cell :: new( false ) ;
24
26
}
25
27
26
28
/// Enforces that item_path_str always returns an absolute path and
@@ -51,6 +53,17 @@ pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
51
53
} )
52
54
}
53
55
56
+ /// Add the `crate::` prefix to paths where appropriate.
57
+ pub fn with_crate_prefix < F : FnOnce ( ) -> R , R > ( f : F ) -> R {
58
+ SHOULD_PREFIX_WITH_CRATE . with ( |flag| {
59
+ let old = flag. get ( ) ;
60
+ flag. set ( true ) ;
61
+ let result = f ( ) ;
62
+ flag. set ( old) ;
63
+ result
64
+ } )
65
+ }
66
+
54
67
impl < ' a , ' gcx , ' tcx > TyCtxt < ' a , ' gcx , ' tcx > {
55
68
/// Returns a string identifying this def-id. This string is
56
69
/// suitable for user output. It is relative to the current crate
@@ -64,6 +77,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
64
77
}
65
78
} ) ;
66
79
let mut buffer = LocalPathBuffer :: new ( mode) ;
80
+ debug ! ( "item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
67
81
self . push_item_path ( & mut buffer, def_id) ;
68
82
buffer. into_string ( )
69
83
}
@@ -77,6 +91,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
77
91
/// suitable for user output. It always begins with a crate identifier.
78
92
pub fn absolute_item_path_str ( self , def_id : DefId ) -> String {
79
93
let mut buffer = LocalPathBuffer :: new ( RootMode :: Absolute ) ;
94
+ debug ! ( "absolute_item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
80
95
self . push_item_path ( & mut buffer, def_id) ;
81
96
buffer. into_string ( )
82
97
}
@@ -85,8 +100,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
85
100
/// various ways, depending on the `root_mode` of the `buffer`.
86
101
/// (See `RootMode` enum for more details.)
87
102
pub fn push_krate_path < T > ( self , buffer : & mut T , cnum : CrateNum )
88
- where T : ItemPathBuffer
103
+ where T : ItemPathBuffer + Debug
89
104
{
105
+ debug ! (
106
+ "push_krate_path: buffer={:?} cnum={:?} LOCAL_CRATE={:?}" ,
107
+ buffer, cnum, LOCAL_CRATE
108
+ ) ;
90
109
match * buffer. root_mode ( ) {
91
110
RootMode :: Local => {
92
111
// In local mode, when we encounter a crate other than
@@ -109,16 +128,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
109
128
..
110
129
} ) = * opt_extern_crate
111
130
{
131
+ debug ! ( "push_krate_path: def_id={:?}" , def_id) ;
112
132
self . push_item_path ( buffer, def_id) ;
113
133
} else {
114
- buffer. push ( & self . crate_name ( cnum) . as_str ( ) ) ;
134
+ let name = self . crate_name ( cnum) . as_str ( ) ;
135
+ debug ! ( "push_krate_path: name={:?}" , name) ;
136
+ buffer. push ( & name) ;
115
137
}
138
+ } else if self . sess . edition ( ) == Edition :: Edition2018 {
139
+ SHOULD_PREFIX_WITH_CRATE . with ( |flag| {
140
+ // We only add the `crate::` keyword where appropriate. This
141
+ // is only possible because of the invariant in `push_item_path`
142
+ // that this function will not be called after printing the path
143
+ // to an item in the standard library. Without this invariant,
144
+ // we would print `crate::std::..` here.
145
+ if flag. get ( ) {
146
+ buffer. push ( & keywords:: Crate . name ( ) . as_str ( ) )
147
+ }
148
+ } )
116
149
}
117
150
}
118
151
RootMode :: Absolute => {
119
152
// In absolute mode, just write the crate name
120
153
// unconditionally.
121
- buffer. push ( & self . original_crate_name ( cnum) . as_str ( ) ) ;
154
+ let name = self . original_crate_name ( cnum) . as_str ( ) ;
155
+ debug ! ( "push_krate_path: original_name={:?}" , name) ;
156
+ buffer. push ( & name) ;
122
157
}
123
158
}
124
159
}
@@ -127,12 +162,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
127
162
/// from at least one local module and returns true. If the crate defining `external_def_id` is
128
163
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
129
164
pub fn try_push_visible_item_path < T > ( self , buffer : & mut T , external_def_id : DefId ) -> bool
130
- where T : ItemPathBuffer
165
+ where T : ItemPathBuffer + Debug
131
166
{
167
+ debug ! (
168
+ "try_push_visible_item_path: buffer={:?} external_def_id={:?}" ,
169
+ buffer, external_def_id
170
+ ) ;
132
171
let visible_parent_map = self . visible_parent_map ( LOCAL_CRATE ) ;
133
172
134
173
let ( mut cur_def, mut cur_path) = ( external_def_id, Vec :: < LocalInternedString > :: new ( ) ) ;
135
174
loop {
175
+ debug ! (
176
+ "try_push_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}" ,
177
+ cur_def, cur_path, CRATE_DEF_INDEX ,
178
+ ) ;
136
179
// If `cur_def` is a direct or injected extern crate, push the path to the crate
137
180
// followed by the path to the item within the crate and return.
138
181
if cur_def. index == CRATE_DEF_INDEX {
@@ -142,6 +185,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
142
185
direct : true ,
143
186
..
144
187
} ) => {
188
+ debug ! ( "try_push_visible_item_path: def_id={:?}" , def_id) ;
145
189
self . push_item_path ( buffer, def_id) ;
146
190
cur_path. iter ( ) . rev ( ) . for_each ( |segment| buffer. push ( & segment) ) ;
147
191
return true ;
@@ -156,6 +200,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
156
200
}
157
201
158
202
let mut cur_def_key = self . def_key ( cur_def) ;
203
+ debug ! ( "try_push_visible_item_path: cur_def_key={:?}" , cur_def_key) ;
159
204
160
205
// For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
161
206
if let DefPathData :: StructCtor = cur_def_key. disambiguated_data . data {
@@ -175,6 +220,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
175
220
Symbol :: intern ( "<unnamed>" ) . as_str ( )
176
221
}
177
222
} ) ;
223
+ debug ! ( "try_push_visible_item_path: symbol={:?}" , symbol) ;
178
224
cur_path. push ( symbol) ;
179
225
180
226
match visible_parent_map. get ( & cur_def) {
@@ -185,15 +231,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
185
231
}
186
232
187
233
pub fn push_item_path < T > ( self , buffer : & mut T , def_id : DefId )
188
- where T : ItemPathBuffer
234
+ where T : ItemPathBuffer + Debug
189
235
{
236
+ debug ! ( "push_item_path: buffer={:?} def_id={:?}" , buffer, def_id) ;
190
237
match * buffer. root_mode ( ) {
191
238
RootMode :: Local if !def_id. is_local ( ) =>
192
239
if self . try_push_visible_item_path ( buffer, def_id) { return } ,
193
240
_ => { }
194
241
}
195
242
196
243
let key = self . def_key ( def_id) ;
244
+ debug ! ( "push_item_path: key={:?}" , key) ;
197
245
match key. disambiguated_data . data {
198
246
DefPathData :: CrateRoot => {
199
247
assert ! ( key. parent. is_none( ) ) ;
@@ -225,9 +273,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
225
273
data @ DefPathData :: ImplTrait |
226
274
data @ DefPathData :: GlobalMetaData ( ..) => {
227
275
let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
228
- self . push_item_path ( buffer, parent_def_id) ;
276
+
277
+ match self . def_key ( parent_def_id) . disambiguated_data . data {
278
+ // Skip recursing to print the crate root depending on the
279
+ // current name.
280
+ //
281
+ // In particular, don't recurse to print the crate root if we
282
+ // just printed `std`. In doing this, we are able to add
283
+ // `crate::` to trait import suggestions.
284
+ DefPathData :: CrateRoot if data. as_interned_str ( ) == "std" => { } ,
285
+ _ => self . push_item_path ( buffer, parent_def_id) ,
286
+ }
287
+
229
288
buffer. push ( & data. as_interned_str ( ) . as_symbol ( ) . as_str ( ) ) ;
230
- }
289
+ } ,
290
+
231
291
DefPathData :: StructCtor => { // present `X` instead of `X::{{constructor}}`
232
292
let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
233
293
self . push_item_path ( buffer, parent_def_id) ;
@@ -238,8 +298,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
238
298
fn push_impl_path < T > ( self ,
239
299
buffer : & mut T ,
240
300
impl_def_id : DefId )
241
- where T : ItemPathBuffer
301
+ where T : ItemPathBuffer + Debug
242
302
{
303
+ debug ! ( "push_impl_path: buffer={:?} impl_def_id={:?}" , buffer, impl_def_id) ;
243
304
let parent_def_id = self . parent_def_id ( impl_def_id) . unwrap ( ) ;
244
305
245
306
// Always use types for non-local impls, where types are always
@@ -327,7 +388,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
327
388
fn push_impl_path_fallback < T > ( self ,
328
389
buffer : & mut T ,
329
390
impl_def_id : DefId )
330
- where T : ItemPathBuffer
391
+ where T : ItemPathBuffer + Debug
331
392
{
332
393
// If no type info is available, fall back to
333
394
// pretty printing some span information. This should
0 commit comments