about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-12-19 13:25:31 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-03-15 13:25:10 +0200
commit9f8aaa04e02c74209e3ea355d8888cbc59a8fb64 (patch)
tree3be028f8146429f1d5772abf9fee70e873bf62e0 /src
parente0c75ff40def45bbf39bfed5766a1a8a56f2409f (diff)
downloadrust-9f8aaa04e02c74209e3ea355d8888cbc59a8fb64.tar.gz
rust-9f8aaa04e02c74209e3ea355d8888cbc59a8fb64.zip
rustc: move the contents of ty::item_path to ty::print.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/item_path.rs560
-rw-r--r--src/librustc/ty/mod.rs1
-rw-r--r--src/librustc/ty/print.rs560
-rw-r--r--src/librustc/ty/query/plumbing.rs5
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs7
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs2
-rw-r--r--src/librustc_mir/util/liveness.rs4
-rw-r--r--src/librustc_mir/util/pretty.rs7
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustdoc/clean/mod.rs5
10 files changed, 573 insertions, 580 deletions
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
deleted file mode 100644
index 9f34f475eff..00000000000
--- a/src/librustc/ty/item_path.rs
+++ /dev/null
@@ -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
-    }
-}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4f933bf0d53..882e2dc62b1 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -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;
diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs
index a1d93bc4140..053a7531cad 100644
--- a/src/librustc/ty/print.rs
+++ b/src/librustc/ty/print.rs
@@ -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
+    }
+}
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index e3276ba0bea..cff99f23d0e 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -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,
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 1417cbf1265..b417091704d 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -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 {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index c0e2186d9f3..4a2c05b2013 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -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};
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 200089530c1..cbdd50cf405 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -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())
     });
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 12d4e90c7c0..a76d26a6831 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -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()))
     })?;
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index f784a720b19..b4a1a2d76c2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -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;
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 08d165b82b1..6cf8a9896d5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -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 {