diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b670658a10a50..5a940f2f80aa2 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 bfa8353ca343f..3b4d06aab27ef 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 5e204d83aef20..b3ddffc8b12f1 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 2f865f1f8b501..05543f1d2ef73 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!("", trait_ref, - self_ty)) + Symbol::intern( + &format!( + "", + trait_ref.print_only_trait_path(), + self_ty + ) + ) }, None => Symbol::intern(&format!("", self_ty)), }); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6e723cdc999b0..90db1fe319556 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 283fa56d11f4f..5f324527a2725 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 475037f54ba38..88a2db3dc6223 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 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 d945c756f6662..b8ddf6078bda6 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 2a311ea962424..c941b3e5e4be9 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` instead of +/// `>`. +#[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> { + pub fn print_only_trait_path(self) -> ty::Binder> { + self.map_bound(|tr| tr.print_only_trait_path()) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>, @@ -1705,6 +1729,7 @@ forward_display_to_print! { // because `for<'tcx>` isn't possible yet. ty::Binder<&'tcx ty::List>>, ty::Binder>, + ty::Binder>, ty::Binder>, ty::Binder>, ty::Binder>, @@ -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 a0e66d340ae9d..ffbf8813d309d 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 8c4b4c16510bb..fcbc2a3301ad1 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 a33b2e32c8658..fdbf729a773aa 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 6e37a1a47f061..f4b53b4d10604 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::>(); bound_list.sort(); bound_list.dedup(); // #35677 diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 930241262b0c1..3a4a4a50bf273 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 5bb444999681d..650e15ea8a7c8 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,