rustc: move the contents of ty::item_path to ty::print.
This commit is contained in:
parent
e0c75ff40d
commit
9f8aaa04e0
10 changed files with 573 additions and 580 deletions
|
@ -1,560 +0,0 @@
|
|||
use crate::hir::def::Namespace;
|
||||
use crate::hir::map::DefPathData;
|
||||
use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use crate::ty::{self, DefIdTree, Ty, TyCtxt};
|
||||
use crate::ty::print::PrintCx;
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{keywords, Symbol};
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
thread_local! {
|
||||
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false);
|
||||
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
|
||||
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
|
||||
/// Enforces that def_path_str always returns an absolute path and
|
||||
/// also enables "type-based" impl paths. This is used when building
|
||||
/// symbols that contain types, where we want the crate name to be
|
||||
/// part of the symbol.
|
||||
pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
FORCE_ABSOLUTE.with(|force| {
|
||||
let old = force.get();
|
||||
force.set(true);
|
||||
let result = f();
|
||||
force.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Force us to name impls with just the filename/line number. We
|
||||
/// normally try to use types. But at some points, notably while printing
|
||||
/// cycle errors, this can result in extra or suboptimal error output,
|
||||
/// so this variable disables that check.
|
||||
pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
FORCE_IMPL_FILENAME_LINE.with(|force| {
|
||||
let old = force.get();
|
||||
force.set(true);
|
||||
let result = f();
|
||||
force.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds the `crate::` prefix to paths where appropriate.
|
||||
pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
SHOULD_PREFIX_WITH_CRATE.with(|flag| {
|
||||
let old = flag.get();
|
||||
flag.set(true);
|
||||
let result = f();
|
||||
flag.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
|
||||
// (but also some things just print a `DefId` generally so maybe we need this?)
|
||||
fn guess_def_namespace(self, def_id: DefId) -> Namespace {
|
||||
match self.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::ValueNs(..) |
|
||||
DefPathData::EnumVariant(..) |
|
||||
DefPathData::Field(..) |
|
||||
DefPathData::AnonConst |
|
||||
DefPathData::ClosureExpr |
|
||||
DefPathData::StructCtor => Namespace::ValueNS,
|
||||
|
||||
DefPathData::MacroDef(..) => Namespace::MacroNS,
|
||||
|
||||
_ => Namespace::TypeNS,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string identifying this `DefId`. This string is
|
||||
/// suitable for user output. It is relative to the current crate
|
||||
/// root, unless with_forced_absolute_paths was used.
|
||||
pub fn def_path_str_with_substs_and_ns(
|
||||
self,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> String {
|
||||
debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
|
||||
if FORCE_ABSOLUTE.with(|force| force.get()) {
|
||||
PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns)
|
||||
} else {
|
||||
PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string identifying this def-id. This string is
|
||||
/// suitable for user output. It is relative to the current crate
|
||||
/// root, unless with_forced_absolute_paths was used.
|
||||
pub fn def_path_str(self, def_id: DefId) -> String {
|
||||
let ns = self.guess_def_namespace(def_id);
|
||||
self.def_path_str_with_substs_and_ns(def_id, None, ns)
|
||||
}
|
||||
|
||||
/// Returns a string identifying this local node-id.
|
||||
pub fn node_path_str(self, id: ast::NodeId) -> String {
|
||||
self.def_path_str(self.hir().local_def_id(id))
|
||||
}
|
||||
|
||||
/// Returns a string identifying this def-id. This string is
|
||||
/// suitable for user output. It always begins with a crate identifier.
|
||||
pub fn absolute_def_path_str(self, def_id: DefId) -> String {
|
||||
debug!("absolute_def_path_str: def_id={:?}", def_id);
|
||||
let ns = self.guess_def_namespace(def_id);
|
||||
PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ItemPathPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
|
||||
pub fn default_print_def_path(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> P::Path {
|
||||
debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
|
||||
let key = self.tcx.def_key(def_id);
|
||||
debug!("default_print_def_path: key={:?}", key);
|
||||
match key.disambiguated_data.data {
|
||||
DefPathData::CrateRoot => {
|
||||
assert!(key.parent.is_none());
|
||||
self.path_crate(def_id.krate)
|
||||
}
|
||||
|
||||
DefPathData::Impl => {
|
||||
self.print_impl_path(def_id, substs, ns)
|
||||
}
|
||||
|
||||
// Unclear if there is any value in distinguishing these.
|
||||
// Probably eventually (and maybe we would even want
|
||||
// finer-grained distinctions, e.g., between enum/struct).
|
||||
data @ DefPathData::Misc |
|
||||
data @ DefPathData::TypeNs(..) |
|
||||
data @ DefPathData::Trait(..) |
|
||||
data @ DefPathData::TraitAlias(..) |
|
||||
data @ DefPathData::AssocTypeInTrait(..) |
|
||||
data @ DefPathData::AssocTypeInImpl(..) |
|
||||
data @ DefPathData::AssocExistentialInImpl(..) |
|
||||
data @ DefPathData::ValueNs(..) |
|
||||
data @ DefPathData::Module(..) |
|
||||
data @ DefPathData::TypeParam(..) |
|
||||
data @ DefPathData::LifetimeParam(..) |
|
||||
data @ DefPathData::ConstParam(..) |
|
||||
data @ DefPathData::EnumVariant(..) |
|
||||
data @ DefPathData::Field(..) |
|
||||
data @ DefPathData::AnonConst |
|
||||
data @ DefPathData::MacroDef(..) |
|
||||
data @ DefPathData::ClosureExpr |
|
||||
data @ DefPathData::ImplTrait |
|
||||
data @ DefPathData::GlobalMetaData(..) => {
|
||||
let parent_did = self.tcx.parent(def_id).unwrap();
|
||||
let path = self.print_def_path(parent_did, None, ns);
|
||||
self.path_append(path, &data.as_interned_str().as_symbol().as_str())
|
||||
},
|
||||
|
||||
DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
|
||||
let parent_def_id = self.tcx.parent(def_id).unwrap();
|
||||
self.print_def_path(parent_def_id, substs, ns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_print_impl_path(
|
||||
&mut self,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> P::Path {
|
||||
debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id);
|
||||
let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
|
||||
|
||||
// Decide whether to print the parent path for the impl.
|
||||
// Logically, since impls are global, it's never needed, but
|
||||
// users may find it useful. Currently, we omit the parent if
|
||||
// the impl is either in the same module as the self-type or
|
||||
// as the trait.
|
||||
let mut self_ty = self.tcx.type_of(impl_def_id);
|
||||
if let Some(substs) = substs {
|
||||
self_ty = self_ty.subst(self.tcx, substs);
|
||||
}
|
||||
let in_self_mod = match characteristic_def_id_of_type(self_ty) {
|
||||
None => false,
|
||||
Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id),
|
||||
};
|
||||
|
||||
let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id);
|
||||
if let Some(substs) = substs {
|
||||
impl_trait_ref = impl_trait_ref.subst(self.tcx, substs);
|
||||
}
|
||||
let in_trait_mod = match impl_trait_ref {
|
||||
None => false,
|
||||
Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id),
|
||||
};
|
||||
|
||||
if !in_self_mod && !in_trait_mod {
|
||||
// If the impl is not co-located with either self-type or
|
||||
// trait-type, then fallback to a format that identifies
|
||||
// the module more clearly.
|
||||
let path = self.print_def_path(parent_def_id, None, ns);
|
||||
if let Some(trait_ref) = impl_trait_ref {
|
||||
return self.path_append(path, &format!("<impl {} for {}>", trait_ref, self_ty));
|
||||
} else {
|
||||
return self.path_append(path, &format!("<impl {}>", self_ty));
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try to give a good form that would be valid language
|
||||
// syntax. Preferably using associated item notation.
|
||||
|
||||
if let Some(trait_ref) = impl_trait_ref {
|
||||
// Trait impls.
|
||||
return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref));
|
||||
}
|
||||
|
||||
// Inherent impls. Try to print `Foo::bar` for an inherent
|
||||
// impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
|
||||
// anything other than a simple path.
|
||||
match self_ty.sty {
|
||||
ty::Adt(adt_def, substs) => {
|
||||
// FIXME(eddyb) this should recurse to build the path piecewise.
|
||||
// self.print_def_path(adt_def.did, Some(substs), ns)
|
||||
let mut s = String::new();
|
||||
crate::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap();
|
||||
self.path_impl(&s)
|
||||
}
|
||||
|
||||
ty::Foreign(did) => self.print_def_path(did, None, ns),
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) |
|
||||
ty::Str => {
|
||||
self.path_impl(&self_ty.to_string())
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.path_impl(&format!("<{}>", self_ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// As a heuristic, when we see an impl, if we see that the
|
||||
/// 'self type' is a type defined in the same module as the impl,
|
||||
/// we can omit including the path to the impl itself. This
|
||||
/// function tries to find a "characteristic `DefId`" for a
|
||||
/// type. It's just a heuristic so it makes some questionable
|
||||
/// decisions and we may want to adjust it later.
|
||||
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
|
||||
match ty.sty {
|
||||
ty::Adt(adt_def, _) => Some(adt_def.did),
|
||||
|
||||
ty::Dynamic(data, ..) => data.principal_def_id(),
|
||||
|
||||
ty::Array(subty, _) |
|
||||
ty::Slice(subty) => characteristic_def_id_of_type(subty),
|
||||
|
||||
ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
|
||||
|
||||
ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
|
||||
|
||||
ty::Tuple(ref tys) => tys.iter()
|
||||
.filter_map(|ty| characteristic_def_id_of_type(ty))
|
||||
.next(),
|
||||
|
||||
ty::FnDef(def_id, _) |
|
||||
ty::Closure(def_id, _) |
|
||||
ty::Generator(def_id, _, _) |
|
||||
ty::Foreign(def_id) => Some(def_id),
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Str |
|
||||
ty::FnPtr(_) |
|
||||
ty::Projection(_) |
|
||||
ty::Placeholder(..) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Param(_) |
|
||||
ty::Opaque(..) |
|
||||
ty::Infer(_) |
|
||||
ty::Bound(..) |
|
||||
ty::Error |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Never |
|
||||
ty::Float(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Unifying Trait for different kinds of item paths we might
|
||||
/// construct. The basic interface is that components get appended.
|
||||
pub trait ItemPathPrinter: Sized {
|
||||
type Path;
|
||||
|
||||
fn print_def_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.default_print_def_path(def_id, substs, ns)
|
||||
}
|
||||
fn print_impl_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.default_print_impl_path(impl_def_id, substs, ns)
|
||||
}
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path;
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path;
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path;
|
||||
}
|
||||
|
||||
struct AbsolutePathPrinter;
|
||||
|
||||
impl ItemPathPrinter for AbsolutePathPrinter {
|
||||
type Path = String;
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
self.tcx.original_crate_name(cnum).to_string()
|
||||
}
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
|
||||
text.to_string()
|
||||
}
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
mut path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path {
|
||||
if !path.is_empty() {
|
||||
path.push_str("::");
|
||||
}
|
||||
path.push_str(text);
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalPathPrinter;
|
||||
|
||||
impl LocalPathPrinter {
|
||||
/// If possible, this returns a global path resolving to `def_id` that is visible
|
||||
/// from at least one local module and returns true. If the crate defining `def_id` is
|
||||
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
|
||||
fn try_print_visible_def_path(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
def_id: DefId,
|
||||
ns: Namespace,
|
||||
) -> Option<<Self as ItemPathPrinter>::Path> {
|
||||
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||
|
||||
// If `def_id` is a direct or injected extern crate, return the
|
||||
// path to the crate followed by the path to the item within the crate.
|
||||
if def_id.index == CRATE_DEF_INDEX {
|
||||
let cnum = def_id.krate;
|
||||
|
||||
if cnum == LOCAL_CRATE {
|
||||
return Some(self.path_crate(cnum));
|
||||
}
|
||||
|
||||
// In local mode, when we encounter a crate other than
|
||||
// LOCAL_CRATE, execution proceeds in one of two ways:
|
||||
//
|
||||
// 1. for a direct dependency, where user added an
|
||||
// `extern crate` manually, we put the `extern
|
||||
// crate` as the parent. So you wind up with
|
||||
// something relative to the current crate.
|
||||
// 2. for an extern inferred from a path or an indirect crate,
|
||||
// where there is no explicit `extern crate`, we just prepend
|
||||
// the crate name.
|
||||
match *self.tcx.extern_crate(def_id) {
|
||||
Some(ExternCrate {
|
||||
src: ExternCrateSource::Extern(def_id),
|
||||
direct: true,
|
||||
span,
|
||||
..
|
||||
}) => {
|
||||
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||
let path = if !span.is_dummy() {
|
||||
self.print_def_path(def_id, None, ns)
|
||||
} else {
|
||||
self.path_crate(cnum)
|
||||
};
|
||||
return Some(path);
|
||||
}
|
||||
None => {
|
||||
return Some(self.path_crate(cnum));
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
if def_id.is_local() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE);
|
||||
|
||||
let mut cur_def_key = self.tcx.def_key(def_id);
|
||||
debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
|
||||
|
||||
// For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
|
||||
if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
|
||||
let parent = DefId {
|
||||
krate: def_id.krate,
|
||||
index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
|
||||
};
|
||||
|
||||
cur_def_key = self.tcx.def_key(parent);
|
||||
}
|
||||
|
||||
let visible_parent = visible_parent_map.get(&def_id).cloned()?;
|
||||
let path = self.try_print_visible_def_path(visible_parent, ns)?;
|
||||
let actual_parent = self.tcx.parent(def_id);
|
||||
|
||||
let data = cur_def_key.disambiguated_data.data;
|
||||
debug!(
|
||||
"try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
|
||||
data, visible_parent, actual_parent,
|
||||
);
|
||||
|
||||
let symbol = match data {
|
||||
// In order to output a path that could actually be imported (valid and visible),
|
||||
// we need to handle re-exports correctly.
|
||||
//
|
||||
// For example, take `std::os::unix::process::CommandExt`, this trait is actually
|
||||
// defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
|
||||
//
|
||||
// `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
|
||||
// private so the "true" path to `CommandExt` isn't accessible.
|
||||
//
|
||||
// In this case, the `visible_parent_map` will look something like this:
|
||||
//
|
||||
// (child) -> (parent)
|
||||
// `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
|
||||
// `std::sys::unix::ext::process` -> `std::sys::unix::ext`
|
||||
// `std::sys::unix::ext` -> `std::os`
|
||||
//
|
||||
// This is correct, as the visible parent of `std::sys::unix::ext` is in fact
|
||||
// `std::os`.
|
||||
//
|
||||
// When printing the path to `CommandExt` and looking at the `cur_def_key` that
|
||||
// corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
|
||||
// to the parent - resulting in a mangled path like
|
||||
// `std::os::ext::process::CommandExt`.
|
||||
//
|
||||
// Instead, we must detect that there was a re-export and instead print `unix`
|
||||
// (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
|
||||
// do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
|
||||
// the visible parent (`std::os`). If these do not match, then we iterate over
|
||||
// the children of the visible parent (as was done when computing
|
||||
// `visible_parent_map`), looking for the specific child we currently have and then
|
||||
// have access to the re-exported name.
|
||||
DefPathData::Module(actual_name) |
|
||||
DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => {
|
||||
self.tcx.item_children(visible_parent)
|
||||
.iter()
|
||||
.find(|child| child.def.def_id() == def_id)
|
||||
.map(|child| child.ident.as_str())
|
||||
.unwrap_or_else(|| actual_name.as_str())
|
||||
}
|
||||
_ => {
|
||||
data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
|
||||
// Re-exported `extern crate` (#43189).
|
||||
if let DefPathData::CrateRoot = data {
|
||||
self.tcx.original_crate_name(def_id.krate).as_str()
|
||||
} else {
|
||||
Symbol::intern("<unnamed>").as_str()
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
debug!("try_print_visible_def_path: symbol={:?}", symbol);
|
||||
Some(self.path_append(path, &symbol))
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemPathPrinter for LocalPathPrinter {
|
||||
type Path = String;
|
||||
|
||||
fn print_def_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.try_print_visible_def_path(def_id, ns)
|
||||
.unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns))
|
||||
}
|
||||
fn print_impl_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
// Always use types for non-local impls, where types are always
|
||||
// available, and filename/line-number is mostly uninteresting.
|
||||
let use_types = !impl_def_id.is_local() || {
|
||||
// Otherwise, use filename/line-number if forced.
|
||||
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
|
||||
!force_no_types
|
||||
};
|
||||
|
||||
if !use_types {
|
||||
// If no type info is available, fall back to
|
||||
// pretty printing some span information. This should
|
||||
// only occur very early in the compiler pipeline.
|
||||
// FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)`
|
||||
let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
|
||||
let path = self.print_def_path(parent_def_id, None, ns);
|
||||
let span = self.tcx.def_span(impl_def_id);
|
||||
return self.path_append(path, &format!("<impl at {:?}>", span));
|
||||
}
|
||||
|
||||
self.default_print_impl_path(impl_def_id, substs, ns)
|
||||
}
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
if cnum == LOCAL_CRATE {
|
||||
if self.tcx.sess.rust_2018() {
|
||||
// We add the `crate::` keyword on Rust 2018, only when desired.
|
||||
if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
|
||||
return keywords::Crate.name().to_string();
|
||||
}
|
||||
}
|
||||
String::new()
|
||||
} else {
|
||||
self.tcx.crate_name(cnum).to_string()
|
||||
}
|
||||
}
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
|
||||
text.to_string()
|
||||
}
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
mut path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path {
|
||||
if !path.is_empty() {
|
||||
path.push_str("::");
|
||||
}
|
||||
path.push_str(text);
|
||||
path
|
||||
}
|
||||
}
|
|
@ -95,7 +95,6 @@ mod erase_regions;
|
|||
pub mod fast_reject;
|
||||
pub mod fold;
|
||||
pub mod inhabitedness;
|
||||
pub mod item_path;
|
||||
pub mod layout;
|
||||
pub mod _match;
|
||||
pub mod outlives;
|
||||
|
|
|
@ -1,11 +1,64 @@
|
|||
use crate::ty::{self, TyCtxt, TypeFoldable};
|
||||
use crate::hir::def::Namespace;
|
||||
use crate::hir::map::DefPathData;
|
||||
use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{keywords, Symbol};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use syntax::symbol::InternedString;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
|
||||
thread_local! {
|
||||
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false);
|
||||
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
|
||||
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
|
||||
/// Enforces that def_path_str always returns an absolute path and
|
||||
/// also enables "type-based" impl paths. This is used when building
|
||||
/// symbols that contain types, where we want the crate name to be
|
||||
/// part of the symbol.
|
||||
pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
FORCE_ABSOLUTE.with(|force| {
|
||||
let old = force.get();
|
||||
force.set(true);
|
||||
let result = f();
|
||||
force.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Force us to name impls with just the filename/line number. We
|
||||
/// normally try to use types. But at some points, notably while printing
|
||||
/// cycle errors, this can result in extra or suboptimal error output,
|
||||
/// so this variable disables that check.
|
||||
pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
FORCE_IMPL_FILENAME_LINE.with(|force| {
|
||||
let old = force.get();
|
||||
force.set(true);
|
||||
let result = f();
|
||||
force.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds the `crate::` prefix to paths where appropriate.
|
||||
pub fn with_crate_prefix<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
SHOULD_PREFIX_WITH_CRATE.with(|flag| {
|
||||
let old = flag.get();
|
||||
flag.set(true);
|
||||
let result = f();
|
||||
flag.set(old);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this module uses `pub(crate)` for things used only
|
||||
// from `ppaux` - when that is removed, they can be re-privatized.
|
||||
|
||||
|
@ -89,6 +142,511 @@ pub trait Print<'tcx, P> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Printer: Sized {
|
||||
type Path;
|
||||
|
||||
fn print_def_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.default_print_def_path(def_id, substs, ns)
|
||||
}
|
||||
fn print_impl_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.default_print_impl_path(impl_def_id, substs, ns)
|
||||
}
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path;
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path;
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path;
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
|
||||
// (but also some things just print a `DefId` generally so maybe we need this?)
|
||||
fn guess_def_namespace(self, def_id: DefId) -> Namespace {
|
||||
match self.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::ValueNs(..) |
|
||||
DefPathData::EnumVariant(..) |
|
||||
DefPathData::Field(..) |
|
||||
DefPathData::AnonConst |
|
||||
DefPathData::ClosureExpr |
|
||||
DefPathData::StructCtor => Namespace::ValueNS,
|
||||
|
||||
DefPathData::MacroDef(..) => Namespace::MacroNS,
|
||||
|
||||
_ => Namespace::TypeNS,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string identifying this `DefId`. This string is
|
||||
/// suitable for user output. It is relative to the current crate
|
||||
/// root, unless with_forced_absolute_paths was used.
|
||||
pub fn def_path_str_with_substs_and_ns(
|
||||
self,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> String {
|
||||
debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
|
||||
if FORCE_ABSOLUTE.with(|force| force.get()) {
|
||||
PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns)
|
||||
} else {
|
||||
PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string identifying this `DefId`. This string is
|
||||
/// suitable for user output. It is relative to the current crate
|
||||
/// root, unless with_forced_absolute_paths was used.
|
||||
pub fn def_path_str(self, def_id: DefId) -> String {
|
||||
let ns = self.guess_def_namespace(def_id);
|
||||
self.def_path_str_with_substs_and_ns(def_id, None, ns)
|
||||
}
|
||||
|
||||
/// Returns a string identifying this local node-id.
|
||||
// FIXME(eddyb) remove in favor of calling `def_path_str` directly.
|
||||
pub fn node_path_str(self, id: ast::NodeId) -> String {
|
||||
self.def_path_str(self.hir().local_def_id(id))
|
||||
}
|
||||
|
||||
/// Returns a string identifying this `DefId`. This string is
|
||||
/// suitable for user output. It always begins with a crate identifier.
|
||||
pub fn absolute_def_path_str(self, def_id: DefId) -> String {
|
||||
debug!("absolute_def_path_str: def_id={:?}", def_id);
|
||||
let ns = self.guess_def_namespace(def_id);
|
||||
PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Printer> PrintCx<'a, 'gcx, 'tcx, P> {
|
||||
pub fn default_print_def_path(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> P::Path {
|
||||
debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
|
||||
let key = self.tcx.def_key(def_id);
|
||||
debug!("default_print_def_path: key={:?}", key);
|
||||
match key.disambiguated_data.data {
|
||||
DefPathData::CrateRoot => {
|
||||
assert!(key.parent.is_none());
|
||||
self.path_crate(def_id.krate)
|
||||
}
|
||||
|
||||
DefPathData::Impl => {
|
||||
self.print_impl_path(def_id, substs, ns)
|
||||
}
|
||||
|
||||
// Unclear if there is any value in distinguishing these.
|
||||
// Probably eventually (and maybe we would even want
|
||||
// finer-grained distinctions, e.g., between enum/struct).
|
||||
data @ DefPathData::Misc |
|
||||
data @ DefPathData::TypeNs(..) |
|
||||
data @ DefPathData::Trait(..) |
|
||||
data @ DefPathData::TraitAlias(..) |
|
||||
data @ DefPathData::AssocTypeInTrait(..) |
|
||||
data @ DefPathData::AssocTypeInImpl(..) |
|
||||
data @ DefPathData::AssocExistentialInImpl(..) |
|
||||
data @ DefPathData::ValueNs(..) |
|
||||
data @ DefPathData::Module(..) |
|
||||
data @ DefPathData::TypeParam(..) |
|
||||
data @ DefPathData::LifetimeParam(..) |
|
||||
data @ DefPathData::ConstParam(..) |
|
||||
data @ DefPathData::EnumVariant(..) |
|
||||
data @ DefPathData::Field(..) |
|
||||
data @ DefPathData::AnonConst |
|
||||
data @ DefPathData::MacroDef(..) |
|
||||
data @ DefPathData::ClosureExpr |
|
||||
data @ DefPathData::ImplTrait |
|
||||
data @ DefPathData::GlobalMetaData(..) => {
|
||||
let parent_did = self.tcx.parent(def_id).unwrap();
|
||||
let path = self.print_def_path(parent_did, None, ns);
|
||||
self.path_append(path, &data.as_interned_str().as_symbol().as_str())
|
||||
},
|
||||
|
||||
DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
|
||||
let parent_def_id = self.tcx.parent(def_id).unwrap();
|
||||
self.print_def_path(parent_def_id, substs, ns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_print_impl_path(
|
||||
&mut self,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> P::Path {
|
||||
debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id);
|
||||
let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
|
||||
|
||||
// Decide whether to print the parent path for the impl.
|
||||
// Logically, since impls are global, it's never needed, but
|
||||
// users may find it useful. Currently, we omit the parent if
|
||||
// the impl is either in the same module as the self-type or
|
||||
// as the trait.
|
||||
let mut self_ty = self.tcx.type_of(impl_def_id);
|
||||
if let Some(substs) = substs {
|
||||
self_ty = self_ty.subst(self.tcx, substs);
|
||||
}
|
||||
let in_self_mod = match characteristic_def_id_of_type(self_ty) {
|
||||
None => false,
|
||||
Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id),
|
||||
};
|
||||
|
||||
let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id);
|
||||
if let Some(substs) = substs {
|
||||
impl_trait_ref = impl_trait_ref.subst(self.tcx, substs);
|
||||
}
|
||||
let in_trait_mod = match impl_trait_ref {
|
||||
None => false,
|
||||
Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id),
|
||||
};
|
||||
|
||||
if !in_self_mod && !in_trait_mod {
|
||||
// If the impl is not co-located with either self-type or
|
||||
// trait-type, then fallback to a format that identifies
|
||||
// the module more clearly.
|
||||
let path = self.print_def_path(parent_def_id, None, ns);
|
||||
if let Some(trait_ref) = impl_trait_ref {
|
||||
return self.path_append(path, &format!("<impl {} for {}>", trait_ref, self_ty));
|
||||
} else {
|
||||
return self.path_append(path, &format!("<impl {}>", self_ty));
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try to give a good form that would be valid language
|
||||
// syntax. Preferably using associated item notation.
|
||||
|
||||
if let Some(trait_ref) = impl_trait_ref {
|
||||
// Trait impls.
|
||||
return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref));
|
||||
}
|
||||
|
||||
// Inherent impls. Try to print `Foo::bar` for an inherent
|
||||
// impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
|
||||
// anything other than a simple path.
|
||||
match self_ty.sty {
|
||||
ty::Adt(adt_def, substs) => {
|
||||
// FIXME(eddyb) this should recurse to build the path piecewise.
|
||||
// self.print_def_path(adt_def.did, Some(substs), ns)
|
||||
let mut s = String::new();
|
||||
crate::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap();
|
||||
self.path_impl(&s)
|
||||
}
|
||||
|
||||
ty::Foreign(did) => self.print_def_path(did, None, ns),
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Float(_) |
|
||||
ty::Str => {
|
||||
self.path_impl(&self_ty.to_string())
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.path_impl(&format!("<{}>", self_ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// As a heuristic, when we see an impl, if we see that the
|
||||
/// 'self type' is a type defined in the same module as the impl,
|
||||
/// we can omit including the path to the impl itself. This
|
||||
/// function tries to find a "characteristic `DefId`" for a
|
||||
/// type. It's just a heuristic so it makes some questionable
|
||||
/// decisions and we may want to adjust it later.
|
||||
pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
|
||||
match ty.sty {
|
||||
ty::Adt(adt_def, _) => Some(adt_def.did),
|
||||
|
||||
ty::Dynamic(data, ..) => data.principal_def_id(),
|
||||
|
||||
ty::Array(subty, _) |
|
||||
ty::Slice(subty) => characteristic_def_id_of_type(subty),
|
||||
|
||||
ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty),
|
||||
|
||||
ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
|
||||
|
||||
ty::Tuple(ref tys) => tys.iter()
|
||||
.filter_map(|ty| characteristic_def_id_of_type(ty))
|
||||
.next(),
|
||||
|
||||
ty::FnDef(def_id, _) |
|
||||
ty::Closure(def_id, _) |
|
||||
ty::Generator(def_id, _, _) |
|
||||
ty::Foreign(def_id) => Some(def_id),
|
||||
|
||||
ty::Bool |
|
||||
ty::Char |
|
||||
ty::Int(_) |
|
||||
ty::Uint(_) |
|
||||
ty::Str |
|
||||
ty::FnPtr(_) |
|
||||
ty::Projection(_) |
|
||||
ty::Placeholder(..) |
|
||||
ty::UnnormalizedProjection(..) |
|
||||
ty::Param(_) |
|
||||
ty::Opaque(..) |
|
||||
ty::Infer(_) |
|
||||
ty::Bound(..) |
|
||||
ty::Error |
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::Never |
|
||||
ty::Float(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) remove, alongside `FORCE_ABSOLUTE` and `absolute_def_path_str`.
|
||||
struct AbsolutePathPrinter;
|
||||
|
||||
impl Printer for AbsolutePathPrinter {
|
||||
type Path = String;
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
self.tcx.original_crate_name(cnum).to_string()
|
||||
}
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
|
||||
text.to_string()
|
||||
}
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
mut path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path {
|
||||
if !path.is_empty() {
|
||||
path.push_str("::");
|
||||
}
|
||||
path.push_str(text);
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FmtPrinter<F: fmt::Write> {
|
||||
pub fmt: F,
|
||||
}
|
||||
|
||||
// FIXME(eddyb) integrate into `FmtPrinter`.
|
||||
struct LocalPathPrinter;
|
||||
|
||||
impl LocalPathPrinter {
|
||||
/// If possible, this returns a global path resolving to `def_id` that is visible
|
||||
/// from at least one local module and returns true. If the crate defining `def_id` is
|
||||
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
|
||||
fn try_print_visible_def_path(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
def_id: DefId,
|
||||
ns: Namespace,
|
||||
) -> Option<<Self as Printer>::Path> {
|
||||
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||
|
||||
// If `def_id` is a direct or injected extern crate, return the
|
||||
// path to the crate followed by the path to the item within the crate.
|
||||
if def_id.index == CRATE_DEF_INDEX {
|
||||
let cnum = def_id.krate;
|
||||
|
||||
if cnum == LOCAL_CRATE {
|
||||
return Some(self.path_crate(cnum));
|
||||
}
|
||||
|
||||
// In local mode, when we encounter a crate other than
|
||||
// LOCAL_CRATE, execution proceeds in one of two ways:
|
||||
//
|
||||
// 1. for a direct dependency, where user added an
|
||||
// `extern crate` manually, we put the `extern
|
||||
// crate` as the parent. So you wind up with
|
||||
// something relative to the current crate.
|
||||
// 2. for an extern inferred from a path or an indirect crate,
|
||||
// where there is no explicit `extern crate`, we just prepend
|
||||
// the crate name.
|
||||
match *self.tcx.extern_crate(def_id) {
|
||||
Some(ExternCrate {
|
||||
src: ExternCrateSource::Extern(def_id),
|
||||
direct: true,
|
||||
span,
|
||||
..
|
||||
}) => {
|
||||
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||
let path = if !span.is_dummy() {
|
||||
self.print_def_path(def_id, None, ns)
|
||||
} else {
|
||||
self.path_crate(cnum)
|
||||
};
|
||||
return Some(path);
|
||||
}
|
||||
None => {
|
||||
return Some(self.path_crate(cnum));
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
if def_id.is_local() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE);
|
||||
|
||||
let mut cur_def_key = self.tcx.def_key(def_id);
|
||||
debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
|
||||
|
||||
// For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
|
||||
if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
|
||||
let parent = DefId {
|
||||
krate: def_id.krate,
|
||||
index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
|
||||
};
|
||||
|
||||
cur_def_key = self.tcx.def_key(parent);
|
||||
}
|
||||
|
||||
let visible_parent = visible_parent_map.get(&def_id).cloned()?;
|
||||
let path = self.try_print_visible_def_path(visible_parent, ns)?;
|
||||
let actual_parent = self.tcx.parent(def_id);
|
||||
|
||||
let data = cur_def_key.disambiguated_data.data;
|
||||
debug!(
|
||||
"try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}",
|
||||
data, visible_parent, actual_parent,
|
||||
);
|
||||
|
||||
let symbol = match data {
|
||||
// In order to output a path that could actually be imported (valid and visible),
|
||||
// we need to handle re-exports correctly.
|
||||
//
|
||||
// For example, take `std::os::unix::process::CommandExt`, this trait is actually
|
||||
// defined at `std::sys::unix::ext::process::CommandExt` (at time of writing).
|
||||
//
|
||||
// `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is
|
||||
// private so the "true" path to `CommandExt` isn't accessible.
|
||||
//
|
||||
// In this case, the `visible_parent_map` will look something like this:
|
||||
//
|
||||
// (child) -> (parent)
|
||||
// `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process`
|
||||
// `std::sys::unix::ext::process` -> `std::sys::unix::ext`
|
||||
// `std::sys::unix::ext` -> `std::os`
|
||||
//
|
||||
// This is correct, as the visible parent of `std::sys::unix::ext` is in fact
|
||||
// `std::os`.
|
||||
//
|
||||
// When printing the path to `CommandExt` and looking at the `cur_def_key` that
|
||||
// corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go
|
||||
// to the parent - resulting in a mangled path like
|
||||
// `std::os::ext::process::CommandExt`.
|
||||
//
|
||||
// Instead, we must detect that there was a re-export and instead print `unix`
|
||||
// (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To
|
||||
// do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with
|
||||
// the visible parent (`std::os`). If these do not match, then we iterate over
|
||||
// the children of the visible parent (as was done when computing
|
||||
// `visible_parent_map`), looking for the specific child we currently have and then
|
||||
// have access to the re-exported name.
|
||||
DefPathData::Module(actual_name) |
|
||||
DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => {
|
||||
self.tcx.item_children(visible_parent)
|
||||
.iter()
|
||||
.find(|child| child.def.def_id() == def_id)
|
||||
.map(|child| child.ident.as_str())
|
||||
.unwrap_or_else(|| actual_name.as_str())
|
||||
}
|
||||
_ => {
|
||||
data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
|
||||
// Re-exported `extern crate` (#43189).
|
||||
if let DefPathData::CrateRoot = data {
|
||||
self.tcx.original_crate_name(def_id.krate).as_str()
|
||||
} else {
|
||||
Symbol::intern("<unnamed>").as_str()
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
debug!("try_print_visible_def_path: symbol={:?}", symbol);
|
||||
Some(self.path_append(path, &symbol))
|
||||
}
|
||||
}
|
||||
|
||||
impl Printer for LocalPathPrinter {
|
||||
type Path = String;
|
||||
|
||||
fn print_def_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
self.try_print_visible_def_path(def_id, ns)
|
||||
.unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns))
|
||||
}
|
||||
fn print_impl_path(
|
||||
self: &mut PrintCx<'_, '_, 'tcx, Self>,
|
||||
impl_def_id: DefId,
|
||||
substs: Option<SubstsRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Self::Path {
|
||||
// Always use types for non-local impls, where types are always
|
||||
// available, and filename/line-number is mostly uninteresting.
|
||||
let use_types = !impl_def_id.is_local() || {
|
||||
// Otherwise, use filename/line-number if forced.
|
||||
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
|
||||
!force_no_types
|
||||
};
|
||||
|
||||
if !use_types {
|
||||
// If no type info is available, fall back to
|
||||
// pretty printing some span information. This should
|
||||
// only occur very early in the compiler pipeline.
|
||||
// FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)`
|
||||
let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
|
||||
let path = self.print_def_path(parent_def_id, None, ns);
|
||||
let span = self.tcx.def_span(impl_def_id);
|
||||
return self.path_append(path, &format!("<impl at {:?}>", span));
|
||||
}
|
||||
|
||||
self.default_print_impl_path(impl_def_id, substs, ns)
|
||||
}
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
if cnum == LOCAL_CRATE {
|
||||
if self.tcx.sess.rust_2018() {
|
||||
// We add the `crate::` keyword on Rust 2018, only when desired.
|
||||
if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
|
||||
return keywords::Crate.name().to_string();
|
||||
}
|
||||
}
|
||||
String::new()
|
||||
} else {
|
||||
self.tcx.crate_name(cnum).to_string()
|
||||
}
|
||||
}
|
||||
fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
|
||||
text.to_string()
|
||||
}
|
||||
fn path_append(
|
||||
self: &mut PrintCx<'_, '_, '_, Self>,
|
||||
mut path: Self::Path,
|
||||
text: &str,
|
||||
) -> Self::Path {
|
||||
if !path.is_empty() {
|
||||
path.push_str("::");
|
||||
}
|
||||
path.push_str(text);
|
||||
path
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
|
||||
use crate::dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex};
|
||||
use crate::ty::tls;
|
||||
use crate::ty::{TyCtxt};
|
||||
use crate::ty::{self, TyCtxt};
|
||||
use crate::ty::query::Query;
|
||||
use crate::ty::query::config::{QueryConfig, QueryDescription};
|
||||
use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo};
|
||||
use crate::ty::item_path;
|
||||
|
||||
use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
|
||||
|
||||
|
@ -299,7 +298,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// sometimes cycles itself, leading to extra cycle errors.
|
||||
// (And cycle errors around impls tend to occur during the
|
||||
// collect/coherence phases anyhow.)
|
||||
item_path::with_forced_impl_filename_line(|| {
|
||||
ty::print::with_forced_impl_filename_line(|| {
|
||||
let span = fix_span(stack[1 % stack.len()].span, &stack[0].query);
|
||||
let mut err = struct_span_err!(self.sess,
|
||||
span,
|
||||
|
|
|
@ -93,8 +93,7 @@ use rustc::hir::Node;
|
|||
use rustc::hir::CodegenFnAttrFlags;
|
||||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::ich::NodeIdHashingMode;
|
||||
use rustc::ty::item_path::{self, ItemPathPrinter};
|
||||
use rustc::ty::print::PrintCx;
|
||||
use rustc::ty::print::{PrintCx, Printer};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
|
@ -225,7 +224,7 @@ fn get_symbol_hash<'a, 'tcx>(
|
|||
}
|
||||
|
||||
fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName {
|
||||
item_path::with_forced_absolute_paths(|| {
|
||||
ty::print::with_forced_absolute_paths(|| {
|
||||
PrintCx::new(tcx, SymbolPathPrinter)
|
||||
.print_def_path(def_id, None, Namespace::ValueNS)
|
||||
.into_interned()
|
||||
|
@ -400,7 +399,7 @@ impl SymbolPath {
|
|||
|
||||
struct SymbolPathPrinter;
|
||||
|
||||
impl ItemPathPrinter for SymbolPathPrinter {
|
||||
impl Printer for SymbolPathPrinter {
|
||||
type Path = SymbolPath;
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
|
|
|
@ -104,7 +104,7 @@ use rustc::hir::map::DefPathData;
|
|||
use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
|
||||
use rustc::middle::exported_symbols::SymbolExportLevel;
|
||||
use rustc::ty::{self, TyCtxt, InstanceDef};
|
||||
use rustc::ty::item_path::characteristic_def_id_of_type;
|
||||
use rustc::ty::print::characteristic_def_id_of_type;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet};
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc::mir::visit::{
|
|||
};
|
||||
use rustc::mir::Local;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{item_path, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use rustc_data_structures::work_queue::WorkQueue;
|
||||
|
@ -265,7 +265,7 @@ pub fn dump_mir<'a, 'tcx>(
|
|||
if !dump_enabled(tcx, pass_name, source) {
|
||||
return;
|
||||
}
|
||||
let node_path = item_path::with_forced_impl_filename_line(|| {
|
||||
let node_path = ty::print::with_forced_impl_filename_line(|| {
|
||||
// see notes on #41697 below
|
||||
tcx.def_path_str(source.def_id())
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
|||
use rustc::mir::*;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::item_path;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use std::fmt::Display;
|
||||
|
@ -78,7 +77,7 @@ pub fn dump_mir<'a, 'gcx, 'tcx, F>(
|
|||
return;
|
||||
}
|
||||
|
||||
let node_path = item_path::with_forced_impl_filename_line(|| {
|
||||
let node_path = ty::print::with_forced_impl_filename_line(|| {
|
||||
// see notes on #41697 below
|
||||
tcx.def_path_str(source.def_id())
|
||||
});
|
||||
|
@ -103,7 +102,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(
|
|||
None => return false,
|
||||
Some(ref filters) => filters,
|
||||
};
|
||||
let node_path = item_path::with_forced_impl_filename_line(|| {
|
||||
let node_path = ty::print::with_forced_impl_filename_line(|| {
|
||||
// see notes on #41697 below
|
||||
tcx.def_path_str(source.def_id())
|
||||
});
|
||||
|
@ -612,7 +611,7 @@ fn write_mir_sig(
|
|||
_ => bug!("Unexpected def description {:?}", descr),
|
||||
}
|
||||
|
||||
item_path::with_forced_impl_filename_line(|| {
|
||||
ty::print::with_forced_impl_filename_line(|| {
|
||||
// see notes on #41697 elsewhere
|
||||
write!(w, " {}", tcx.def_path_str(src.def_id()))
|
||||
})?;
|
||||
|
|
|
@ -15,7 +15,7 @@ use rustc::hir::print;
|
|||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::traits::Obligation;
|
||||
use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
|
||||
use rustc::ty::item_path::with_crate_prefix;
|
||||
use rustc::ty::print::with_crate_prefix;
|
||||
use syntax_pos::{Span, FileName};
|
||||
use syntax::ast;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
|
|
|
@ -4225,12 +4225,11 @@ pub fn path_to_def(tcx: &TyCtxt<'_, '_, '_>, path: &[&str]) -> Option<DefId> {
|
|||
|
||||
pub fn get_path_for_type<F>(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, def_ctor: F) -> hir::Path
|
||||
where F: Fn(DefId) -> Def {
|
||||
use rustc::ty::item_path::ItemPathPrinter;
|
||||
use rustc::ty::print::PrintCx;
|
||||
use rustc::ty::print::{PrintCx, Printer};
|
||||
|
||||
struct AbsolutePathPrinter;
|
||||
|
||||
impl ItemPathPrinter for AbsolutePathPrinter {
|
||||
impl Printer for AbsolutePathPrinter {
|
||||
type Path = Vec<String>;
|
||||
|
||||
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue