Skip to content

Commit

Permalink
Add wrapper to allow customising ty::TraitRef's printing behaviour.
Browse files Browse the repository at this point in the history
Add a wrapper newtype called `TraitRefPrintOnlyTraitPath` which
overrides the printing behaviour of `ty::TraitRef` to be the simple
format `Trait<U>`.

Printing of `ty::TraitRef` for `Debug` and `Display` is now the more
verbose `<T as Trait<U>>`.

This fixes rust-lang#59188.
  • Loading branch information
nathankleyn committed Apr 25, 2019
1 parent 112f7e9 commit f5ec9d8
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 19 deletions.
16 changes: 14 additions & 2 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
match *values {
infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(ref exp_found) => {
let pretty_exp_found = ty::error::ExpectedFound {
expected: exp_found.expected.print_only_trait_path(),
found: exp_found.found.print_only_trait_path()
};
self.expected_found_str(&pretty_exp_found)
},
infer::PolyTraitRefs(ref exp_found) => {
let pretty_exp_found = ty::error::ExpectedFound {
expected: exp_found.expected.print_only_trait_path(),
found: exp_found.found.print_only_trait_path()
};
self.expected_found_str(&pretty_exp_found)
},
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
value: trait_ref,
};

let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref.print_only_trait_path());
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
err.note(&{
Expand Down Expand Up @@ -427,7 +427,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
note
});

let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref.print_only_trait_path());
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
err.note(&{
let passive_voice = match actual_has_vid {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
// This shouldn't ever be needed, but just in case:
path.push(match trait_ref {
Some(trait_ref) => {
Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str()
Symbol::intern(&format!("<impl {} for {}>", trait_ref.print_only_trait_path(), self_ty)).as_str()
},
None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
});
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let is_try = self.tcx.sess.source_map().span_to_snippet(span)
.map(|s| &s == "?")
.unwrap_or(false);
let is_from = format!("{}", trait_ref).starts_with("std::convert::From<");
let is_from = format!("{}", trait_ref.print_only_trait_path())
.starts_with("std::convert::From<");
let message = if is_try && is_from {
Some(format!(
"`?` couldn't convert the error to `{}`",
Expand All @@ -667,7 +668,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
format!("{}the trait `{}` is not implemented for `{}`",
pre_message,
trait_ref,
trait_ref.print_only_trait_path(),
trait_ref.self_ty())
};

Expand Down Expand Up @@ -1630,7 +1631,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
err.note(
&format!("required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref,
parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty()));
let parent_predicate = parent_trait_ref.to_predicate();
self.note_obligation_cause_code(err,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option<
use std::fmt::Write;

let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) {
tr
tr.print_only_trait_path()
} else {
return None;
};
Expand Down
63 changes: 57 additions & 6 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:

p!(print(self_ty));
if let Some(trait_ref) = trait_ref {
p!(write(" as "), print(trait_ref));
p!(write(" as "), print(trait_ref.print_only_trait_path()));
}
Ok(cx)
})
Expand All @@ -425,7 +425,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:

p!(write("impl "));
if let Some(trait_ref) = trait_ref {
p!(print(trait_ref), write(" for "));
p!(print(trait_ref.print_only_trait_path()), write(" for "));
}
p!(print(self_ty));

Expand Down Expand Up @@ -559,7 +559,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:

p!(
write("{}", if first { " " } else { "+" }),
print(trait_ref));
print(trait_ref.print_only_trait_path()));
first = false;
}
}
Expand Down Expand Up @@ -1395,6 +1395,52 @@ impl<'gcx: 'tcx, 'tcx, T, U, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P>
}
}

/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait path. That is, it will print `Trait<U>` instead of
/// `<T as Trait<U>>`.
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);

impl TraitRefPrintOnlyTraitPath<'tcx> {
pub fn self_ty(&self) -> ty::Ty<'tcx> {
self.0.self_ty()
}
}

impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}

impl<'a, 'tcx> ty::Lift<'tcx> for TraitRefPrintOnlyTraitPath<'a> {
type Lifted = TraitRefPrintOnlyTraitPath<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.0.substs).map(|substs| TraitRefPrintOnlyTraitPath(ty::TraitRef {
def_id: self.0.def_id,
substs,
}))
}
}

TupleStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for TraitRefPrintOnlyTraitPath<'tcx> {
a
}
}

impl ty::TraitRef<'tcx> {
pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
TraitRefPrintOnlyTraitPath(self)
}
}

impl ty::PolyTraitRef<'tcx> {
pub fn print_only_trait_path(self) -> ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>> {
self.map_bound(|x| TraitRefPrintOnlyTraitPath(x))
}
}

macro_rules! forward_display_to_print {
($($ty:ty),+) => {
$(impl fmt::Display for $ty {
Expand Down Expand Up @@ -1447,6 +1493,7 @@ forward_display_to_print! {
// because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
ty::Binder<ty::TraitRef<'tcx>>,
ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>>,
ty::Binder<ty::FnSig<'tcx>>,
ty::Binder<ty::TraitPredicate<'tcx>>,
ty::Binder<ty::SubtypePredicate<'tcx>>,
Expand Down Expand Up @@ -1482,7 +1529,7 @@ define_print_and_forward_display! {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = cx.tcx().mk_infer(ty::FreshTy(0));
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
p!(print(trait_ref))
p!(print(trait_ref.print_only_trait_path()))
}

ty::ExistentialProjection<'tcx> {
Expand Down Expand Up @@ -1528,7 +1575,11 @@ define_print_and_forward_display! {
}

ty::TraitRef<'tcx> {
p!(print_def_path(self.def_id, self.substs));
p!(write("<{} as {}>", self.self_ty(), self))
}

TraitRefPrintOnlyTraitPath<'tcx> {
p!(print_def_path(self.0.def_id, self.0.substs));
}

&'tcx ty::Const<'tcx> {
Expand All @@ -1553,7 +1604,7 @@ define_print_and_forward_display! {
}

ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref.print_only_trait_path()))
}

ty::ProjectionPredicate<'tcx> {
Expand Down
5 changes: 1 addition & 4 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,7 @@ impl fmt::Debug for ty::FloatVarValue {

impl fmt::Debug for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// FIXME(#59188) this is used across the compiler to print
// a `TraitRef` qualified (with the Self type explicit),
// instead of having a different way to make that choice.
write!(f, "<{} as {}>", self.self_ty(), self)
fmt::Display::fmt(self, f)
}
}

Expand Down

0 comments on commit f5ec9d8

Please sign in to comment.