use crate::middle::cstore::{ExternCrate, ExternCrateSource};
use crate::mir::interpret::{AllocId, ConstValue, GlobalAlloc, Pointer, Scalar};
-use crate::ty::layout::IntegerExt;
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
-use crate::ty::{self, ConstInt, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::ieee::{Double, Single};
-use rustc_apfloat::Float;
use rustc_ast as ast;
-use rustc_attr::{SignedInt, UnsignedInt};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
use rustc_hir::ItemKind;
use rustc_session::config::TrimmedDefPaths;
use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_target::abi::{Integer, Size};
+use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
use std::cell::Cell;
use std::char;
use std::collections::BTreeMap;
+use std::convert::TryFrom;
use std::fmt::{self, Write as _};
-use std::ops::{Deref, DerefMut};
+use std::ops::{ControlFlow, Deref, DerefMut};
// `pretty` is a separate module only for organization.
use super::*;
macro_rules! p {
+ (@$lit:literal) => {
+ write!(scoped_cx!(), $lit)?
+ };
(@write($($data:expr),+)) => {
write!(scoped_cx!(), $($data),+)?
};
(@$method:ident($($arg:expr),*)) => {
scoped_cx!() = scoped_cx!().$method($($arg),*)?
};
- ($($kind:ident $data:tt),+) => {{
- $(p!(@$kind $data);)+
+ ($($elem:tt $(($($args:tt)*))?),+) => {{
+ $(p!(@ $elem $(($($args)*))?);)+
}};
}
macro_rules! define_scoped_cx {
/// Avoids running any queries during any prints that occur
/// during the closure. This may alter the appearance of some
/// types (e.g. forcing verbose printing for opaque types).
-/// This method is used during some queries (e.g. `predicates_of`
+/// This method is used during some queries (e.g. `explicit_item_bounds`
/// for opaque types), to ensure that any debug printing that
/// occurs during the query computation does not end up recursively
/// calling the same query.
p!(print(self_ty));
if let Some(trait_ref) = trait_ref {
- p!(write(" as "), print(trait_ref.print_only_trait_path()));
+ p!(" as ", print(trait_ref.print_only_trait_path()));
}
Ok(cx)
})
self.generic_delimiters(|mut cx| {
define_scoped_cx!(cx);
- p!(write("impl "));
+ p!("impl ");
if let Some(trait_ref) = trait_ref {
- p!(print(trait_ref.print_only_trait_path()), write(" for "));
+ p!(print(trait_ref.print_only_trait_path()), " for ");
}
p!(print(self_ty));
define_scoped_cx!(self);
match *ty.kind() {
- ty::Bool => p!(write("bool")),
- ty::Char => p!(write("char")),
+ ty::Bool => p!("bool"),
+ ty::Char => p!("char"),
ty::Int(t) => p!(write("{}", t.name_str())),
ty::Uint(t) => p!(write("{}", t.name_str())),
ty::Float(t) => p!(write("{}", t.name_str())),
p!(print(tm.ty))
}
ty::Ref(r, ty, mutbl) => {
- p!(write("&"));
+ p!("&");
if self.region_should_not_be_omitted(r) {
- p!(print(r), write(" "));
+ p!(print(r), " ");
}
p!(print(ty::TypeAndMut { ty, mutbl }))
}
- ty::Never => p!(write("!")),
+ ty::Never => p!("!"),
ty::Tuple(ref tys) => {
- p!(write("("), comma_sep(tys.iter()));
+ p!("(", comma_sep(tys.iter()));
if tys.len() == 1 {
- p!(write(","));
+ p!(",");
}
- p!(write(")"))
+ p!(")")
}
ty::FnDef(def_id, substs) => {
let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
- p!(print(sig), write(" {{"), print_value_path(def_id, substs), write("}}"));
+ p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
p!(write("{}", infer_ty))
}
}
- ty::Error(_) => p!(write("[type error]")),
+ ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(write("{}", param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
ty::Dynamic(data, r) => {
let print_r = self.region_should_not_be_omitted(r);
if print_r {
- p!(write("("));
+ p!("(");
}
- p!(write("dyn "), print(data));
+ p!("dyn ", print(data));
if print_r {
- p!(write(" + "), print(r), write(")"));
+ p!(" + ", print(r), ")");
}
}
ty::Foreign(def_id) => {
p!(write("{}", name));
// FIXME(eddyb) print this with `print_def_path`.
if !substs.is_empty() {
- p!(write("::"));
+ p!("::");
p!(generic_delimiters(|cx| cx.comma_sep(substs.iter())));
}
return Ok(self);
}
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
- let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+ let bounds = self.tcx().explicit_item_bounds(def_id);
let mut first = true;
let mut is_sized = false;
- p!(write("impl"));
- for predicate in bounds.predicates {
+ p!("impl");
+ for (predicate, _) in bounds {
+ let predicate = predicate.subst(self.tcx(), substs);
// Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
// may contain unbound variables. We therefore do this manually.
//
// FIXME(lcnr): Find out why exactly this is the case :)
- if let ty::PredicateAtom::Trait(pred, _) =
- predicate.bound_atom(self.tcx()).skip_binder()
- {
- let trait_ref = ty::Binder::bind(pred.trait_ref);
+ let bound_predicate = predicate.bound_atom_with_opt_escaping(self.tcx());
+ if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+ let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
is_sized = true;
if !is_sized {
p!(write("{}?Sized", if first { " " } else { "+" }));
} else if first {
- p!(write(" Sized"));
+ p!(" Sized");
}
Ok(self)
})?);
}
- ty::Str => p!(write("str")),
+ ty::Str => p!("str"),
ty::Generator(did, substs, movability) => {
p!(write("["));
match movability {
hir::Movability::Movable => {}
- hir::Movability::Static => p!(write("static ")),
+ hir::Movability::Static => p!("static "),
}
if !self.tcx().sess.verbose() {
- p!(write("generator"));
+ p!("generator");
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
} else {
- p!(write("@{}", self.tcx().def_path_str(did)));
+ p!(write("@"), print_def_path(did, substs));
}
} else {
p!(print_def_path(did, substs));
- if substs.as_generator().is_valid() {
- // Search for the first inference variable
- p!(write(" upvar_tys=("));
- let mut uninferred_ty =
- substs.as_generator().upvar_tys().filter(|ty| ty.is_ty_infer());
- if uninferred_ty.next().is_some() {
- p!(write("unavailable"));
- } else {
- self = self.comma_sep(substs.as_generator().upvar_tys())?;
- }
- p!(write(")"));
+ p!(" upvar_tys=(");
+ if !substs.as_generator().is_valid() {
+ p!("unavailable");
+ } else {
+ self = self.comma_sep(substs.as_generator().upvar_tys())?;
}
+ p!(")");
}
if substs.as_generator().is_valid() {
- p!(write(" "), print(substs.as_generator().witness()));
+ p!(" ", print(substs.as_generator().witness()));
}
- p!(write("]"));
+ p!("]")
}
ty::GeneratorWitness(types) => {
p!(in_binder(&types));
if let Some(did) = did.as_local() {
let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
if self.tcx().sess.opts.debugging_opts.span_free_formats {
- p!(write("@"), print_def_path(did.to_def_id(), substs));
+ p!("@", print_def_path(did.to_def_id(), substs));
} else {
let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
}
} else {
- p!(write("@{}", self.tcx().def_path_str(did)));
+ p!(write("@"), print_def_path(did, substs));
}
} else {
p!(print_def_path(did, substs));
- if substs.as_closure().is_valid() {
- // Search for the first inference variable
- let mut uninferred_ty =
- substs.as_closure().upvar_tys().filter(|ty| ty.is_ty_infer());
- if uninferred_ty.next().is_some() {
- // If the upvar substs contain an inference variable we haven't
- // finished capture analysis.
- p!(write(" closure_substs=(unavailable)"));
- } else {
- p!(write(" closure_kind_ty="), print(substs.as_closure().kind_ty()));
- p!(
- write(" closure_sig_as_fn_ptr_ty="),
- print(substs.as_closure().sig_as_fn_ptr_ty())
- );
- p!(write(" upvar_tys=("));
- self = self.comma_sep(substs.as_closure().upvar_tys())?;
- p!(write(")"));
- }
+ if !substs.as_closure().is_valid() {
+ p!(" closure_substs=(unavailable)");
+ } else {
+ p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
+ p!(
+ " closure_sig_as_fn_ptr_ty=",
+ print(substs.as_closure().sig_as_fn_ptr_ty())
+ );
+ p!(" upvar_tys=(");
+ self = self.comma_sep(substs.as_closure().upvar_tys())?;
+ p!(")");
}
}
- p!(write("]"));
+ p!("]");
}
ty::Array(ty, sz) => {
- p!(write("["), print(ty), write("; "));
+ p!("[", print(ty), "; ");
if self.tcx().sess.verbose() {
p!(write("{:?}", sz));
} else if let ty::ConstKind::Unevaluated(..) = sz.val {
// Do not try to evaluate unevaluated constants. If we are const evaluating an
// array length anon const, rustc will (with debug assertions) print the
// constant's path. Which will end up here again.
- p!(write("_"));
+ p!("_");
} else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) {
p!(write("{}", n));
} else if let ty::ConstKind::Param(param) = sz.val {
p!(write("{}", param));
} else {
- p!(write("_"));
+ p!("_");
}
- p!(write("]"))
+ p!("]")
}
- ty::Slice(ty) => p!(write("["), print(ty), write("]")),
+ ty::Slice(ty) => p!("[", print(ty), "]"),
}
Ok(self)
for (_, def_id) in auto_traits {
if !first {
- p!(write(" + "));
+ p!(" + ");
}
first = false;
) -> Result<Self, Self::Error> {
define_scoped_cx!(self);
- p!(write("("), comma_sep(inputs.iter().copied()));
+ p!("(", comma_sep(inputs.iter().copied()));
if c_variadic {
if !inputs.is_empty() {
- p!(write(", "));
+ p!(", ");
}
- p!(write("..."));
+ p!("...");
}
- p!(write(")"));
+ p!(")");
if !output.is_unit() {
- p!(write(" -> "), print(output));
+ p!(" -> ", print(output));
}
Ok(self)
self.pretty_print_bound_var(debruijn, bound_var)?
}
ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
- ty::ConstKind::Error(_) => p!(write("[const error]")),
+ ty::ConstKind::Error(_) => p!("[const error]"),
};
Ok(self)
}
ty::Array(
ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. },
ty::Const {
- val:
- ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw {
- data,
- ..
- })),
+ val: ty::ConstKind::Value(ConstValue::Scalar(int)),
..
},
),
),
) => match self.tcx().get_global_alloc(ptr.alloc_id) {
Some(GlobalAlloc::Memory(alloc)) => {
- if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
- {
+ let bytes = int.assert_bits(self.tcx().data_layout.pointer_size);
+ let size = Size::from_bytes(bytes);
+ if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), ptr, size) {
p!(pretty_print_byte_str(byte_str))
} else {
- p!(write("<too short allocation>"))
+ p!("<too short allocation>")
}
}
// FIXME: for statics and functions, we could in principle print more detail.
Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
- Some(GlobalAlloc::Function(_)) => p!(write("<function>")),
- None => p!(write("<dangling pointer>")),
+ Some(GlobalAlloc::Function(_)) => p!("<function>"),
+ None => p!("<dangling pointer>"),
},
// Bool
- (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
- (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
+ (Scalar::Int(int), ty::Bool) if int == ScalarInt::FALSE => p!("false"),
+ (Scalar::Int(int), ty::Bool) if int == ScalarInt::TRUE => p!("true"),
// Float
- (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => {
- p!(write("{}f32", Single::from_bits(data)))
+ (Scalar::Int(int), ty::Float(ast::FloatTy::F32)) => {
+ p!(write("{}f32", Single::try_from(int).unwrap()))
}
- (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F64)) => {
- p!(write("{}f64", Double::from_bits(data)))
+ (Scalar::Int(int), ty::Float(ast::FloatTy::F64)) => {
+ p!(write("{}f64", Double::try_from(int).unwrap()))
}
// Int
- (Scalar::Raw { data, .. }, ty::Uint(ui)) => {
- let size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
- let int = ConstInt::new(data, size, false, ty.is_ptr_sized_integral());
- if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
- }
- (Scalar::Raw { data, .. }, ty::Int(i)) => {
- let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();
- let int = ConstInt::new(data, size, true, ty.is_ptr_sized_integral());
+ (Scalar::Int(int), ty::Uint(_) | ty::Int(_)) => {
+ let int =
+ ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
}
// Char
- (Scalar::Raw { data, .. }, ty::Char) if char::from_u32(data as u32).is_some() => {
- p!(write("{:?}", char::from_u32(data as u32).unwrap()))
+ (Scalar::Int(int), ty::Char) if char::try_from(int).is_ok() => {
+ p!(write("{:?}", char::try_from(int).unwrap()))
}
// Raw pointers
- (Scalar::Raw { data, .. }, ty::RawPtr(_)) => {
+ (Scalar::Int(int), ty::RawPtr(_)) => {
+ let data = int.assert_bits(self.tcx().data_layout.pointer_size);
self = self.typed_value(
|mut this| {
write!(this, "0x{:x}", data)?;
)?;
}
// For function type zsts just printing the path is enough
- (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)),
+ (Scalar::Int(int), ty::FnDef(d, s)) if int == ScalarInt::ZST => {
+ p!(print_value_path(*d, s))
+ }
// Nontrivial types with scalar bit representation
- (Scalar::Raw { data, size }, _) => {
+ (Scalar::Int(int), _) => {
let print = |mut this: Self| {
- if size == 0 {
+ if int.size() == Size::ZERO {
write!(this, "transmute(())")?;
} else {
- write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?;
+ write!(this, "transmute(0x{:x})", int)?;
}
Ok(this)
};
fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
- p!(write("b\""));
+ p!("b\"");
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
}
}
- p!(write("\""));
+ p!("\"");
Ok(self)
}
define_scoped_cx!(self);
if self.tcx().sess.verbose() {
- p!(write("ConstValue({:?}: ", ct), print(ty), write(")"));
+ p!(write("ConstValue({:?}: ", ct), print(ty), ")");
return Ok(self);
}
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
- let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
+ let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
p!(write("{:?}", s));
Ok(self)
}
let ptr = Pointer::new(AllocId(0), offset);
let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap();
- p!(write("*"));
+ p!("*");
p!(pretty_print_byte_str(byte_str));
Ok(self)
}
match *ty.kind() {
ty::Array(..) => {
- p!(write("["), comma_sep(fields), write("]"));
+ p!("[", comma_sep(fields), "]");
}
ty::Tuple(..) => {
- p!(write("("), comma_sep(fields));
+ p!("(", comma_sep(fields));
if contents.fields.len() == 1 {
- p!(write(","));
+ p!(",");
}
- p!(write(")"));
+ p!(")");
}
ty::Adt(def, substs) if def.variants.is_empty() => {
p!(print_value_path(def.did, substs));
match variant_def.ctor_kind {
CtorKind::Const => {}
CtorKind::Fn => {
- p!(write("("), comma_sep(fields), write(")"));
+ p!("(", comma_sep(fields), ")");
}
CtorKind::Fictive => {
- p!(write(" {{ "));
+ p!(" {{ ");
let mut first = true;
for (field_def, field) in variant_def.fields.iter().zip(fields) {
if !first {
- p!(write(", "));
+ p!(", ");
}
p!(write("{}: ", field_def.ident), print(field));
first = false;
}
- p!(write(" }}"));
+ p!(" }}");
}
}
}
// fallback
p!(write("{:?}", ct));
if print_ty {
- p!(write(": "), print(ty));
+ p!(": ", print(ty));
}
Ok(self)
}
if this.print_alloc_ids {
p!(write("{:?}", p));
} else {
- p!(write("&_"));
+ p!("&_");
}
Ok(this)
};
ty::ReVar(_) => {}
ty::ReErased => {}
ty::ReStatic => {
- p!(write("'static"));
+ p!("'static");
return Ok(self);
}
ty::ReEmpty(ty::UniverseIndex::ROOT) => {
- p!(write("'<empty>"));
+ p!("'<empty>");
return Ok(self);
}
ty::ReEmpty(ui) => {
}
}
- p!(write("'_"));
+ p!("'_");
Ok(self)
}
{
struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
- fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
if let ty::ReLateBound(_, ty::BrNamed(_, name)) = *r {
self.0.insert(name);
}
type Error = P::Error;
fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
define_scoped_cx!(cx);
- p!(print(self.0), write(": "), print(self.1));
+ p!(print(self.0), ": ", print(self.1));
Ok(cx)
}
}
$(impl fmt::Display for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
- tcx.lift(self)
+ tcx.lift(*self)
.expect("could not lift for printing")
.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?;
Ok(())
(self, cx):
&'tcx ty::List<Ty<'tcx>> {
- p!(write("{{"), comma_sep(self.iter()), write("}}"))
+ p!("{{", comma_sep(self.iter()), "}}")
}
ty::TypeAndMut<'tcx> {
p!(write("extern {} ", self.abi));
}
- p!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
+ p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
}
ty::InferTy {
return Ok(cx);
}
match *self {
- ty::TyVar(_) => p!(write("_")),
+ ty::TyVar(_) => p!("_"),
ty::IntVar(_) => p!(write("{}", "{integer}")),
ty::FloatVar(_) => p!(write("{}", "{float}")),
ty::FreshTy(v) => p!(write("FreshTy({})", v)),
}
ty::SubtypePredicate<'tcx> {
- p!(print(self.a), write(" <: "), print(self.b))
+ p!(print(self.a), " <: ", print(self.b))
}
ty::TraitPredicate<'tcx> {
- p!(print(self.trait_ref.self_ty()), write(": "),
+ p!(print(self.trait_ref.self_ty()), ": ",
print(self.trait_ref.print_only_trait_path()))
}
ty::ProjectionPredicate<'tcx> {
- p!(print(self.projection_ty), write(" == "), print(self.ty))
+ p!(print(self.projection_ty), " == ", print(self.ty))
}
ty::ProjectionTy<'tcx> {
ty::ClosureKind {
match *self {
- ty::ClosureKind::Fn => p!(write("Fn")),
- ty::ClosureKind::FnMut => p!(write("FnMut")),
- ty::ClosureKind::FnOnce => p!(write("FnOnce")),
+ ty::ClosureKind::Fn => p!("Fn"),
+ ty::ClosureKind::FnMut => p!("FnMut"),
+ ty::ClosureKind::FnOnce => p!("FnOnce"),
}
}
match *self {
ty::PredicateAtom::Trait(ref data, constness) => {
if let hir::Constness::Const = constness {
- p!(write("const "));
+ p!("const ");
}
p!(print(data))
}
ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
- ty::PredicateAtom::WellFormed(arg) => p!(print(arg), write(" well-formed")),
+ ty::PredicateAtom::WellFormed(arg) => p!(print(arg), " well-formed"),
ty::PredicateAtom::ObjectSafe(trait_def_id) => {
- p!(write("the trait `"),
- print_def_path(trait_def_id, &[]),
- write("` is object-safe"))
+ p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
- p!(write("the closure `"),
+ p!("the closure `",
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
ty::PredicateAtom::ConstEvaluatable(def, substs) => {
- p!(write("the constant `"),
- print_value_path(def.did, substs),
- write("` can be evaluated"))
+ p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
}
ty::PredicateAtom::ConstEquate(c1, c2) => {
- p!(write("the constant `"),
- print(c1),
- write("` equals `"),
- print(c2),
- write("`"))
+ p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
- p!(write("the type `"),
- print(ty),
- write("` is found in the environment"))
+ p!("the type `", print(ty), "` is found in the environment")
}
}
}