2 use crate::hir::def::Namespace;
3 use crate::ty::subst::{Kind, UnpackedKind};
4 use crate::ty::{self, ParamConst, Ty};
5 use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print};
6 use crate::mir::interpret::ConstValue;
11 use rustc_target::spec::abi::Abi;
13 macro_rules! define_print {
14 ([$($target:ty),+] $vars:tt $def:tt) => {
15 $(define_print!($target, $vars $def);)+
18 ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => {
19 impl<P: PrettyPrinter> Print<'tcx, P> for $target {
21 type Error = fmt::Error;
22 fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
25 define_scoped_cx!($cx);
27 #[allow(unreachable_code)]
32 impl fmt::Display for $target {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
35 cx.tcx.lift(self).expect("could not lift for printing").print(cx)?;
45 scoped_cx!() = scoped_cx!().nest($closure)?
48 macro_rules! print_inner {
49 (write ($($data:expr),+)) => {
50 write!(scoped_cx!().printer, $($data),+)?
52 ($kind:ident ($data:expr)) => {
53 nest!(|cx| $data.$kind(cx))
57 ($($kind:ident $data:tt),+) => {
59 $(print_inner!($kind $data));+
63 macro_rules! define_scoped_cx {
65 #[allow(unused_macros)]
66 macro_rules! scoped_cx {
73 &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
75 // Generate the main trait ref, including associated types.
78 if let Some(principal) = self.principal() {
79 let mut resugared_principal = false;
81 // Special-case `Fn(...) -> ...` and resugar it.
82 let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id);
83 if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() {
84 if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
85 let mut projections = self.projection_bounds();
86 if let (Some(proj), None) = (projections.next(), projections.next()) {
87 nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty()));
88 nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty));
89 resugared_principal = true;
94 if !resugared_principal {
95 // Use a type that can't appear in defaults of type parameters.
96 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
97 let principal = principal.with_self_ty(cx.tcx, dummy_self);
98 nest!(|cx| cx.print_def_path(
100 Some(principal.substs),
101 self.projection_bounds(),
108 // FIXME(eddyb) avoid printing twice (needed to ensure
109 // that the auto traits are sorted *and* printed via cx).
110 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
111 (cx.tcx.def_path_str(did), did)
114 // The auto traits come ordered by `DefPathHash`. While
115 // `DefPathHash` is *stable* in the sense that it depends on
116 // neither the host nor the phase of the moon, it depends
117 // "pseudorandomly" on the compiler version and the target.
119 // To avoid that causing instabilities in compiletest
120 // output, sort the auto-traits alphabetically.
123 for (_, def_id) in auto_traits {
129 nest!(|cx| cx.print_def_path(def_id, None, iter::empty()));
136 &'tcx ty::List<Ty<'tcx>>, (self, cx) {
139 let mut tys = self.iter();
140 if let Some(&ty) = tys.next() {
143 p!(write(", "), print(ty));
152 ty::TypeAndMut<'tcx>, (self, cx) {
155 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
162 ty::ExistentialTraitRef<'tcx>, (self, cx) {
164 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
166 let trait_ref = *ty::Binder::bind(*self)
167 .with_self_ty(cx.tcx, dummy_self)
175 ty::RegionKind, (self, cx) {
177 return cx.print_region(self);
183 ty::FnSig<'tcx>, (self, cx) {
185 if self.unsafety == hir::Unsafety::Unsafe {
186 p!(write("unsafe "));
189 if self.abi != Abi::Rust {
190 p!(write("extern {} ", self.abi));
194 nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
200 ty::InferTy, (self, cx) {
202 if cx.tcx.sess.verbose() {
203 p!(write("{:?}", self));
204 return Ok(cx.printer);
207 ty::TyVar(_) => p!(write("_")),
208 ty::IntVar(_) => p!(write("{}", "{integer}")),
209 ty::FloatVar(_) => p!(write("{}", "{float}")),
210 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
211 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
212 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
218 // The generic impl doesn't work yet because projections are not
219 // normalized under HRTB.
220 /*impl<T> fmt::Display for ty::Binder<T>
221 where T: fmt::Display + for<'a> ty::Lift<'a>,
222 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 PrintCx::with_tls_tcx(|cx| cx.pretty_in_binder(cx.tcx.lift(self)
226 .expect("could not lift for printing")))
232 ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
233 ty::Binder<ty::TraitRef<'tcx>>,
234 ty::Binder<ty::FnSig<'tcx>>,
235 ty::Binder<ty::TraitPredicate<'tcx>>,
236 ty::Binder<ty::SubtypePredicate<'tcx>>,
237 ty::Binder<ty::ProjectionPredicate<'tcx>>,
238 ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
239 ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
243 nest!(|cx| cx.pretty_in_binder(self))
249 ty::TraitRef<'tcx>, (self, cx) {
251 nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty()));
257 Ty<'tcx>, (self, cx) {
259 return cx.print_type(self);
265 ConstValue<'tcx>, (self, cx) {
268 ConstValue::Infer(..) => p!(write("_")),
269 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
270 _ => p!(write("{:?}", self)),
277 ty::Const<'tcx>, (self, cx) {
279 p!(write("{} : {}", self.val, self.ty))
285 ty::LazyConst<'tcx>, (self, cx) {
288 // FIXME(const_generics) this should print at least the type.
289 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
290 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
297 ty::ParamTy, (self, cx) {
299 p!(write("{}", self.name))
305 ty::ParamConst, (self, cx) {
307 p!(write("{}", self.name))
312 // Similar problem to `Binder<T>`, can't define a generic impl.
315 ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
316 ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
320 p!(print(self.0), write(" : "), print(self.1))
326 ty::SubtypePredicate<'tcx>, (self, cx) {
328 p!(print(self.a), write(" <: "), print(self.b))
334 ty::TraitPredicate<'tcx>, (self, cx) {
336 p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
342 ty::ProjectionPredicate<'tcx>, (self, cx) {
344 p!(print(self.projection_ty), write(" == "), print(self.ty))
350 ty::ProjectionTy<'tcx>, (self, cx) {
352 nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty()));
358 ty::ClosureKind, (self, cx) {
361 ty::ClosureKind::Fn => p!(write("Fn")),
362 ty::ClosureKind::FnMut => p!(write("FnMut")),
363 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
370 ty::Predicate<'tcx>, (self, cx) {
373 ty::Predicate::Trait(ref data) => p!(print(data)),
374 ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
375 ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
376 ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
377 ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
378 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
379 ty::Predicate::ObjectSafe(trait_def_id) => {
380 p!(write("the trait `"));
381 nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty()));
382 p!(write("` is object-safe"))
384 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
385 p!(write("the closure `"));
386 nest!(|cx| cx.print_value_path(closure_def_id, None));
387 p!(write("` implements the trait `{}`", kind))
389 ty::Predicate::ConstEvaluatable(def_id, substs) => {
390 p!(write("the constant `"));
391 nest!(|cx| cx.print_value_path(def_id, Some(substs)));
392 p!(write("` can be evaluated"))
400 Kind<'tcx>, (self, cx) {
402 match self.unpack() {
403 UnpackedKind::Lifetime(lt) => p!(print(lt)),
404 UnpackedKind::Type(ty) => p!(print(ty)),
405 UnpackedKind::Const(ct) => p!(print(ct)),