Skip to content

Commit 3592437

Browse files
committed
Pass TraitRefs to overlap
1 parent 735ddcc commit 3592437

File tree

1 file changed

+41
-27
lines changed

1 file changed

+41
-27
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
1919
use rustc_middle::traits::specialization_graph::OverlapMode;
2020
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
2121
use rustc_middle::ty::{
22-
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
22+
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
23+
TypeVisitor, TypingMode,
2324
};
2425
pub use rustc_next_trait_solver::coherence::*;
2526
use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
@@ -120,7 +121,7 @@ pub fn overlapping_inherent_impls(
120121
return None;
121122
}
122123

123-
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, false)
124+
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, None)
124125
}
125126

126127
/// If there are types that satisfy both impls, returns `Some`
@@ -137,8 +138,10 @@ pub fn overlapping_trait_impls(
137138
// Before doing expensive operations like entering an inference context, do
138139
// a quick check via fast_reject to tell if the impl headers could possibly
139140
// unify.
140-
let impl1_args = tcx.impl_trait_ref(impl1_def_id).unwrap().skip_binder().args;
141-
let impl2_args = tcx.impl_trait_ref(impl2_def_id).unwrap().skip_binder().args;
141+
let trait_ref1 = tcx.impl_trait_ref(impl1_def_id).unwrap();
142+
let trait_ref2 = tcx.impl_trait_ref(impl2_def_id).unwrap();
143+
let impl1_args = trait_ref1.skip_binder().args;
144+
let impl2_args = trait_ref2.skip_binder().args;
142145
let may_overlap =
143146
DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args);
144147

@@ -148,17 +151,21 @@ pub fn overlapping_trait_impls(
148151
return None;
149152
}
150153

151-
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, true)
154+
let trait_refs = Some((trait_ref1, trait_ref2));
155+
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, trait_refs)
152156
}
153157

154-
fn overlapping_impls(
155-
tcx: TyCtxt<'_>,
158+
fn overlapping_impls<'tcx>(
159+
tcx: TyCtxt<'tcx>,
156160
impl1_def_id: DefId,
157161
impl2_def_id: DefId,
158162
skip_leak_check: SkipLeakCheck,
159163
overlap_mode: OverlapMode,
160-
is_of_trait: bool,
161-
) -> Option<OverlapResult<'_>> {
164+
trait_refs: Option<(
165+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
166+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
167+
)>,
168+
) -> Option<OverlapResult<'tcx>> {
162169
if tcx.next_trait_solver_in_coherence() {
163170
overlap(
164171
tcx,
@@ -167,7 +174,7 @@ fn overlapping_impls(
167174
impl1_def_id,
168175
impl2_def_id,
169176
overlap_mode,
170-
is_of_trait,
177+
trait_refs,
171178
)
172179
} else {
173180
let _overlap_with_bad_diagnostics = overlap(
@@ -177,7 +184,7 @@ fn overlapping_impls(
177184
impl1_def_id,
178185
impl2_def_id,
179186
overlap_mode,
180-
is_of_trait,
187+
trait_refs,
181188
)?;
182189

183190
// In the case where we detect an error, run the check again, but
@@ -190,7 +197,7 @@ fn overlapping_impls(
190197
impl1_def_id,
191198
impl2_def_id,
192199
overlap_mode,
193-
is_of_trait,
200+
trait_refs,
194201
)
195202
.unwrap();
196203
Some(overlap)
@@ -200,7 +207,7 @@ fn overlapping_impls(
200207
fn fresh_impl_header<'tcx>(
201208
infcx: &InferCtxt<'tcx>,
202209
impl_def_id: DefId,
203-
is_of_trait: bool,
210+
trait_ref: Option<EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
204211
) -> ImplHeader<'tcx> {
205212
let tcx = infcx.tcx;
206213
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
@@ -209,8 +216,7 @@ fn fresh_impl_header<'tcx>(
209216
impl_def_id,
210217
impl_args,
211218
self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
212-
trait_ref: is_of_trait
213-
.then(|| tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args)),
219+
trait_ref: trait_ref.map(|trait_ref| trait_ref.instantiate(tcx, impl_args)),
214220
predicates: tcx
215221
.predicates_of(impl_def_id)
216222
.instantiate(tcx, impl_args)
@@ -224,9 +230,9 @@ fn fresh_impl_header_normalized<'tcx>(
224230
infcx: &InferCtxt<'tcx>,
225231
param_env: ty::ParamEnv<'tcx>,
226232
impl_def_id: DefId,
227-
is_of_trait: bool,
233+
trait_ref: Option<EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
228234
) -> ImplHeader<'tcx> {
229-
let header = fresh_impl_header(infcx, impl_def_id, is_of_trait);
235+
let header = fresh_impl_header(infcx, impl_def_id, trait_ref);
230236

231237
let InferOk { value: mut header, obligations } =
232238
infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
@@ -245,15 +251,18 @@ fn overlap<'tcx>(
245251
impl1_def_id: DefId,
246252
impl2_def_id: DefId,
247253
overlap_mode: OverlapMode,
248-
is_of_trait: bool,
254+
trait_refs: Option<(
255+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
256+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
257+
)>,
249258
) -> Option<OverlapResult<'tcx>> {
250259
if overlap_mode.use_negative_impl() {
251-
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, is_of_trait)
260+
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, trait_refs)
252261
|| impl_intersection_has_negative_obligation(
253262
tcx,
254263
impl2_def_id,
255264
impl1_def_id,
256-
is_of_trait,
265+
trait_refs,
257266
)
258267
{
259268
return None;
@@ -276,10 +285,11 @@ fn overlap<'tcx>(
276285
// empty environment.
277286
let param_env = ty::ParamEnv::empty();
278287

288+
let (trait_ref1, trait_ref2) = trait_refs.unzip();
279289
let impl1_header =
280-
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait);
290+
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, trait_ref1);
281291
let impl2_header =
282-
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait);
292+
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, trait_ref2);
283293

284294
// Equate the headers to find their intersection (the general type, with infer vars,
285295
// that may apply both impls).
@@ -489,11 +499,14 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
489499
/// after negating, giving us `&str: !Error`. This is a negative impl provided by
490500
/// libstd, and therefore we can guarantee for certain that libstd will never add
491501
/// a positive impl for `&str: Error` (without it being a breaking change).
492-
fn impl_intersection_has_negative_obligation(
493-
tcx: TyCtxt<'_>,
502+
fn impl_intersection_has_negative_obligation<'tcx>(
503+
tcx: TyCtxt<'tcx>,
494504
impl1_def_id: DefId,
495505
impl2_def_id: DefId,
496-
is_of_trait: bool,
506+
trait_refs: Option<(
507+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
508+
EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
509+
)>,
497510
) -> bool {
498511
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
499512

@@ -503,11 +516,12 @@ fn impl_intersection_has_negative_obligation(
503516
let root_universe = infcx.universe();
504517
assert_eq!(root_universe, ty::UniverseIndex::ROOT);
505518

506-
let impl1_header = fresh_impl_header(infcx, impl1_def_id, is_of_trait);
519+
let (trait_ref1, trait_ref2) = trait_refs.unzip();
520+
let impl1_header = fresh_impl_header(infcx, impl1_def_id, trait_ref1);
507521
let param_env =
508522
ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)).instantiate(tcx, impl1_header.impl_args);
509523

510-
let impl2_header = fresh_impl_header(infcx, impl2_def_id, is_of_trait);
524+
let impl2_header = fresh_impl_header(infcx, impl2_def_id, trait_ref2);
511525

512526
// Equate the headers to find their intersection (the general type, with infer vars,
513527
// that may apply both impls).

0 commit comments

Comments
 (0)