diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 9150417a85d..b6677326227 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -135,7 +135,6 @@ pub mod ty; pub mod util { pub mod captures; pub mod common; - mod ppaux; pub mod nodemap; pub mod profiling; pub mod bug; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index d1632e1e9bb..85786818a53 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -13,11 +13,8 @@ use std::ops::Deref; mod pretty; pub use self::pretty::*; -// FIXME(eddyb) this module uses `pub(crate)` for things used only -// from `ppaux` - when that is removed, they can be re-privatized. - #[derive(Default)] -pub(crate) struct PrintConfig { +struct PrintConfig { used_region_names: Option>, region_index: usize, binder_depth: usize, @@ -26,7 +23,7 @@ pub(crate) struct PrintConfig { pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub printer: P, - pub(crate) config: &'a mut PrintConfig, + config: &'a mut PrintConfig, } // HACK(eddyb) this is solely for `self: PrintCx`, e.g. to @@ -51,7 +48,7 @@ impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { }) } - pub(crate) fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { + pub fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7488b074471..f1ab58bc2e2 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -9,6 +9,7 @@ use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::mir::interpret::ConstValue; use syntax::symbol::{keywords, Symbol}; +use rustc_target::spec::abi::Abi; use syntax::symbol::InternedString; use std::cell::Cell; @@ -1357,3 +1358,302 @@ impl Print<'tcx, P> for ty::Binder cx.in_binder(self) } } + +pub trait LiftAndPrintToFmt<'tcx> { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result; +} + +impl LiftAndPrintToFmt<'tcx> for T + where T: ty::Lift<'tcx>, + for<'a, 'b> >::Lifted: + Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> +{ + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; + Ok(()) + }) + } +} + +// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. +impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + self.print(cx)?; + Ok(()) + }) + } +} + +macro_rules! forward_display_to_print { + (<$($T:ident),*> $ty:ty) => { + impl<$($T),*> fmt::Display for $ty + where Self: for<'a> LiftAndPrintToFmt<'a> + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) + } + } + }; + + ($ty:ty) => { + forward_display_to_print!(<> $ty); + }; +} + +macro_rules! define_print_and_forward_display { + (($self:ident, $cx:ident): <$($T:ident),*> $ty:ty $print:block) => { + impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $ty + where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* + { + type Output = P; + type Error = fmt::Error; + fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + #[allow(unused_mut)] + let mut $cx = $cx; + define_scoped_cx!($cx); + let _: () = $print; + #[allow(unreachable_code)] + Ok($cx.printer) + } + } + + forward_display_to_print!(<$($T),*> $ty); + }; + + (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { + $(define_print_and_forward_display!(($self, $cx): <> $ty $print);)+ + }; +} + +forward_display_to_print!(ty::RegionKind); +forward_display_to_print!(Ty<'tcx>); +forward_display_to_print!( ty::Binder); + +define_print_and_forward_display! { + (self, cx): + + ty::OutlivesPredicate { + p!(print(self.0), write(" : "), print(self.1)) + } +} + +define_print_and_forward_display! { + (self, cx): + + &'tcx ty::List> { + // Generate the main trait ref, including associated types. + let mut first = true; + + if let Some(principal) = self.principal() { + let mut resugared_principal = false; + + // Special-case `Fn(...) -> ...` and resugar it. + let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); + if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { + if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { + let mut projections = self.projection_bounds(); + if let (Some(proj), None) = (projections.next(), projections.next()) { + nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); + nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); + resugared_principal = true; + } + } + } + + if !resugared_principal { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(cx.tcx, dummy_self); + nest!(|cx| cx.print_def_path( + principal.def_id, + Some(principal.substs), + self.projection_bounds(), + )); + } + first = false; + } + + // Builtin bounds. + // FIXME(eddyb) avoid printing twice (needed to ensure + // that the auto traits are sorted *and* printed via cx). + let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { + (cx.tcx.def_path_str(did), did) + }).collect(); + + // The auto traits come ordered by `DefPathHash`. While + // `DefPathHash` is *stable* in the sense that it depends on + // neither the host nor the phase of the moon, it depends + // "pseudorandomly" on the compiler version and the target. + // + // To avoid that causing instabilities in compiletest + // output, sort the auto-traits alphabetically. + auto_traits.sort(); + + for (_, def_id) in auto_traits { + if !first { + p!(write(" + ")); + } + first = false; + + nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); + } + } + + &'tcx ty::List> { + p!(write("{{")); + let mut tys = self.iter(); + if let Some(&ty) = tys.next() { + p!(print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); + } + } + p!(write("}}")) + } + + ty::TypeAndMut<'tcx> { + p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), + print(self.ty)) + } + + ty::ExistentialTraitRef<'tcx> { + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + + let trait_ref = *ty::Binder::bind(*self) + .with_self_ty(cx.tcx, dummy_self) + .skip_binder(); + p!(print(trait_ref)) + } + + ty::FnSig<'tcx> { + if self.unsafety == hir::Unsafety::Unsafe { + p!(write("unsafe ")); + } + + if self.abi != Abi::Rust { + p!(write("extern {} ", self.abi)); + } + + p!(write("fn")); + nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); + } + + ty::InferTy { + if cx.tcx.sess.verbose() { + p!(write("{:?}", self)); + return Ok(cx.printer); + } + match *self { + ty::TyVar(_) => p!(write("_")), + ty::IntVar(_) => p!(write("{}", "{integer}")), + ty::FloatVar(_) => p!(write("{}", "{float}")), + ty::FreshTy(v) => p!(write("FreshTy({})", v)), + ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), + ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) + } + } + + ty::TraitRef<'tcx> { + nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); + } + + ConstValue<'tcx> { + match self { + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)), + _ => p!(write("{:?}", self)), + } + } + + ty::Const<'tcx> { + p!(write("{} : {}", self.val, self.ty)) + } + + ty::LazyConst<'tcx> { + match self { + // FIXME(const_generics) this should print at least the type. + ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), + ty::LazyConst::Evaluated(c) => p!(write("{}", c)), + } + } + + ty::ParamTy { + p!(write("{}", self.name)) + } + + ty::ParamConst { + p!(write("{}", self.name)) + } + + ty::SubtypePredicate<'tcx> { + p!(print(self.a), write(" <: "), print(self.b)) + } + + ty::TraitPredicate<'tcx> { + p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + } + + ty::ProjectionPredicate<'tcx> { + p!(print(self.projection_ty), write(" == "), print(self.ty)) + } + + ty::ProjectionTy<'tcx> { + nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); + } + + ty::ClosureKind { + match *self { + ty::ClosureKind::Fn => p!(write("Fn")), + ty::ClosureKind::FnMut => p!(write("FnMut")), + ty::ClosureKind::FnOnce => p!(write("FnOnce")), + } + } + + ty::Predicate<'tcx> { + match *self { + ty::Predicate::Trait(ref data) => p!(print(data)), + ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), + ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::Projection(ref predicate) => p!(print(predicate)), + ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), + ty::Predicate::ObjectSafe(trait_def_id) => { + p!(write("the trait `")); + nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); + p!(write("` is object-safe")) + } + ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { + p!(write("the closure `")); + nest!(|cx| cx.print_value_path(closure_def_id, None)); + p!(write("` implements the trait `{}`", kind)) + } + ty::Predicate::ConstEvaluatable(def_id, substs) => { + p!(write("the constant `")); + nest!(|cx| cx.print_value_path(def_id, Some(substs))); + p!(write("` can be evaluated")) + } + } + } + + Kind<'tcx> { + match self.unpack() { + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), + UnpackedKind::Const(ct) => p!(print(ct)), + } + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs deleted file mode 100644 index f8d0c8f661c..00000000000 --- a/src/librustc/util/ppaux.rs +++ /dev/null @@ -1,418 +0,0 @@ -use crate::hir; -use crate::hir::def::Namespace; -use crate::ty::subst::{Kind, UnpackedKind}; -use crate::ty::{self, ParamConst, Ty, TyCtxt}; -use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; -use crate::mir::interpret::ConstValue; - -use std::fmt; -use std::iter; - -use rustc_target::spec::abi::Abi; - -pub trait LiftAndPrintToFmt<'tcx> { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result; -} - -impl LiftAndPrintToFmt<'tcx> for T - where T: ty::Lift<'tcx>, - for<'a, 'b> >::Lifted: - Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> -{ - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; - Ok(()) - }) - } -} - -// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. -impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - self.print(cx)?; - Ok(()) - }) - } -} - -macro_rules! define_print { - (<$($T:ident),*> $target:ty) => { - impl<$($T),*> fmt::Display for $target - where Self: for<'a> LiftAndPrintToFmt<'a> - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) - } - } - }; - - (<$($T:ident),*> $target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { - impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $target - where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* - { - type Output = P; - type Error = fmt::Error; - fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { - #[allow(unused_mut)] - let mut $cx = $cx; - define_scoped_cx!($cx); - let _: () = $disp; - #[allow(unreachable_code)] - Ok($cx.printer) - } - } - - define_print!(<$($T),*> $target); - }; - - ($target:ty) => { - define_print!(<> $target); - }; - - ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { - define_print!(<> $target, ($self, $cx) { display $disp }); - }; -} - -macro_rules! nest { - ($closure:expr) => { - scoped_cx!() = scoped_cx!().nest($closure)? - } -} -macro_rules! print_inner { - (write ($($data:expr),+)) => { - write!(scoped_cx!().printer, $($data),+)? - }; - ($kind:ident ($data:expr)) => { - nest!(|cx| $data.$kind(cx)) - }; -} -macro_rules! p { - ($($kind:ident $data:tt),+) => { - { - $(print_inner!($kind $data));+ - } - }; -} -macro_rules! define_scoped_cx { - ($cx:ident) => { - #[allow(unused_macros)] - macro_rules! scoped_cx { - () => ($cx) - } - }; -} - -define_print! { - &'tcx ty::List>, (self, cx) { - display { - // Generate the main trait ref, including associated types. - let mut first = true; - - if let Some(principal) = self.principal() { - let mut resugared_principal = false; - - // Special-case `Fn(...) -> ...` and resugar it. - let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); - if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { - let mut projections = self.projection_bounds(); - if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); - nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); - resugared_principal = true; - } - } - } - - if !resugared_principal { - // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let principal = principal.with_self_ty(cx.tcx, dummy_self); - nest!(|cx| cx.print_def_path( - principal.def_id, - Some(principal.substs), - self.projection_bounds(), - )); - } - first = false; - } - - // Builtin bounds. - // FIXME(eddyb) avoid printing twice (needed to ensure - // that the auto traits are sorted *and* printed via cx). - let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - (cx.tcx.def_path_str(did), did) - }).collect(); - - // The auto traits come ordered by `DefPathHash`. While - // `DefPathHash` is *stable* in the sense that it depends on - // neither the host nor the phase of the moon, it depends - // "pseudorandomly" on the compiler version and the target. - // - // To avoid that causing instabilities in compiletest - // output, sort the auto-traits alphabetically. - auto_traits.sort(); - - for (_, def_id) in auto_traits { - if !first { - p!(write(" + ")); - } - first = false; - - nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); - } - } - } -} - -define_print! { - &'tcx ty::List>, (self, cx) { - display { - p!(write("{{")); - let mut tys = self.iter(); - if let Some(&ty) = tys.next() { - p!(print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } - } - p!(write("}}")) - } - } -} - -define_print! { - ty::TypeAndMut<'tcx>, (self, cx) { - display { - p!( - write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), - print(self.ty)) - } - } -} - -define_print! { - ty::ExistentialTraitRef<'tcx>, (self, cx) { - display { - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - - let trait_ref = *ty::Binder::bind(*self) - .with_self_ty(cx.tcx, dummy_self) - .skip_binder(); - p!(print(trait_ref)) - } - } -} - -define_print! { - ty::RegionKind -} - -define_print! { - ty::FnSig<'tcx>, (self, cx) { - display { - if self.unsafety == hir::Unsafety::Unsafe { - p!(write("unsafe ")); - } - - if self.abi != Abi::Rust { - p!(write("extern {} ", self.abi)); - } - - p!(write("fn")); - nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); - } - } -} - -define_print! { - ty::InferTy, (self, cx) { - display { - if cx.tcx.sess.verbose() { - p!(write("{:?}", self)); - return Ok(cx.printer); - } - match *self { - ty::TyVar(_) => p!(write("_")), - ty::IntVar(_) => p!(write("{}", "{integer}")), - ty::FloatVar(_) => p!(write("{}", "{float}")), - ty::FreshTy(v) => p!(write("FreshTy({})", v)), - ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), - ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) - } - } - } -} - -define_print! { - ty::Binder -} - -define_print! { - ty::TraitRef<'tcx>, (self, cx) { - display { - nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); - } - } -} - -define_print! { - Ty<'tcx> -} - -define_print! { - ConstValue<'tcx>, (self, cx) { - display { - match self { - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)), - _ => p!(write("{:?}", self)), - } - } - } -} - -define_print! { - ty::Const<'tcx>, (self, cx) { - display { - p!(write("{} : {}", self.val, self.ty)) - } - } -} - -define_print! { - ty::LazyConst<'tcx>, (self, cx) { - display { - match self { - // FIXME(const_generics) this should print at least the type. - ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), - ty::LazyConst::Evaluated(c) => p!(write("{}", c)), - } - } - } -} - -define_print! { - ty::ParamTy, (self, cx) { - display { - p!(write("{}", self.name)) - } - } -} - -define_print! { - ty::ParamConst, (self, cx) { - display { - p!(write("{}", self.name)) - } - } -} - -define_print! { - ty::OutlivesPredicate, (self, cx) { - display { - p!(print(self.0), write(" : "), print(self.1)) - } - } -} - -define_print! { - ty::SubtypePredicate<'tcx>, (self, cx) { - display { - p!(print(self.a), write(" <: "), print(self.b)) - } - } -} - -define_print! { - ty::TraitPredicate<'tcx>, (self, cx) { - display { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) - } - } -} - -define_print! { - ty::ProjectionPredicate<'tcx>, (self, cx) { - display { - p!(print(self.projection_ty), write(" == "), print(self.ty)) - } - } -} - -define_print! { - ty::ProjectionTy<'tcx>, (self, cx) { - display { - nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); - } - } -} - -define_print! { - ty::ClosureKind, (self, cx) { - display { - match *self { - ty::ClosureKind::Fn => p!(write("Fn")), - ty::ClosureKind::FnMut => p!(write("FnMut")), - ty::ClosureKind::FnOnce => p!(write("FnOnce")), - } - } - } -} - -define_print! { - ty::Predicate<'tcx>, (self, cx) { - display { - match *self { - ty::Predicate::Trait(ref data) => p!(print(data)), - ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), - ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), - ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), - ty::Predicate::Projection(ref predicate) => p!(print(predicate)), - ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), - ty::Predicate::ObjectSafe(trait_def_id) => { - p!(write("the trait `")); - nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); - p!(write("` is object-safe")) - } - ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - p!(write("the closure `")); - nest!(|cx| cx.print_value_path(closure_def_id, None)); - p!(write("` implements the trait `{}`", kind)) - } - ty::Predicate::ConstEvaluatable(def_id, substs) => { - p!(write("the constant `")); - nest!(|cx| cx.print_value_path(def_id, Some(substs))); - p!(write("` can be evaluated")) - } - } - } - } -} - -define_print! { - Kind<'tcx>, (self, cx) { - display { - match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(print(lt)), - UnpackedKind::Type(ty) => p!(print(ty)), - UnpackedKind::Const(ct) => p!(print(ct)), - } - } - } -}