Skip to content

Commit a1adf25

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

File tree

1 file changed

+39
-26
lines changed

1 file changed

+39
-26
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub fn overlapping_inherent_impls(
120120
return None;
121121
}
122122

123-
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, false)
123+
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, None)
124124
}
125125

126126
/// If there are types that satisfy both impls, returns `Some`
@@ -137,8 +137,10 @@ pub fn overlapping_trait_impls(
137137
// Before doing expensive operations like entering an inference context, do
138138
// a quick check via fast_reject to tell if the impl headers could possibly
139139
// 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;
140+
let trait_ref1 = tcx.impl_trait_ref(impl1_def_id).unwrap();
141+
let trait_ref2 = tcx.impl_trait_ref(impl2_def_id).unwrap();
142+
let impl1_args = trait_ref1.skip_binder().args;
143+
let impl2_args = trait_ref2.skip_binder().args;
142144
let may_overlap =
143145
DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args);
144146

@@ -148,17 +150,21 @@ pub fn overlapping_trait_impls(
148150
return None;
149151
}
150152

151-
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, true)
153+
let trait_refs = Some((trait_ref1, trait_ref2));
154+
overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, trait_refs)
152155
}
153156

154-
fn overlapping_impls(
155-
tcx: TyCtxt<'_>,
157+
fn overlapping_impls<'tcx>(
158+
tcx: TyCtxt<'tcx>,
156159
impl1_def_id: DefId,
157160
impl2_def_id: DefId,
158161
skip_leak_check: SkipLeakCheck,
159162
overlap_mode: OverlapMode,
160-
is_of_trait: bool,
161-
) -> Option<OverlapResult<'_>> {
163+
trait_refs: Option<(
164+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
165+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
166+
)>,
167+
) -> Option<OverlapResult<'tcx>> {
162168
if tcx.next_trait_solver_in_coherence() {
163169
overlap(
164170
tcx,
@@ -167,7 +173,7 @@ fn overlapping_impls(
167173
impl1_def_id,
168174
impl2_def_id,
169175
overlap_mode,
170-
is_of_trait,
176+
trait_refs,
171177
)
172178
} else {
173179
let _overlap_with_bad_diagnostics = overlap(
@@ -177,7 +183,7 @@ fn overlapping_impls(
177183
impl1_def_id,
178184
impl2_def_id,
179185
overlap_mode,
180-
is_of_trait,
186+
trait_refs,
181187
)?;
182188

183189
// In the case where we detect an error, run the check again, but
@@ -190,7 +196,7 @@ fn overlapping_impls(
190196
impl1_def_id,
191197
impl2_def_id,
192198
overlap_mode,
193-
is_of_trait,
199+
trait_refs,
194200
)
195201
.unwrap();
196202
Some(overlap)
@@ -200,7 +206,7 @@ fn overlapping_impls(
200206
fn fresh_impl_header<'tcx>(
201207
infcx: &InferCtxt<'tcx>,
202208
impl_def_id: DefId,
203-
is_of_trait: bool,
209+
trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
204210
) -> ImplHeader<'tcx> {
205211
let tcx = infcx.tcx;
206212
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
@@ -209,8 +215,7 @@ fn fresh_impl_header<'tcx>(
209215
impl_def_id,
210216
impl_args,
211217
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)),
218+
trait_ref: trait_ref.map(|trait_ref| trait_ref.instantiate(tcx, impl_args)),
214219
predicates: tcx
215220
.predicates_of(impl_def_id)
216221
.instantiate(tcx, impl_args)
@@ -224,9 +229,9 @@ fn fresh_impl_header_normalized<'tcx>(
224229
infcx: &InferCtxt<'tcx>,
225230
param_env: ty::ParamEnv<'tcx>,
226231
impl_def_id: DefId,
227-
is_of_trait: bool,
232+
trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
228233
) -> ImplHeader<'tcx> {
229-
let header = fresh_impl_header(infcx, impl_def_id, is_of_trait);
234+
let header = fresh_impl_header(infcx, impl_def_id, trait_ref);
230235

231236
let InferOk { value: mut header, obligations } =
232237
infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
@@ -245,15 +250,18 @@ fn overlap<'tcx>(
245250
impl1_def_id: DefId,
246251
impl2_def_id: DefId,
247252
overlap_mode: OverlapMode,
248-
is_of_trait: bool,
253+
trait_refs: Option<(
254+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
255+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
256+
)>,
249257
) -> Option<OverlapResult<'tcx>> {
250258
if overlap_mode.use_negative_impl() {
251-
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, is_of_trait)
259+
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, trait_refs)
252260
|| impl_intersection_has_negative_obligation(
253261
tcx,
254262
impl2_def_id,
255263
impl1_def_id,
256-
is_of_trait,
264+
trait_refs,
257265
)
258266
{
259267
return None;
@@ -276,10 +284,11 @@ fn overlap<'tcx>(
276284
// empty environment.
277285
let param_env = ty::ParamEnv::empty();
278286

287+
let (trait_ref1, trait_ref2) = trait_refs.unzip();
279288
let impl1_header =
280-
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait);
289+
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, trait_ref1);
281290
let impl2_header =
282-
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait);
291+
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, trait_ref2);
283292

284293
// Equate the headers to find their intersection (the general type, with infer vars,
285294
// that may apply both impls).
@@ -489,11 +498,14 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
489498
/// after negating, giving us `&str: !Error`. This is a negative impl provided by
490499
/// libstd, and therefore we can guarantee for certain that libstd will never add
491500
/// a positive impl for `&str: Error` (without it being a breaking change).
492-
fn impl_intersection_has_negative_obligation(
493-
tcx: TyCtxt<'_>,
501+
fn impl_intersection_has_negative_obligation<'tcx>(
502+
tcx: TyCtxt<'tcx>,
494503
impl1_def_id: DefId,
495504
impl2_def_id: DefId,
496-
is_of_trait: bool,
505+
trait_refs: Option<(
506+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
507+
ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
508+
)>,
497509
) -> bool {
498510
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
499511

@@ -503,11 +515,12 @@ fn impl_intersection_has_negative_obligation(
503515
let root_universe = infcx.universe();
504516
assert_eq!(root_universe, ty::UniverseIndex::ROOT);
505517

506-
let impl1_header = fresh_impl_header(infcx, impl1_def_id, is_of_trait);
518+
let (trait_ref1, trait_ref2) = trait_refs.unzip();
519+
let impl1_header = fresh_impl_header(infcx, impl1_def_id, trait_ref1);
507520
let param_env =
508521
ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)).instantiate(tcx, impl1_header.impl_args);
509522

510-
let impl2_header = fresh_impl_header(infcx, impl2_def_id, is_of_trait);
523+
let impl2_header = fresh_impl_header(infcx, impl2_def_id, trait_ref2);
511524

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

0 commit comments

Comments
 (0)