Skip to content

Commit 9933b80

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#59188.
2 parents 54a3aa8 + f07bd06 commit 9933b80

File tree

15 files changed

+92
-42
lines changed

15 files changed

+92
-42
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 14 additions & 2 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 7 additions & 2 deletions
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

Lines changed: 10 additions & 8 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 36 additions & 6 deletions
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

Lines changed: 1 addition & 4 deletions
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

0 commit comments

Comments
 (0)