about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2019-11-29 22:57:31 +0100
committerGitHub <noreply@github.com>2019-11-29 22:57:31 +0100
commit64efc45bb9f550374df302d219dd721f19604b2b (patch)
tree4ddc18399246474f221c194358833e3844334a23
parent7b75a360f6913445a593b7c8f2635f77b609da35 (diff)
parentf07bd0613790080225cc7f7cc735655dcb2257f8 (diff)
downloadrust-64efc45bb9f550374df302d219dd721f19604b2b.tar.gz
rust-64efc45bb9f550374df302d219dd721f19604b2b.zip
Rollup merge of #66613 - Areredify:trait-ref-print, r=eddyb
Allow customising ty::TraitRef's printing behavior

This pr allows to explicitly choose which representation of `TraitRef` (`<T as Trait<U>>` or `Trait<U>`) you want to print. `Debug` and `Display` representations of `TraitRef` now match.

Closes #59188.
-rw-r--r--src/librustc/infer/error_reporting/mod.rs16
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs8
-rw-r--r--src/librustc/infer/mod.rs2
-rw-r--r--src/librustc/lint/context.rs9
-rw-r--r--src/librustc/traits/error_reporting.rs18
-rw-r--r--src/librustc/traits/select.rs4
-rw-r--r--src/librustc/traits/specialize/mod.rs2
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs2
-rw-r--r--src/librustc/ty/print/pretty.rs42
-rw-r--r--src/librustc/ty/structural_impls.rs5
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_typeck/astconv.rs12
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs4
15 files changed, 92 insertions, 42 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index b670658a10a..5a940f2f80a 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -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)
+            },
         }
     }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index bfa8353ca34..3b4d06aab27 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -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()),
                 )
             };
 
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 5e204d83aef..b3ddffc8b12 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -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
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 2f865f1f8b5..05543f1d2ef 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -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)),
                 });
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 6e723cdc999..90db1fe3195 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -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,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 283fa56d11f..5f324527a27 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -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 {
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 475037f54ba..88a2db3dc62 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -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.
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index d945c756f66..b8ddf6078bd 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -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.
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 2a311ea9624..c941b3e5e4b 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -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> {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index a0e66d340ae..ffbf8813d30 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -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)
     }
 }
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 8c4b4c16510..fcbc2a3301a 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -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))
     }
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index a33b2e32c86..fdbf729a773 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -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();
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 6e37a1a47f0..f4b53b4d106 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -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
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 930241262b0..3a4a4a50bf2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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");
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 5bb44499968..650e15ea8a7 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -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,