@@ -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,7 +77,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
64
77
}
65
78
} ) ;
66
79
let mut buffer = LocalPathBuffer :: new ( mode) ;
67
- self . push_item_path ( & mut buffer, def_id) ;
80
+ debug ! ( "item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
81
+ self . push_item_path ( & mut buffer, def_id, false ) ;
68
82
buffer. into_string ( )
69
83
}
70
84
@@ -77,16 +91,26 @@ 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 ) ;
80
- self . push_item_path ( & mut buffer, def_id) ;
94
+ debug ! ( "absolute_item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
95
+ self . push_item_path ( & mut buffer, def_id, false ) ;
81
96
buffer. into_string ( )
82
97
}
83
98
84
99
/// Returns the "path" to a particular crate. This can proceed in
85
100
/// various ways, depending on the `root_mode` of the `buffer`.
86
101
/// (See `RootMode` enum for more details.)
87
- pub fn push_krate_path < T > ( self , buffer : & mut T , cnum : CrateNum )
88
- where T : ItemPathBuffer
102
+ ///
103
+ /// `pushed_prelude_crate` argument should be `true` when the buffer
104
+ /// has had a prelude crate pushed to it. If this is the case, then
105
+ /// we do not want to prepend `crate::` (as that would not be a valid
106
+ /// path).
107
+ pub fn push_krate_path < T > ( self , buffer : & mut T , cnum : CrateNum , pushed_prelude_crate : bool )
108
+ where T : ItemPathBuffer + Debug
89
109
{
110
+ debug ! (
111
+ "push_krate_path: buffer={:?} cnum={:?} LOCAL_CRATE={:?}" ,
112
+ buffer, cnum, LOCAL_CRATE
113
+ ) ;
90
114
match * buffer. root_mode ( ) {
91
115
RootMode :: Local => {
92
116
// In local mode, when we encounter a crate other than
@@ -109,30 +133,56 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
109
133
..
110
134
} ) = * opt_extern_crate
111
135
{
112
- self . push_item_path ( buffer, def_id) ;
136
+ debug ! ( "push_krate_path: def_id={:?}" , def_id) ;
137
+ self . push_item_path ( buffer, def_id, pushed_prelude_crate) ;
113
138
} else {
114
- buffer. push ( & self . crate_name ( cnum) . as_str ( ) ) ;
139
+ let name = self . crate_name ( cnum) . as_str ( ) ;
140
+ debug ! ( "push_krate_path: name={:?}" , name) ;
141
+ buffer. push ( & name) ;
115
142
}
143
+ } else if self . sess . edition ( ) == Edition :: Edition2018 && !pushed_prelude_crate {
144
+ SHOULD_PREFIX_WITH_CRATE . with ( |flag| {
145
+ // We only add the `crate::` keyword where appropriate. In particular,
146
+ // when we've not previously pushed a prelude crate to this path.
147
+ if flag. get ( ) {
148
+ buffer. push ( & keywords:: Crate . name ( ) . as_str ( ) )
149
+ }
150
+ } )
116
151
}
117
152
}
118
153
RootMode :: Absolute => {
119
154
// In absolute mode, just write the crate name
120
155
// unconditionally.
121
- buffer. push ( & self . original_crate_name ( cnum) . as_str ( ) ) ;
156
+ let name = self . original_crate_name ( cnum) . as_str ( ) ;
157
+ debug ! ( "push_krate_path: original_name={:?}" , name) ;
158
+ buffer. push ( & name) ;
122
159
}
123
160
}
124
161
}
125
162
126
163
/// If possible, this pushes a global path resolving to `external_def_id` that is visible
127
164
/// from at least one local module and returns true. If the crate defining `external_def_id` is
128
165
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
129
- pub fn try_push_visible_item_path < T > ( self , buffer : & mut T , external_def_id : DefId ) -> bool
130
- where T : ItemPathBuffer
166
+ pub fn try_push_visible_item_path < T > (
167
+ self ,
168
+ buffer : & mut T ,
169
+ external_def_id : DefId ,
170
+ pushed_prelude_crate : bool ,
171
+ ) -> bool
172
+ where T : ItemPathBuffer + Debug
131
173
{
174
+ debug ! (
175
+ "try_push_visible_item_path: buffer={:?} external_def_id={:?}" ,
176
+ buffer, external_def_id
177
+ ) ;
132
178
let visible_parent_map = self . visible_parent_map ( LOCAL_CRATE ) ;
133
179
134
180
let ( mut cur_def, mut cur_path) = ( external_def_id, Vec :: < LocalInternedString > :: new ( ) ) ;
135
181
loop {
182
+ debug ! (
183
+ "try_push_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}" ,
184
+ cur_def, cur_path, CRATE_DEF_INDEX ,
185
+ ) ;
136
186
// If `cur_def` is a direct or injected extern crate, push the path to the crate
137
187
// followed by the path to the item within the crate and return.
138
188
if cur_def. index == CRATE_DEF_INDEX {
@@ -142,7 +192,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
142
192
direct : true ,
143
193
..
144
194
} ) => {
145
- self . push_item_path ( buffer, def_id) ;
195
+ debug ! ( "try_push_visible_item_path: def_id={:?}" , def_id) ;
196
+ self . push_item_path ( buffer, def_id, pushed_prelude_crate) ;
146
197
cur_path. iter ( ) . rev ( ) . for_each ( |segment| buffer. push ( & segment) ) ;
147
198
return true ;
148
199
}
@@ -156,6 +207,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
156
207
}
157
208
158
209
let mut cur_def_key = self . def_key ( cur_def) ;
210
+ debug ! ( "try_push_visible_item_path: cur_def_key={:?}" , cur_def_key) ;
159
211
160
212
// For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
161
213
if let DefPathData :: StructCtor = cur_def_key. disambiguated_data . data {
@@ -175,6 +227,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
175
227
Symbol :: intern ( "<unnamed>" ) . as_str ( )
176
228
}
177
229
} ) ;
230
+ debug ! ( "try_push_visible_item_path: symbol={:?}" , symbol) ;
178
231
cur_path. push ( symbol) ;
179
232
180
233
match visible_parent_map. get ( & cur_def) {
@@ -184,24 +237,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
184
237
}
185
238
}
186
239
187
- pub fn push_item_path < T > ( self , buffer : & mut T , def_id : DefId )
188
- where T : ItemPathBuffer
240
+ pub fn push_item_path < T > ( self , buffer : & mut T , def_id : DefId , pushed_prelude_crate : bool )
241
+ where T : ItemPathBuffer + Debug
189
242
{
243
+ debug ! (
244
+ "push_item_path: buffer={:?} def_id={:?} pushed_prelude_crate={:?}" ,
245
+ buffer, def_id, pushed_prelude_crate
246
+ ) ;
190
247
match * buffer. root_mode ( ) {
191
248
RootMode :: Local if !def_id. is_local ( ) =>
192
- if self . try_push_visible_item_path ( buffer, def_id) { return } ,
249
+ if self . try_push_visible_item_path ( buffer, def_id, pushed_prelude_crate ) { return } ,
193
250
_ => { }
194
251
}
195
252
196
253
let key = self . def_key ( def_id) ;
254
+ debug ! ( "push_item_path: key={:?}" , key) ;
197
255
match key. disambiguated_data . data {
198
256
DefPathData :: CrateRoot => {
199
257
assert ! ( key. parent. is_none( ) ) ;
200
- self . push_krate_path ( buffer, def_id. krate ) ;
258
+ self . push_krate_path ( buffer, def_id. krate , pushed_prelude_crate ) ;
201
259
}
202
260
203
261
DefPathData :: Impl => {
204
- self . push_impl_path ( buffer, def_id) ;
262
+ self . push_impl_path ( buffer, def_id, pushed_prelude_crate ) ;
205
263
}
206
264
207
265
// Unclear if there is any value in distinguishing these.
@@ -224,22 +282,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
224
282
data @ DefPathData :: ClosureExpr |
225
283
data @ DefPathData :: ImplTrait |
226
284
data @ DefPathData :: GlobalMetaData ( ..) => {
227
- let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
228
- self . push_item_path ( buffer, parent_def_id) ;
285
+ let parent_did = self . parent_def_id ( def_id) . unwrap ( ) ;
286
+
287
+ // Keep track of whether we are one recursion away from the `CrateRoot` and
288
+ // pushing the name of a prelude crate. If we are, we'll want to know this when
289
+ // printing the `CrateRoot` so we don't prepend a `crate::` to paths.
290
+ let mut is_prelude_crate = false ;
291
+ if let DefPathData :: CrateRoot = self . def_key ( parent_did) . disambiguated_data . data {
292
+ if self . sess . extern_prelude . contains ( & data. as_interned_str ( ) . as_symbol ( ) ) {
293
+ is_prelude_crate = true ;
294
+ }
295
+ }
296
+
297
+ self . push_item_path (
298
+ buffer, parent_did, pushed_prelude_crate || is_prelude_crate
299
+ ) ;
229
300
buffer. push ( & data. as_interned_str ( ) . as_symbol ( ) . as_str ( ) ) ;
230
- }
301
+ } ,
302
+
231
303
DefPathData :: StructCtor => { // present `X` instead of `X::{{constructor}}`
232
304
let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
233
- self . push_item_path ( buffer, parent_def_id) ;
305
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
234
306
}
235
307
}
236
308
}
237
309
238
- fn push_impl_path < T > ( self ,
239
- buffer : & mut T ,
240
- impl_def_id : DefId )
241
- where T : ItemPathBuffer
310
+ fn push_impl_path < T > (
311
+ self ,
312
+ buffer : & mut T ,
313
+ impl_def_id : DefId ,
314
+ pushed_prelude_crate : bool ,
315
+ )
316
+ where T : ItemPathBuffer + Debug
242
317
{
318
+ debug ! ( "push_impl_path: buffer={:?} impl_def_id={:?}" , buffer, impl_def_id) ;
243
319
let parent_def_id = self . parent_def_id ( impl_def_id) . unwrap ( ) ;
244
320
245
321
// Always use types for non-local impls, where types are always
@@ -251,7 +327,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
251
327
} ;
252
328
253
329
if !use_types {
254
- return self . push_impl_path_fallback ( buffer, impl_def_id) ;
330
+ return self . push_impl_path_fallback ( buffer, impl_def_id, pushed_prelude_crate ) ;
255
331
}
256
332
257
333
// Decide whether to print the parent path for the impl.
@@ -275,7 +351,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
275
351
// If the impl is not co-located with either self-type or
276
352
// trait-type, then fallback to a format that identifies
277
353
// the module more clearly.
278
- self . push_item_path ( buffer, parent_def_id) ;
354
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
279
355
if let Some ( trait_ref) = impl_trait_ref {
280
356
buffer. push ( & format ! ( "<impl {} for {}>" , trait_ref, self_ty) ) ;
281
357
} else {
@@ -301,13 +377,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
301
377
match self_ty. sty {
302
378
ty:: Adt ( adt_def, substs) => {
303
379
if substs. types ( ) . next ( ) . is_none ( ) { // ignore regions
304
- self . push_item_path ( buffer, adt_def. did ) ;
380
+ self . push_item_path ( buffer, adt_def. did , pushed_prelude_crate ) ;
305
381
} else {
306
382
buffer. push ( & format ! ( "<{}>" , self_ty) ) ;
307
383
}
308
384
}
309
385
310
- ty:: Foreign ( did) => self . push_item_path ( buffer, did) ,
386
+ ty:: Foreign ( did) => self . push_item_path ( buffer, did, pushed_prelude_crate ) ,
311
387
312
388
ty:: Bool |
313
389
ty:: Char |
@@ -324,16 +400,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
324
400
}
325
401
}
326
402
327
- fn push_impl_path_fallback < T > ( self ,
328
- buffer : & mut T ,
329
- impl_def_id : DefId )
330
- where T : ItemPathBuffer
403
+ fn push_impl_path_fallback < T > (
404
+ self ,
405
+ buffer : & mut T ,
406
+ impl_def_id : DefId ,
407
+ pushed_prelude_crate : bool ,
408
+ )
409
+ where T : ItemPathBuffer + Debug
331
410
{
332
411
// If no type info is available, fall back to
333
412
// pretty printing some span information. This should
334
413
// only occur very early in the compiler pipeline.
335
414
let parent_def_id = self . parent_def_id ( impl_def_id) . unwrap ( ) ;
336
- self . push_item_path ( buffer, parent_def_id) ;
415
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
337
416
let node_id = self . hir . as_local_node_id ( impl_def_id) . unwrap ( ) ;
338
417
let item = self . hir . expect_item ( node_id) ;
339
418
let span_str = self . sess . source_map ( ) . span_to_string ( item. span ) ;
0 commit comments