Skip to content

Commit 02357e4

Browse files
committed
Attempt to resolve linking issues.
This commit takes a different approach to add the `crate::` prefix to item paths than previous commits. Previously, recursion was stopped after a prelude crate name was pushed to the path. It is theorized that this was the cause of the linking issues since the same path logic is used for symbol names and that not recursing meant that details were being missed that affect symbol names. As of this commit, instead of ceasing recursion, a flag is passed through to any subsequent recursive calls so that the same effect can be achieved by checking that flag.
1 parent 4cbd397 commit 02357e4

File tree

3 files changed

+60
-44
lines changed

3 files changed

+60
-44
lines changed

src/librustc/ty/item_path.rs

+58-42
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
7878
});
7979
let mut buffer = LocalPathBuffer::new(mode);
8080
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);
8282
buffer.into_string()
8383
}
8484

@@ -92,14 +92,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
9292
pub fn absolute_item_path_str(self, def_id: DefId) -> String {
9393
let mut buffer = LocalPathBuffer::new(RootMode::Absolute);
9494
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);
9696
buffer.into_string()
9797
}
9898

9999
/// Returns the "path" to a particular crate. This can proceed in
100100
/// various ways, depending on the `root_mode` of the `buffer`.
101101
/// (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)
103108
where T: ItemPathBuffer + Debug
104109
{
105110
debug!(
@@ -129,19 +134,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
129134
}) = *opt_extern_crate
130135
{
131136
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);
133138
} else {
134139
let name = self.crate_name(cnum).as_str();
135140
debug!("push_krate_path: name={:?}", name);
136141
buffer.push(&name);
137142
}
138-
} else if self.sess.edition() == Edition::Edition2018 {
143+
} else if self.sess.edition() == Edition::Edition2018 && !pushed_prelude_crate {
139144
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.
145147
if flag.get() {
146148
buffer.push(&keywords::Crate.name().as_str())
147149
}
@@ -161,7 +163,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
161163
/// If possible, this pushes a global path resolving to `external_def_id` that is visible
162164
/// from at least one local module and returns true. If the crate defining `external_def_id` is
163165
/// 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
165172
where T: ItemPathBuffer + Debug
166173
{
167174
debug!(
@@ -186,7 +193,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
186193
..
187194
}) => {
188195
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);
190197
cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
191198
return true;
192199
}
@@ -230,13 +237,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
230237
}
231238
}
232239

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)
234241
where T: ItemPathBuffer + Debug
235242
{
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+
);
237247
match *buffer.root_mode() {
238248
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 },
240250
_ => {}
241251
}
242252

@@ -245,11 +255,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
245255
match key.disambiguated_data.data {
246256
DefPathData::CrateRoot => {
247257
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);
249259
}
250260

251261
DefPathData::Impl => {
252-
self.push_impl_path(buffer, def_id);
262+
self.push_impl_path(buffer, def_id, pushed_prelude_crate);
253263
}
254264

255265
// Unclear if there is any value in distinguishing these.
@@ -272,34 +282,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
272282
data @ DefPathData::ClosureExpr |
273283
data @ DefPathData::ImplTrait |
274284
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+
}
288295
}
289296

297+
self.push_item_path(
298+
buffer, parent_did, pushed_prelude_crate || is_prelude_crate
299+
);
290300
buffer.push(&data.as_interned_str().as_symbol().as_str());
291301
},
292302

293303
DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
294304
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);
296306
}
297307
}
298308
}
299309

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+
)
303316
where T: ItemPathBuffer + Debug
304317
{
305318
debug!("push_impl_path: buffer={:?} impl_def_id={:?}", buffer, impl_def_id);
@@ -314,7 +327,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
314327
};
315328

316329
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);
318331
}
319332

320333
// Decide whether to print the parent path for the impl.
@@ -338,7 +351,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
338351
// If the impl is not co-located with either self-type or
339352
// trait-type, then fallback to a format that identifies
340353
// 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);
342355
if let Some(trait_ref) = impl_trait_ref {
343356
buffer.push(&format!("<impl {} for {}>", trait_ref, self_ty));
344357
} else {
@@ -364,13 +377,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
364377
match self_ty.sty {
365378
ty::Adt(adt_def, substs) => {
366379
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);
368381
} else {
369382
buffer.push(&format!("<{}>", self_ty));
370383
}
371384
}
372385

373-
ty::Foreign(did) => self.push_item_path(buffer, did),
386+
ty::Foreign(did) => self.push_item_path(buffer, did, pushed_prelude_crate),
374387

375388
ty::Bool |
376389
ty::Char |
@@ -387,16 +400,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
387400
}
388401
}
389402

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+
)
393409
where T: ItemPathBuffer + Debug
394410
{
395411
// If no type info is available, fall back to
396412
// pretty printing some span information. This should
397413
// only occur very early in the compiler pipeline.
398414
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);
400416
let node_id = self.hir.as_local_node_id(impl_def_id).unwrap();
401417
let item = self.hir.expect_item(node_id);
402418
let span_str = self.sess.source_map().span_to_string(item.span);

src/librustc_codegen_utils/symbol_names.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ fn get_symbol_hash<'a, 'tcx>(
228228
fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName {
229229
let mut buffer = SymbolPathBuffer::new();
230230
item_path::with_forced_absolute_paths(|| {
231-
tcx.push_item_path(&mut buffer, def_id);
231+
tcx.push_item_path(&mut buffer, def_id, false);
232232
});
233233
buffer.into_interned()
234234
}

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4008,7 +4008,7 @@ where F: Fn(DefId) -> Def {
40084008

40094009
let mut apb = AbsolutePathBuffer { names: vec![] };
40104010

4011-
tcx.push_item_path(&mut apb, def_id);
4011+
tcx.push_item_path(&mut apb, def_id, false);
40124012

40134013
hir::Path {
40144014
span: DUMMY_SP,

0 commit comments

Comments
 (0)