Skip to content

Commit b16b339

Browse files
committed
Auto 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.
2 parents 25d8a94 + f07bd06 commit b16b339

File tree

15 files changed

+92
-42
lines changed

15 files changed

+92
-42
lines changed

src/librustc/infer/error_reporting/mod.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1545,8 +1545,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15451545
infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
15461546
infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
15471547
infer::Consts(ref exp_found) => self.expected_found_str(exp_found),
1548-
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
1549-
infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
1548+
infer::TraitRefs(ref exp_found) => {
1549+
let pretty_exp_found = ty::error::ExpectedFound {
1550+
expected: exp_found.expected.print_only_trait_path(),
1551+
found: exp_found.found.print_only_trait_path()
1552+
};
1553+
self.expected_found_str(&pretty_exp_found)
1554+
},
1555+
infer::PolyTraitRefs(ref exp_found) => {
1556+
let pretty_exp_found = ty::error::ExpectedFound {
1557+
expected: exp_found.expected.print_only_trait_path(),
1558+
found: exp_found.found.print_only_trait_path()
1559+
};
1560+
self.expected_found_str(&pretty_exp_found)
1561+
},
15501562
}
15511563
}
15521564

src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,15 @@ impl NiceRegionError<'me, 'tcx> {
401401
format!(
402402
"{}`{}` would have to be implemented for the type `{}`",
403403
if leading_ellipsis { "..." } else { "" },
404-
expected_trait_ref,
404+
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
405405
expected_trait_ref.map(|tr| tr.self_ty()),
406406
)
407407
} else {
408408
format!(
409409
"{}`{}` must implement `{}`",
410410
if leading_ellipsis { "..." } else { "" },
411411
expected_trait_ref.map(|tr| tr.self_ty()),
412-
expected_trait_ref,
412+
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
413413
)
414414
};
415415

@@ -449,14 +449,14 @@ impl NiceRegionError<'me, 'tcx> {
449449
let mut note = if passive_voice {
450450
format!(
451451
"...but `{}` is actually implemented for the type `{}`",
452-
actual_trait_ref,
452+
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
453453
actual_trait_ref.map(|tr| tr.self_ty()),
454454
)
455455
} else {
456456
format!(
457457
"...but `{}` actually implements `{}`",
458458
actual_trait_ref.map(|tr| tr.self_ty()),
459-
actual_trait_ref,
459+
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
460460
)
461461
};
462462

src/librustc/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12921292
}
12931293

12941294
pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
1295-
self.resolve_vars_if_possible(t).to_string()
1295+
self.resolve_vars_if_possible(t).print_only_trait_path().to_string()
12961296
}
12971297

12981298
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the

src/librustc/lint/context.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,13 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
800800
// This shouldn't ever be needed, but just in case:
801801
path.push(match trait_ref {
802802
Some(trait_ref) => {
803-
Symbol::intern(&format!("<impl {} for {}>", trait_ref,
804-
self_ty))
803+
Symbol::intern(
804+
&format!(
805+
"<impl {} for {}>",
806+
trait_ref.print_only_trait_path(),
807+
self_ty
808+
)
809+
)
805810
},
806811
None => Symbol::intern(&format!("<impl {}>", self_ty)),
807812
});

src/librustc/traits/error_reporting.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
737737
let is_try = self.tcx.sess.source_map().span_to_snippet(span)
738738
.map(|s| &s == "?")
739739
.unwrap_or(false);
740-
let is_from = format!("{}", trait_ref).starts_with("std::convert::From<");
740+
let is_from =
741+
format!("{}", trait_ref.print_only_trait_path())
742+
.starts_with("std::convert::From<");
741743
let (message, note) = if is_try && is_from {
742744
(Some(format!(
743745
"`?` couldn't convert the error to `{}`",
@@ -768,7 +770,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
768770
format!(
769771
"{}the trait `{}` is not implemented for `{}`",
770772
pre_message,
771-
trait_ref,
773+
trait_ref.print_only_trait_path(),
772774
trait_ref.self_ty(),
773775
)
774776
};
@@ -1189,7 +1191,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11891191
if param_ty => {
11901192
// Missing generic type parameter bound.
11911193
let param_name = self_ty.to_string();
1192-
let constraint = trait_ref.to_string();
1194+
let constraint = trait_ref.print_only_trait_path().to_string();
11931195
if suggest_constraining_type_param(
11941196
generics,
11951197
&mut err,
@@ -1416,7 +1418,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14161418
let msg = format!(
14171419
"the trait bound `{}: {}` is not satisfied",
14181420
found,
1419-
obligation.parent_trait_ref.skip_binder(),
1421+
obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
14201422
);
14211423
if has_custom_message {
14221424
err.note(&msg);
@@ -1430,7 +1432,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14301432
}
14311433
err.span_label(span, &format!(
14321434
"expected an implementor of trait `{}`",
1433-
obligation.parent_trait_ref.skip_binder(),
1435+
obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
14341436
));
14351437
err.span_suggestion(
14361438
span,
@@ -1562,7 +1564,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15621564
} else {
15631565
err.note(&format!(
15641566
"`{}` is implemented for `{:?}`, but not for `{:?}`",
1565-
trait_ref,
1567+
trait_ref.print_only_trait_path(),
15661568
trait_type,
15671569
trait_ref.skip_binder().self_ty(),
15681570
));
@@ -2226,7 +2228,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22262228

22272229
err.span_note(span, &format!(
22282230
"future does not implement `{}` as this value is used across an await",
2229-
trait_ref,
2231+
trait_ref.print_only_trait_path(),
22302232
));
22312233

22322234
// 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> {
24092411
let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
24102412
err.note(
24112413
&format!("required because of the requirements on the impl of `{}` for `{}`",
2412-
parent_trait_ref,
2414+
parent_trait_ref.print_only_trait_path(),
24132415
parent_trait_ref.skip_binder().self_ty()));
24142416
let parent_predicate = parent_trait_ref.to_predicate();
24152417
self.note_obligation_cause_code(err,

src/librustc/traits/select.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10441044
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
10451045
let self_ty = trait_ref.self_ty();
10461046
let cause = IntercrateAmbiguityCause::DownstreamCrate {
1047-
trait_desc: trait_ref.to_string(),
1047+
trait_desc: trait_ref.print_only_trait_path().to_string(),
10481048
self_desc: if self_ty.has_concrete_skeleton() {
10491049
Some(self_ty.to_string())
10501050
} else {
@@ -1386,7 +1386,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13861386
if !candidate_set.ambiguous && no_candidates_apply {
13871387
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
13881388
let self_ty = trait_ref.self_ty();
1389-
let trait_desc = trait_ref.to_string();
1389+
let trait_desc = trait_ref.print_only_trait_path().to_string();
13901390
let self_desc = if self_ty.has_concrete_skeleton() {
13911391
Some(self_ty.to_string())
13921392
} else {

src/librustc/traits/specialize/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String>
417417
w.push('>');
418418
}
419419

420-
write!(w, " {} for {}", trait_ref, tcx.type_of(impl_def_id)).unwrap();
420+
write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
421421

422422
// The predicates will contain default bounds like `T: Sized`. We need to
423423
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.

src/librustc/traits/specialize/specialization_graph.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'tcx> Children {
146146
let self_ty = trait_ref.self_ty();
147147
OverlapError {
148148
with_impl: possible_sibling,
149-
trait_desc: trait_ref.to_string(),
149+
trait_desc: trait_ref.print_only_trait_path().to_string(),
150150
// Only report the `Self` type if it has at least
151151
// some outer concrete shell; otherwise, it's
152152
// not adding much information.

src/librustc/ty/print/pretty.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ pub trait PrettyPrinter<'tcx>:
449449

450450
p!(print(self_ty));
451451
if let Some(trait_ref) = trait_ref {
452-
p!(write(" as "), print(trait_ref));
452+
p!(write(" as "), print(trait_ref.print_only_trait_path()));
453453
}
454454
Ok(cx)
455455
})
@@ -468,7 +468,7 @@ pub trait PrettyPrinter<'tcx>:
468468

469469
p!(write("impl "));
470470
if let Some(trait_ref) = trait_ref {
471-
p!(print(trait_ref), write(" for "));
471+
p!(print(trait_ref.print_only_trait_path()), write(" for "));
472472
}
473473
p!(print(self_ty));
474474

@@ -619,7 +619,7 @@ pub trait PrettyPrinter<'tcx>:
619619

620620
p!(
621621
write("{}", if first { " " } else { "+" }),
622-
print(trait_ref));
622+
print(trait_ref.print_only_trait_path()));
623623
first = false;
624624
}
625625
}
@@ -1696,6 +1696,30 @@ impl fmt::Display for ty::RegionKind {
16961696
}
16971697
}
16981698

1699+
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
1700+
/// the trait path. That is, it will print `Trait<U>` instead of
1701+
/// `<T as Trait<U>>`.
1702+
#[derive(Copy, Clone, TypeFoldable, Lift)]
1703+
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
1704+
1705+
impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
1706+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1707+
fmt::Display::fmt(self, f)
1708+
}
1709+
}
1710+
1711+
impl ty::TraitRef<'tcx> {
1712+
pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
1713+
TraitRefPrintOnlyTraitPath(self)
1714+
}
1715+
}
1716+
1717+
impl ty::Binder<ty::TraitRef<'tcx>> {
1718+
pub fn print_only_trait_path(self) -> ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>> {
1719+
self.map_bound(|tr| tr.print_only_trait_path())
1720+
}
1721+
}
1722+
16991723
forward_display_to_print! {
17001724
Ty<'tcx>,
17011725
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
@@ -1705,6 +1729,7 @@ forward_display_to_print! {
17051729
// because `for<'tcx>` isn't possible yet.
17061730
ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
17071731
ty::Binder<ty::TraitRef<'tcx>>,
1732+
ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>>,
17081733
ty::Binder<ty::FnSig<'tcx>>,
17091734
ty::Binder<ty::TraitPredicate<'tcx>>,
17101735
ty::Binder<ty::SubtypePredicate<'tcx>>,
@@ -1739,7 +1764,7 @@ define_print_and_forward_display! {
17391764
// Use a type that can't appear in defaults of type parameters.
17401765
let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
17411766
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
1742-
p!(print(trait_ref))
1767+
p!(print(trait_ref.print_only_trait_path()))
17431768
}
17441769

17451770
ty::ExistentialProjection<'tcx> {
@@ -1783,7 +1808,11 @@ define_print_and_forward_display! {
17831808
}
17841809

17851810
ty::TraitRef<'tcx> {
1786-
p!(print_def_path(self.def_id, self.substs));
1811+
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
1812+
}
1813+
1814+
TraitRefPrintOnlyTraitPath<'tcx> {
1815+
p!(print_def_path(self.0.def_id, self.0.substs));
17871816
}
17881817

17891818
ty::ParamTy {
@@ -1799,7 +1828,8 @@ define_print_and_forward_display! {
17991828
}
18001829

18011830
ty::TraitPredicate<'tcx> {
1802-
p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1831+
p!(print(self.trait_ref.self_ty()), write(": "),
1832+
print(self.trait_ref.print_only_trait_path()))
18031833
}
18041834

18051835
ty::ProjectionPredicate<'tcx> {

src/librustc/ty/structural_impls.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,7 @@ impl fmt::Debug for ty::FloatVarValue {
223223

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

src/librustc_privacy/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ where
8484
{
8585
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
8686
let TraitRef { def_id, substs } = trait_ref;
87-
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) ||
87+
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path()) ||
8888
(!self.def_id_visitor.shallow() && substs.visit_with(self))
8989
}
9090

src/librustc_typeck/astconv.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11491149
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
11501150
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
11511151
});
1152-
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
1153-
binding.item_name, binding.span)
1152+
self.one_bound_for_assoc_type(
1153+
candidates,
1154+
&trait_ref.print_only_trait_path().to_string(),
1155+
binding.item_name,
1156+
binding.span
1157+
)
11541158
}?;
11551159

11561160
let (assoc_ident, def_scope) =
@@ -1589,12 +1593,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15891593
if let Some(span) = bound_span {
15901594
err.span_label(span, format!("ambiguous `{}` from `{}`",
15911595
assoc_name,
1592-
bound));
1596+
bound.print_only_trait_path()));
15931597
} else {
15941598
span_note!(&mut err, span,
15951599
"associated type `{}` could derive from `{}`",
15961600
ty_param_name,
1597-
bound);
1601+
bound.print_only_trait_path());
15981602
}
15991603
}
16001604
err.emit();

src/librustc_typeck/check/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
502502

503503
if !unsatisfied_predicates.is_empty() {
504504
let mut bound_list = unsatisfied_predicates.iter()
505-
.map(|p| format!("`{} : {}`", p.self_ty(), p))
505+
.map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path()))
506506
.collect::<Vec<_>>();
507507
bound_list.sort();
508508
bound_list.dedup(); // #35677

src/librustc_typeck/check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,7 @@ fn check_impl_items_against_trait<'tcx>(
20022002
"item `{}` is an associated const, \
20032003
which doesn't match its trait `{}`",
20042004
ty_impl_item.ident,
2005-
impl_trait_ref);
2005+
impl_trait_ref.print_only_trait_path());
20062006
err.span_label(impl_item.span, "does not match trait");
20072007
// We can only get the spans from local trait definition
20082008
// Same for E0324 and E0325
@@ -2026,7 +2026,7 @@ fn check_impl_items_against_trait<'tcx>(
20262026
"item `{}` is an associated method, \
20272027
which doesn't match its trait `{}`",
20282028
ty_impl_item.ident,
2029-
impl_trait_ref);
2029+
impl_trait_ref.print_only_trait_path());
20302030
err.span_label(impl_item.span, "does not match trait");
20312031
if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
20322032
err.span_label(trait_span, "item in trait");
@@ -2045,7 +2045,7 @@ fn check_impl_items_against_trait<'tcx>(
20452045
"item `{}` is an associated type, \
20462046
which doesn't match its trait `{}`",
20472047
ty_impl_item.ident,
2048-
impl_trait_ref);
2048+
impl_trait_ref.print_only_trait_path());
20492049
err.span_label(impl_item.span, "does not match trait");
20502050
if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
20512051
err.span_label(trait_span, "item in trait");

src/librustc_typeck/coherence/unsafety.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ impl UnsafetyChecker<'tcx> {
3535
item.span,
3636
E0199,
3737
"implementing the trait `{}` is not unsafe",
38-
trait_ref);
38+
trait_ref.print_only_trait_path());
3939
}
4040

4141
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
4242
span_err!(self.tcx.sess,
4343
item.span,
4444
E0200,
4545
"the trait `{}` requires an `unsafe impl` declaration",
46-
trait_ref);
46+
trait_ref.print_only_trait_path());
4747
}
4848

4949
(Unsafety::Normal, Some(attr_name), Unsafety::Normal,

0 commit comments

Comments
 (0)