@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
78
78
} ) ;
79
79
let mut buffer = LocalPathBuffer :: new ( mode) ;
80
80
debug ! ( "item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
81
- self . push_item_path ( & mut buffer, def_id) ;
81
+ self . push_item_path ( & mut buffer, def_id, false ) ;
82
82
buffer. into_string ( )
83
83
}
84
84
@@ -92,14 +92,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
92
92
pub fn absolute_item_path_str ( self , def_id : DefId ) -> String {
93
93
let mut buffer = LocalPathBuffer :: new ( RootMode :: Absolute ) ;
94
94
debug ! ( "absolute_item_path_str: buffer={:?} def_id={:?}" , buffer, def_id) ;
95
- self . push_item_path ( & mut buffer, def_id) ;
95
+ self . push_item_path ( & mut buffer, def_id, false ) ;
96
96
buffer. into_string ( )
97
97
}
98
98
99
99
/// Returns the "path" to a particular crate. This can proceed in
100
100
/// various ways, depending on the `root_mode` of the `buffer`.
101
101
/// (See `RootMode` enum for more details.)
102
- pub fn push_krate_path < T > ( self , buffer : & mut T , cnum : CrateNum )
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 )
103
108
where T : ItemPathBuffer + Debug
104
109
{
105
110
debug ! (
@@ -129,19 +134,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
129
134
} ) = * opt_extern_crate
130
135
{
131
136
debug ! ( "push_krate_path: def_id={:?}" , def_id) ;
132
- self . push_item_path ( buffer, def_id) ;
137
+ self . push_item_path ( buffer, def_id, pushed_prelude_crate ) ;
133
138
} else {
134
139
let name = self . crate_name ( cnum) . as_str ( ) ;
135
140
debug ! ( "push_krate_path: name={:?}" , name) ;
136
141
buffer. push ( & name) ;
137
142
}
138
- } else if self . sess . edition ( ) == Edition :: Edition2018 {
143
+ } else if self . sess . edition ( ) == Edition :: Edition2018 && !pushed_prelude_crate {
139
144
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
+ // We only add the `crate::` keyword where appropriate. In particular,
146
+ // when we've not previously pushed a prelude crate to this path.
145
147
if flag. get ( ) {
146
148
buffer. push ( & keywords:: Crate . name ( ) . as_str ( ) )
147
149
}
@@ -161,7 +163,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
161
163
/// If possible, this pushes a global path resolving to `external_def_id` that is visible
162
164
/// from at least one local module and returns true. If the crate defining `external_def_id` is
163
165
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
164
- pub fn try_push_visible_item_path < T > ( self , buffer : & mut T , external_def_id : DefId ) -> bool
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
165
172
where T : ItemPathBuffer + Debug
166
173
{
167
174
debug ! (
@@ -186,7 +193,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
186
193
..
187
194
} ) => {
188
195
debug ! ( "try_push_visible_item_path: def_id={:?}" , def_id) ;
189
- self . push_item_path ( buffer, def_id) ;
196
+ self . push_item_path ( buffer, def_id, pushed_prelude_crate ) ;
190
197
cur_path. iter ( ) . rev ( ) . for_each ( |segment| buffer. push ( & segment) ) ;
191
198
return true ;
192
199
}
@@ -230,13 +237,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
230
237
}
231
238
}
232
239
233
- pub fn push_item_path < T > ( self , buffer : & mut T , def_id : DefId )
240
+ pub fn push_item_path < T > ( self , buffer : & mut T , def_id : DefId , pushed_prelude_crate : bool )
234
241
where T : ItemPathBuffer + Debug
235
242
{
236
- debug ! ( "push_item_path: buffer={:?} def_id={:?}" , buffer, def_id) ;
243
+ debug ! (
244
+ "push_item_path: buffer={:?} def_id={:?} pushed_prelude_crate={:?}" ,
245
+ buffer, def_id, pushed_prelude_crate
246
+ ) ;
237
247
match * buffer. root_mode ( ) {
238
248
RootMode :: Local if !def_id. is_local ( ) =>
239
- 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 } ,
240
250
_ => { }
241
251
}
242
252
@@ -245,11 +255,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
245
255
match key. disambiguated_data . data {
246
256
DefPathData :: CrateRoot => {
247
257
assert ! ( key. parent. is_none( ) ) ;
248
- self . push_krate_path ( buffer, def_id. krate ) ;
258
+ self . push_krate_path ( buffer, def_id. krate , pushed_prelude_crate ) ;
249
259
}
250
260
251
261
DefPathData :: Impl => {
252
- self . push_impl_path ( buffer, def_id) ;
262
+ self . push_impl_path ( buffer, def_id, pushed_prelude_crate ) ;
253
263
}
254
264
255
265
// Unclear if there is any value in distinguishing these.
@@ -272,34 +282,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
272
282
data @ DefPathData :: ClosureExpr |
273
283
data @ DefPathData :: ImplTrait |
274
284
data @ DefPathData :: GlobalMetaData ( ..) => {
275
- let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
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 self . sess . extern_prelude . contains (
285
- & data. as_interned_str ( ) . as_symbol ( )
286
- ) => { } ,
287
- _ => 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
+ }
288
295
}
289
296
297
+ self . push_item_path (
298
+ buffer, parent_did, pushed_prelude_crate || is_prelude_crate
299
+ ) ;
290
300
buffer. push ( & data. as_interned_str ( ) . as_symbol ( ) . as_str ( ) ) ;
291
301
} ,
292
302
293
303
DefPathData :: StructCtor => { // present `X` instead of `X::{{constructor}}`
294
304
let parent_def_id = self . parent_def_id ( def_id) . unwrap ( ) ;
295
- self . push_item_path ( buffer, parent_def_id) ;
305
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
296
306
}
297
307
}
298
308
}
299
309
300
- fn push_impl_path < T > ( self ,
301
- buffer : & mut T ,
302
- impl_def_id : DefId )
310
+ fn push_impl_path < T > (
311
+ self ,
312
+ buffer : & mut T ,
313
+ impl_def_id : DefId ,
314
+ pushed_prelude_crate : bool ,
315
+ )
303
316
where T : ItemPathBuffer + Debug
304
317
{
305
318
debug ! ( "push_impl_path: buffer={:?} impl_def_id={:?}" , buffer, impl_def_id) ;
@@ -314,7 +327,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
314
327
} ;
315
328
316
329
if !use_types {
317
- return self . push_impl_path_fallback ( buffer, impl_def_id) ;
330
+ return self . push_impl_path_fallback ( buffer, impl_def_id, pushed_prelude_crate ) ;
318
331
}
319
332
320
333
// Decide whether to print the parent path for the impl.
@@ -338,7 +351,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
338
351
// If the impl is not co-located with either self-type or
339
352
// trait-type, then fallback to a format that identifies
340
353
// the module more clearly.
341
- self . push_item_path ( buffer, parent_def_id) ;
354
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
342
355
if let Some ( trait_ref) = impl_trait_ref {
343
356
buffer. push ( & format ! ( "<impl {} for {}>" , trait_ref, self_ty) ) ;
344
357
} else {
@@ -364,13 +377,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
364
377
match self_ty. sty {
365
378
ty:: Adt ( adt_def, substs) => {
366
379
if substs. types ( ) . next ( ) . is_none ( ) { // ignore regions
367
- self . push_item_path ( buffer, adt_def. did ) ;
380
+ self . push_item_path ( buffer, adt_def. did , pushed_prelude_crate ) ;
368
381
} else {
369
382
buffer. push ( & format ! ( "<{}>" , self_ty) ) ;
370
383
}
371
384
}
372
385
373
- ty:: Foreign ( did) => self . push_item_path ( buffer, did) ,
386
+ ty:: Foreign ( did) => self . push_item_path ( buffer, did, pushed_prelude_crate ) ,
374
387
375
388
ty:: Bool |
376
389
ty:: Char |
@@ -387,16 +400,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
387
400
}
388
401
}
389
402
390
- fn push_impl_path_fallback < T > ( self ,
391
- buffer : & mut T ,
392
- impl_def_id : DefId )
403
+ fn push_impl_path_fallback < T > (
404
+ self ,
405
+ buffer : & mut T ,
406
+ impl_def_id : DefId ,
407
+ pushed_prelude_crate : bool ,
408
+ )
393
409
where T : ItemPathBuffer + Debug
394
410
{
395
411
// If no type info is available, fall back to
396
412
// pretty printing some span information. This should
397
413
// only occur very early in the compiler pipeline.
398
414
let parent_def_id = self . parent_def_id ( impl_def_id) . unwrap ( ) ;
399
- self . push_item_path ( buffer, parent_def_id) ;
415
+ self . push_item_path ( buffer, parent_def_id, pushed_prelude_crate ) ;
400
416
let node_id = self . hir . as_local_node_id ( impl_def_id) . unwrap ( ) ;
401
417
let item = self . hir . expect_item ( node_id) ;
402
418
let span_str = self . sess . source_map ( ) . span_to_string ( item. span ) ;
0 commit comments