allow customising ty::TraitRef's printing behavior

fix clippy

allow customising ty::TraitRef's printing behavior

fix clippy

stylistic fix
This commit is contained in:
Mikhail Babenko 2019-11-21 21:01:14 +03:00
parent fe969f4ec6
commit f07bd06137
15 changed files with 92 additions and 42 deletions

View File

@ -1545,8 +1545,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
infer::Consts(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)
},
}
}

View File

@ -401,7 +401,7 @@ impl NiceRegionError<'me, 'tcx> {
format!(
"{}`{}` would have to be implemented for the type `{}`",
if leading_ellipsis { "..." } else { "" },
expected_trait_ref,
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
expected_trait_ref.map(|tr| tr.self_ty()),
)
} else {
@ -409,7 +409,7 @@ impl NiceRegionError<'me, 'tcx> {
"{}`{}` must implement `{}`",
if leading_ellipsis { "..." } else { "" },
expected_trait_ref.map(|tr| tr.self_ty()),
expected_trait_ref,
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
)
};
@ -449,14 +449,14 @@ impl NiceRegionError<'me, 'tcx> {
let mut note = if passive_voice {
format!(
"...but `{}` is actually implemented for the type `{}`",
actual_trait_ref,
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
actual_trait_ref.map(|tr| tr.self_ty()),
)
} else {
format!(
"...but `{}` actually implements `{}`",
actual_trait_ref.map(|tr| tr.self_ty()),
actual_trait_ref,
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
)
};

View File

@ -1292,7 +1292,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
self.resolve_vars_if_possible(t).to_string()
self.resolve_vars_if_possible(t).print_only_trait_path().to_string()
}
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the

View File

@ -800,8 +800,13 @@ 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))
Symbol::intern(
&format!(
"<impl {} for {}>",
trait_ref.print_only_trait_path(),
self_ty
)
)
},
None => Symbol::intern(&format!("<impl {}>", self_ty)),
});

View File

@ -737,7 +737,9 @@ impl<'a, 'tcx> InferCtxt<'a, '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, note) = if is_try && is_from {
(Some(format!(
"`?` couldn't convert the error to `{}`",
@ -768,7 +770,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
format!(
"{}the trait `{}` is not implemented for `{}`",
pre_message,
trait_ref,
trait_ref.print_only_trait_path(),
trait_ref.self_ty(),
)
};
@ -1189,7 +1191,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
if param_ty => {
// Missing generic type parameter bound.
let param_name = self_ty.to_string();
let constraint = trait_ref.to_string();
let constraint = trait_ref.print_only_trait_path().to_string();
if suggest_constraining_type_param(
generics,
&mut err,
@ -1416,7 +1418,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let msg = format!(
"the trait bound `{}: {}` is not satisfied",
found,
obligation.parent_trait_ref.skip_binder(),
obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
);
if has_custom_message {
err.note(&msg);
@ -1430,7 +1432,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
err.span_label(span, &format!(
"expected an implementor of trait `{}`",
obligation.parent_trait_ref.skip_binder(),
obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
));
err.span_suggestion(
span,
@ -1562,7 +1564,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} else {
err.note(&format!(
"`{}` is implemented for `{:?}`, but not for `{:?}`",
trait_ref,
trait_ref.print_only_trait_path(),
trait_type,
trait_ref.skip_binder().self_ty(),
));
@ -2226,7 +2228,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.span_note(span, &format!(
"future does not implement `{}` as this value is used across an await",
trait_ref,
trait_ref.print_only_trait_path(),
));
// Add a note for the item obligation that remains - normally a note pointing to the
@ -2409,7 +2411,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let parent_trait_ref = self.resolve_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,

View File

@ -1044,7 +1044,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
let self_ty = trait_ref.self_ty();
let cause = IntercrateAmbiguityCause::DownstreamCrate {
trait_desc: trait_ref.to_string(),
trait_desc: trait_ref.print_only_trait_path().to_string(),
self_desc: if self_ty.has_concrete_skeleton() {
Some(self_ty.to_string())
} else {
@ -1386,7 +1386,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if !candidate_set.ambiguous && no_candidates_apply {
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
let self_ty = trait_ref.self_ty();
let trait_desc = trait_ref.to_string();
let trait_desc = trait_ref.print_only_trait_path().to_string();
let self_desc = if self_ty.has_concrete_skeleton() {
Some(self_ty.to_string())
} else {

View File

@ -417,7 +417,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String>
w.push('>');
}
write!(w, " {} for {}", trait_ref, tcx.type_of(impl_def_id)).unwrap();
write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
// The predicates will contain default bounds like `T: Sized`. We need to
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.

View File

@ -146,7 +146,7 @@ impl<'tcx> Children {
let self_ty = trait_ref.self_ty();
OverlapError {
with_impl: possible_sibling,
trait_desc: trait_ref.to_string(),
trait_desc: trait_ref.print_only_trait_path().to_string(),
// Only report the `Self` type if it has at least
// some outer concrete shell; otherwise, it's
// not adding much information.

View File

@ -449,7 +449,7 @@ pub trait PrettyPrinter<'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)
})
@ -468,7 +468,7 @@ pub trait PrettyPrinter<'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));
@ -619,7 +619,7 @@ pub trait PrettyPrinter<'tcx>:
p!(
write("{}", if first { " " } else { "+" }),
print(trait_ref));
print(trait_ref.print_only_trait_path()));
first = false;
}
}
@ -1696,6 +1696,30 @@ impl fmt::Display for ty::RegionKind {
}
}
/// 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, TypeFoldable, Lift)]
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl ty::TraitRef<'tcx> {
pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
TraitRefPrintOnlyTraitPath(self)
}
}
impl ty::Binder<ty::TraitRef<'tcx>> {
pub fn print_only_trait_path(self) -> ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>> {
self.map_bound(|tr| tr.print_only_trait_path())
}
}
forward_display_to_print! {
Ty<'tcx>,
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
@ -1705,6 +1729,7 @@ forward_display_to_print! {
// because `for<'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>>,
@ -1739,7 +1764,7 @@ define_print_and_forward_display! {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = cx.tcx().mk_ty_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> {
@ -1783,7 +1808,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.print_only_trait_path()))
}
TraitRefPrintOnlyTraitPath<'tcx> {
p!(print_def_path(self.0.def_id, self.0.substs));
}
ty::ParamTy {
@ -1799,7 +1828,8 @@ 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> {

View File

@ -223,10 +223,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)
}
}

View File

@ -84,7 +84,7 @@ where
{
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
let TraitRef { def_id, substs } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) ||
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path()) ||
(!self.def_id_visitor.shallow() && substs.visit_with(self))
}

View File

@ -1149,8 +1149,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
});
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
binding.item_name, binding.span)
self.one_bound_for_assoc_type(
candidates,
&trait_ref.print_only_trait_path().to_string(),
binding.item_name,
binding.span
)
}?;
let (assoc_ident, def_scope) =
@ -1589,12 +1593,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(span) = bound_span {
err.span_label(span, format!("ambiguous `{}` from `{}`",
assoc_name,
bound));
bound.print_only_trait_path()));
} else {
span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
bound);
bound.print_only_trait_path());
}
}
err.emit();

View File

@ -502,7 +502,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !unsatisfied_predicates.is_empty() {
let mut bound_list = unsatisfied_predicates.iter()
.map(|p| format!("`{} : {}`", p.self_ty(), p))
.map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path()))
.collect::<Vec<_>>();
bound_list.sort();
bound_list.dedup(); // #35677

View File

@ -2002,7 +2002,7 @@ fn check_impl_items_against_trait<'tcx>(
"item `{}` is an associated const, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref);
impl_trait_ref.print_only_trait_path());
err.span_label(impl_item.span, "does not match trait");
// We can only get the spans from local trait definition
// Same for E0324 and E0325
@ -2026,7 +2026,7 @@ fn check_impl_items_against_trait<'tcx>(
"item `{}` is an associated method, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref);
impl_trait_ref.print_only_trait_path());
err.span_label(impl_item.span, "does not match trait");
if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, "item in trait");
@ -2045,7 +2045,7 @@ fn check_impl_items_against_trait<'tcx>(
"item `{}` is an associated type, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref);
impl_trait_ref.print_only_trait_path());
err.span_label(impl_item.span, "does not match trait");
if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, "item in trait");

View File

@ -35,7 +35,7 @@ impl UnsafetyChecker<'tcx> {
item.span,
E0199,
"implementing the trait `{}` is not unsafe",
trait_ref);
trait_ref.print_only_trait_path());
}
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
@ -43,7 +43,7 @@ impl UnsafetyChecker<'tcx> {
item.span,
E0200,
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref);
trait_ref.print_only_trait_path());
}
(Unsafety::Normal, Some(attr_name), Unsafety::Normal,