|
10 | 10 |
|
11 | 11 | use hir::map::DefPathData;
|
12 | 12 | use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
13 |
| -use ty::{self, Ty, TyCtxt}; |
| 13 | +use ty::{self, DefIdTree, Ty, TyCtxt}; |
14 | 14 | use middle::cstore::{ExternCrate, ExternCrateSource};
|
15 | 15 | use syntax::ast;
|
16 | 16 | use syntax::symbol::{keywords, LocalInternedString, Symbol};
|
@@ -219,19 +219,73 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
219 | 219 | cur_def_key = self.def_key(parent);
|
220 | 220 | }
|
221 | 221 |
|
| 222 | + let visible_parent = visible_parent_map.get(&cur_def).cloned(); |
| 223 | + let actual_parent = self.parent(cur_def); |
| 224 | + debug!( |
| 225 | + "try_push_visible_item_path: visible_parent={:?} actual_parent={:?}", |
| 226 | + visible_parent, actual_parent, |
| 227 | + ); |
| 228 | + |
222 | 229 | let data = cur_def_key.disambiguated_data.data;
|
223 |
| - let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { |
224 |
| - if let DefPathData::CrateRoot = data { // reexported `extern crate` (#43189) |
225 |
| - self.original_crate_name(cur_def.krate).as_str() |
226 |
| - } else { |
227 |
| - Symbol::intern("<unnamed>").as_str() |
228 |
| - } |
229 |
| - }); |
| 230 | + let symbol = match data { |
| 231 | + // In order to output a path that could actually be imported (valid and visible), |
| 232 | + // we need to handle re-exports correctly. |
| 233 | + // |
| 234 | + // For example, take `std::os::unix::process::CommandExt`, this trait is actually |
| 235 | + // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). |
| 236 | + // |
| 237 | + // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is |
| 238 | + // private so the "true" path to `CommandExt` isn't accessible. |
| 239 | + // |
| 240 | + // In this case, the `visible_parent_map` will look something like this: |
| 241 | + // |
| 242 | + // (child) -> (parent) |
| 243 | + // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` |
| 244 | + // `std::sys::unix::ext::process` -> `std::sys::unix::ext` |
| 245 | + // `std::sys::unix::ext` -> `std::os` |
| 246 | + // |
| 247 | + // This is correct, as the visible parent of `std::sys::unix::ext` is in fact |
| 248 | + // `std::os`. |
| 249 | + // |
| 250 | + // When printing the path to `CommandExt` and looking at the `cur_def_key` that |
| 251 | + // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go |
| 252 | + // to the parent - resulting in a mangled path like |
| 253 | + // `std::os::ext::process::CommandExt`. |
| 254 | + // |
| 255 | + // Instead, we must detect that there was a re-export and instead print `unix` |
| 256 | + // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To |
| 257 | + // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with |
| 258 | + // the visible parent (`std::os`). If these do not match, then we iterate over |
| 259 | + // the children of the visible parent (as was done when computing |
| 260 | + // `visible_parent_map`), looking for the specific child we currently have and then |
| 261 | + // have access to the re-exported name. |
| 262 | + DefPathData::Module(module_name) if visible_parent != actual_parent => { |
| 263 | + let mut name: Option<ast::Ident> = None; |
| 264 | + if let Some(visible_parent) = visible_parent { |
| 265 | + for child in self.item_children(visible_parent).iter() { |
| 266 | + if child.def.def_id() == cur_def { |
| 267 | + name = Some(child.ident); |
| 268 | + } |
| 269 | + } |
| 270 | + } |
| 271 | + name.map(|n| n.as_str()).unwrap_or(module_name.as_str()) |
| 272 | + }, |
| 273 | + _ => { |
| 274 | + data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { |
| 275 | + // Re-exported `extern crate` (#43189). |
| 276 | + if let DefPathData::CrateRoot = data { |
| 277 | + self.original_crate_name(cur_def.krate).as_str() |
| 278 | + } else { |
| 279 | + Symbol::intern("<unnamed>").as_str() |
| 280 | + } |
| 281 | + }) |
| 282 | + }, |
| 283 | + }; |
230 | 284 | debug!("try_push_visible_item_path: symbol={:?}", symbol);
|
231 | 285 | cur_path.push(symbol);
|
232 | 286 |
|
233 |
| - match visible_parent_map.get(&cur_def) { |
234 |
| - Some(&def) => cur_def = def, |
| 287 | + match visible_parent { |
| 288 | + Some(def) => cur_def = def, |
235 | 289 | None => return false,
|
236 | 290 | };
|
237 | 291 | }
|
|
0 commit comments