Skip to content

Commit 9cce78a

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

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 52 additions & 32 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, None, impl2_def_id, None, skip_leak_check, overlap_mode)
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 impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
141+
let impl2_trait_ref = tcx.impl_trait_ref(impl2_def_id).unwrap();
142+
let impl1_args = impl1_trait_ref.skip_binder().args;
143+
let impl2_args = impl2_trait_ref.skip_binder().args;
142144
let may_overlap =
143145
DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args);
144146

@@ -148,36 +150,47 @@ 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+
overlapping_impls(
154+
tcx,
155+
impl1_def_id,
156+
Some(impl1_trait_ref),
157+
impl2_def_id,
158+
Some(impl2_trait_ref),
159+
skip_leak_check,
160+
overlap_mode,
161+
)
152162
}
153163

154-
fn overlapping_impls(
155-
tcx: TyCtxt<'_>,
164+
fn overlapping_impls<'tcx>(
165+
tcx: TyCtxt<'tcx>,
156166
impl1_def_id: DefId,
167+
impl1_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
157168
impl2_def_id: DefId,
169+
impl2_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
158170
skip_leak_check: SkipLeakCheck,
159171
overlap_mode: OverlapMode,
160-
is_of_trait: bool,
161-
) -> Option<OverlapResult<'_>> {
172+
) -> Option<OverlapResult<'tcx>> {
162173
if tcx.next_trait_solver_in_coherence() {
163174
overlap(
164175
tcx,
165176
TrackAmbiguityCauses::Yes,
166177
skip_leak_check,
167178
impl1_def_id,
179+
impl1_trait_ref,
168180
impl2_def_id,
181+
impl2_trait_ref,
169182
overlap_mode,
170-
is_of_trait,
171183
)
172184
} else {
173185
let _overlap_with_bad_diagnostics = overlap(
174186
tcx,
175187
TrackAmbiguityCauses::No,
176188
skip_leak_check,
177189
impl1_def_id,
190+
impl1_trait_ref,
178191
impl2_def_id,
192+
impl2_trait_ref,
179193
overlap_mode,
180-
is_of_trait,
181194
)?;
182195

183196
// In the case where we detect an error, run the check again, but
@@ -188,9 +201,10 @@ fn overlapping_impls(
188201
TrackAmbiguityCauses::Yes,
189202
skip_leak_check,
190203
impl1_def_id,
204+
impl1_trait_ref,
191205
impl2_def_id,
206+
impl2_trait_ref,
192207
overlap_mode,
193-
is_of_trait,
194208
)
195209
.unwrap();
196210
Some(overlap)
@@ -200,7 +214,7 @@ fn overlapping_impls(
200214
fn fresh_impl_header<'tcx>(
201215
infcx: &InferCtxt<'tcx>,
202216
impl_def_id: DefId,
203-
is_of_trait: bool,
217+
trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
204218
) -> ImplHeader<'tcx> {
205219
let tcx = infcx.tcx;
206220
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
@@ -209,8 +223,7 @@ fn fresh_impl_header<'tcx>(
209223
impl_def_id,
210224
impl_args,
211225
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)),
226+
trait_ref: trait_ref.map(|trait_ref| trait_ref.instantiate(tcx, impl_args)),
214227
predicates: tcx
215228
.predicates_of(impl_def_id)
216229
.instantiate(tcx, impl_args)
@@ -224,9 +237,9 @@ fn fresh_impl_header_normalized<'tcx>(
224237
infcx: &InferCtxt<'tcx>,
225238
param_env: ty::ParamEnv<'tcx>,
226239
impl_def_id: DefId,
227-
is_of_trait: bool,
240+
trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
228241
) -> ImplHeader<'tcx> {
229-
let header = fresh_impl_header(infcx, impl_def_id, is_of_trait);
242+
let header = fresh_impl_header(infcx, impl_def_id, trait_ref);
230243

231244
let InferOk { value: mut header, obligations } =
232245
infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
@@ -243,19 +256,25 @@ fn overlap<'tcx>(
243256
track_ambiguity_causes: TrackAmbiguityCauses,
244257
skip_leak_check: SkipLeakCheck,
245258
impl1_def_id: DefId,
259+
impl1_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
246260
impl2_def_id: DefId,
261+
impl2_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
247262
overlap_mode: OverlapMode,
248-
is_of_trait: bool,
249263
) -> Option<OverlapResult<'tcx>> {
250264
if overlap_mode.use_negative_impl() {
251-
if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, is_of_trait)
252-
|| impl_intersection_has_negative_obligation(
253-
tcx,
254-
impl2_def_id,
255-
impl1_def_id,
256-
is_of_trait,
257-
)
258-
{
265+
if impl_intersection_has_negative_obligation(
266+
tcx,
267+
impl1_def_id,
268+
impl1_trait_ref,
269+
impl2_def_id,
270+
impl2_trait_ref,
271+
) || impl_intersection_has_negative_obligation(
272+
tcx,
273+
impl2_def_id,
274+
impl2_trait_ref,
275+
impl1_def_id,
276+
impl1_trait_ref,
277+
) {
259278
return None;
260279
}
261280
}
@@ -277,9 +296,9 @@ fn overlap<'tcx>(
277296
let param_env = ty::ParamEnv::empty();
278297

279298
let impl1_header =
280-
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait);
299+
fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, impl1_trait_ref);
281300
let impl2_header =
282-
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait);
301+
fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, impl2_trait_ref);
283302

284303
// Equate the headers to find their intersection (the general type, with infer vars,
285304
// that may apply both impls).
@@ -489,11 +508,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
489508
/// after negating, giving us `&str: !Error`. This is a negative impl provided by
490509
/// libstd, and therefore we can guarantee for certain that libstd will never add
491510
/// a positive impl for `&str: Error` (without it being a breaking change).
492-
fn impl_intersection_has_negative_obligation(
493-
tcx: TyCtxt<'_>,
511+
fn impl_intersection_has_negative_obligation<'tcx>(
512+
tcx: TyCtxt<'tcx>,
494513
impl1_def_id: DefId,
514+
impl1_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
495515
impl2_def_id: DefId,
496-
is_of_trait: bool,
516+
impl2_trait_ref: Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>>,
497517
) -> bool {
498518
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
499519

@@ -503,11 +523,11 @@ fn impl_intersection_has_negative_obligation(
503523
let root_universe = infcx.universe();
504524
assert_eq!(root_universe, ty::UniverseIndex::ROOT);
505525

506-
let impl1_header = fresh_impl_header(infcx, impl1_def_id, is_of_trait);
526+
let impl1_header = fresh_impl_header(infcx, impl1_def_id, impl1_trait_ref);
507527
let param_env =
508528
ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)).instantiate(tcx, impl1_header.impl_args);
509529

510-
let impl2_header = fresh_impl_header(infcx, impl2_def_id, is_of_trait);
530+
let impl2_header = fresh_impl_header(infcx, impl2_def_id, impl2_trait_ref);
511531

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

0 commit comments

Comments
 (0)