Skip to content

Commit 0750a5d

Browse files
AmbiguityCause should not eagerly format strings
1 parent b06258c commit 0750a5d

File tree

3 files changed

+54
-67
lines changed

3 files changed

+54
-67
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+15-24
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
2929
use rustc_middle::traits::specialization_graph::OverlapMode;
3030
use rustc_middle::traits::DefiningAnchor;
3131
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
32-
use rustc_middle::ty::print::with_no_trimmed_paths;
3332
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
3433
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
3534
use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE;
@@ -54,7 +53,7 @@ pub enum Conflict {
5453

5554
pub struct OverlapResult<'tcx> {
5655
pub impl_header: ty::ImplHeader<'tcx>,
57-
pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>,
56+
pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
5857

5958
/// `true` if the overlap might've been permitted before the shift
6059
/// to universes.
@@ -979,8 +978,8 @@ where
979978
fn compute_intercrate_ambiguity_causes<'tcx>(
980979
infcx: &InferCtxt<'tcx>,
981980
obligations: &[PredicateObligation<'tcx>],
982-
) -> FxIndexSet<IntercrateAmbiguityCause> {
983-
let mut causes: FxIndexSet<IntercrateAmbiguityCause> = Default::default();
981+
) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
982+
let mut causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>> = Default::default();
984983

985984
for obligation in obligations {
986985
search_ambiguity_causes(infcx, obligation.clone().into(), &mut causes);
@@ -989,11 +988,11 @@ fn compute_intercrate_ambiguity_causes<'tcx>(
989988
causes
990989
}
991990

992-
struct AmbiguityCausesVisitor<'a> {
993-
causes: &'a mut FxIndexSet<IntercrateAmbiguityCause>,
991+
struct AmbiguityCausesVisitor<'a, 'tcx> {
992+
causes: &'a mut FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
994993
}
995994

996-
impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
995+
impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
997996
type BreakTy = !;
998997
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy> {
999998
let infcx = goal.infcx();
@@ -1033,14 +1032,12 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
10331032
} = cand.kind()
10341033
{
10351034
if let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) {
1036-
let value = infcx
1035+
let message = infcx
10371036
.tcx
10381037
.get_attr(def_id, sym::rustc_reservation_impl)
10391038
.and_then(|a| a.value_str());
1040-
if let Some(value) = value {
1041-
self.causes.insert(IntercrateAmbiguityCause::ReservationImpl {
1042-
message: value.to_string(),
1043-
});
1039+
if let Some(message) = message {
1040+
self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message });
10441041
}
10451042
}
10461043
}
@@ -1078,24 +1075,18 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
10781075
Ok(Err(conflict)) => {
10791076
if !trait_ref.references_error() {
10801077
let self_ty = trait_ref.self_ty();
1081-
let (trait_desc, self_desc) = with_no_trimmed_paths!({
1082-
let trait_desc = trait_ref.print_only_trait_path().to_string();
1083-
let self_desc = self_ty
1084-
.has_concrete_skeleton()
1085-
.then(|| self_ty.to_string());
1086-
(trait_desc, self_desc)
1087-
});
1078+
let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);
10881079
ambiguity_cause = Some(match conflict {
10891080
Conflict::Upstream => {
10901081
IntercrateAmbiguityCause::UpstreamCrateUpdate {
1091-
trait_desc,
1092-
self_desc,
1082+
trait_ref,
1083+
self_ty,
10931084
}
10941085
}
10951086
Conflict::Downstream => {
10961087
IntercrateAmbiguityCause::DownstreamCrate {
1097-
trait_desc,
1098-
self_desc,
1088+
trait_ref,
1089+
self_ty,
10991090
}
11001091
}
11011092
});
@@ -1132,7 +1123,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
11321123
fn search_ambiguity_causes<'tcx>(
11331124
infcx: &InferCtxt<'tcx>,
11341125
goal: Goal<'tcx, ty::Predicate<'tcx>>,
1135-
causes: &mut FxIndexSet<IntercrateAmbiguityCause>,
1126+
causes: &mut FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
11361127
) {
11371128
infcx.visit_proof_tree(goal, &mut AmbiguityCausesVisitor { causes });
11381129
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+38-42
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use rustc_middle::ty::GenericArgsRef;
4646
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
4747
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
4848
use rustc_span::symbol::sym;
49+
use rustc_span::Symbol;
4950

5051
use std::cell::{Cell, RefCell};
5152
use std::cmp;
@@ -59,42 +60,46 @@ mod candidate_assembly;
5960
mod confirmation;
6061

6162
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
62-
pub enum IntercrateAmbiguityCause {
63-
DownstreamCrate { trait_desc: String, self_desc: Option<String> },
64-
UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
65-
ReservationImpl { message: String },
63+
pub enum IntercrateAmbiguityCause<'tcx> {
64+
DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },
65+
UpstreamCrateUpdate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },
66+
ReservationImpl { message: Symbol },
6667
}
6768

68-
impl IntercrateAmbiguityCause {
69+
impl<'tcx> IntercrateAmbiguityCause<'tcx> {
6970
/// Emits notes when the overlap is caused by complex intercrate ambiguities.
7071
/// See #23980 for details.
7172
pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diagnostic) {
7273
err.note(self.intercrate_ambiguity_hint());
7374
}
7475

7576
pub fn intercrate_ambiguity_hint(&self) -> String {
76-
match self {
77-
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } => {
78-
let self_desc = if let Some(ty) = self_desc {
79-
format!(" for type `{ty}`")
80-
} else {
81-
String::new()
82-
};
83-
format!("downstream crates may implement trait `{trait_desc}`{self_desc}")
77+
with_no_trimmed_paths!(match self {
78+
IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } => {
79+
format!(
80+
"downstream crates may implement trait `{trait_desc}`{self_desc}",
81+
trait_desc = trait_ref.print_only_trait_path(),
82+
self_desc = if let Some(self_ty) = self_ty {
83+
format!(" for type `{self_ty}`")
84+
} else {
85+
String::new()
86+
}
87+
)
8488
}
85-
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } => {
86-
let self_desc = if let Some(ty) = self_desc {
87-
format!(" for type `{ty}`")
88-
} else {
89-
String::new()
90-
};
89+
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } => {
9190
format!(
9291
"upstream crates may add a new impl of trait `{trait_desc}`{self_desc} \
93-
in future versions"
92+
in future versions",
93+
trait_desc = trait_ref.print_only_trait_path(),
94+
self_desc = if let Some(self_ty) = self_ty {
95+
format!(" for type `{self_ty}`")
96+
} else {
97+
String::new()
98+
}
9499
)
95100
}
96-
IntercrateAmbiguityCause::ReservationImpl { message } => message.clone(),
97-
}
101+
IntercrateAmbiguityCause::ReservationImpl { message } => message.to_string(),
102+
})
98103
}
99104
}
100105

@@ -114,7 +119,7 @@ pub struct SelectionContext<'cx, 'tcx> {
114119
/// We don't do his until we detect a coherence error because it can
115120
/// lead to false overflow results (#47139) and because always
116121
/// computing it may negatively impact performance.
117-
intercrate_ambiguity_causes: Option<FxIndexSet<IntercrateAmbiguityCause>>,
122+
intercrate_ambiguity_causes: Option<FxIndexSet<IntercrateAmbiguityCause<'tcx>>>,
118123

119124
/// The mode that trait queries run in, which informs our error handling
120125
/// policy. In essence, canonicalized queries need their errors propagated
@@ -270,7 +275,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
270275
/// Gets the intercrate ambiguity causes collected since tracking
271276
/// was enabled and disables tracking at the same time. If
272277
/// tracking is not enabled, just returns an empty vector.
273-
pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
278+
pub fn take_intercrate_ambiguity_causes(
279+
&mut self,
280+
) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
274281
assert!(self.is_intercrate());
275282
self.intercrate_ambiguity_causes.take().unwrap_or_default()
276283
}
@@ -428,19 +435,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
428435
);
429436
if !trait_ref.references_error() {
430437
let self_ty = trait_ref.self_ty();
431-
let (trait_desc, self_desc) = with_no_trimmed_paths!({
432-
let trait_desc = trait_ref.print_only_trait_path().to_string();
433-
let self_desc =
434-
self_ty.has_concrete_skeleton().then(|| self_ty.to_string());
435-
(trait_desc, self_desc)
436-
});
438+
let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);
437439
let cause = if let Conflict::Upstream = conflict {
438-
IntercrateAmbiguityCause::UpstreamCrateUpdate {
439-
trait_desc,
440-
self_desc,
441-
}
440+
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty }
442441
} else {
443-
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
442+
IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty }
444443
};
445444
debug!(?cause, "evaluate_stack: pushing cause");
446445
self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
@@ -1451,20 +1450,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14511450
if let ImplCandidate(def_id) = candidate {
14521451
if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) {
14531452
if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes {
1454-
let value = tcx
1453+
let message = tcx
14551454
.get_attr(def_id, sym::rustc_reservation_impl)
14561455
.and_then(|a| a.value_str());
1457-
if let Some(value) = value {
1456+
if let Some(message) = message {
14581457
debug!(
14591458
"filter_reservation_impls: \
14601459
reservation impl ambiguity on {:?}",
14611460
def_id
14621461
);
1463-
intercrate_ambiguity_clauses.insert(
1464-
IntercrateAmbiguityCause::ReservationImpl {
1465-
message: value.to_string(),
1466-
},
1467-
);
1462+
intercrate_ambiguity_clauses
1463+
.insert(IntercrateAmbiguityCause::ReservationImpl { message });
14681464
}
14691465
}
14701466
return Ok(None);

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub struct OverlapError<'tcx> {
3737
pub with_impl: DefId,
3838
pub trait_ref: ty::TraitRef<'tcx>,
3939
pub self_ty: Option<Ty<'tcx>>,
40-
pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>,
40+
pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
4141
pub involves_placeholder: bool,
4242
}
4343

0 commit comments

Comments
 (0)