Skip to content

Commit 42e986f

Browse files
committed
Implement impl_subject_and_oblig instead of repeating the impls
1 parent d96faef commit 42e986f

File tree

3 files changed

+26
-74
lines changed

3 files changed

+26
-74
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+5-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use crate::infer::outlives::env::OutlivesEnvironment;
88
use crate::infer::{CombinedSnapshot, InferOk, RegionckMode};
99
use crate::traits::select::IntercrateAmbiguityCause;
10-
use crate::traits::util::{impl_trait_ref_and_oblig, inherent_impl_and_oblig};
10+
use crate::traits::util::impl_subject_and_oblig;
1111
use crate::traits::SkipLeakCheck;
1212
use crate::traits::{
1313
self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
@@ -316,36 +316,14 @@ fn negative_impl<'cx, 'tcx>(
316316
Err(err) => bug!("failed to fully normalize {:?}: {:?}", impl1_def_id, err),
317317
};
318318

319-
let (subject2, obligations) =
320-
impl_subject_and_obligations(&infcx, impl_env, subject1, impl2_def_id);
321-
322-
!equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations)
323-
})
324-
}
325-
326-
fn impl_subject_and_obligations<'cx, 'tcx>(
327-
infcx: &InferCtxt<'cx, 'tcx>,
328-
impl_env: ty::ParamEnv<'tcx>,
329-
subject1: ImplSubject<'tcx>,
330-
impl2_def_id: DefId,
331-
) -> (ImplSubject<'tcx>, Box<dyn Iterator<Item = PredicateObligation<'tcx>> + 'tcx>) {
332-
if let ImplSubject::Trait(_) = subject1 {
333319
// Attempt to prove that impl2 applies, given all of the above.
334320
let selcx = &mut SelectionContext::new(&infcx);
335321
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
336-
let (impl2_trait_ref, obligations) =
337-
impl_trait_ref_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
338-
339-
(ImplSubject::Trait(impl2_trait_ref), Box::new(obligations))
340-
} else {
341-
// Attempt to prove that impl2 applies, given all of the above.
342-
let selcx = &mut SelectionContext::new(&infcx);
343-
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
344-
let (impl2_ty, obligations) =
345-
inherent_impl_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
322+
let (subject2, obligations) =
323+
impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
346324

347-
(ImplSubject::Inherent(impl2_ty), Box::new(obligations))
348-
}
325+
!equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations)
326+
})
349327
}
350328

351329
fn equate<'cx, 'tcx>(

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

+11-9
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ use rustc_errors::{struct_span_err, EmissionGuarantee};
2020
use rustc_hir::def_id::{DefId, LocalDefId};
2121
use rustc_middle::lint::LintDiagnosticBuilder;
2222
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
23-
use rustc_middle::ty::{self, TyCtxt};
23+
use rustc_middle::ty::{self, ImplSubject, TyCtxt};
2424
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
2525
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
2626
use rustc_span::{Span, DUMMY_SP};
2727

28-
use super::util::impl_trait_ref_and_oblig;
28+
use super::util;
2929
use super::{FulfillmentContext, SelectionContext};
3030

3131
/// Information pertinent to an overlapping impl error.
@@ -186,18 +186,20 @@ fn fulfill_implication<'a, 'tcx>(
186186
param_env, source_trait_ref, target_impl
187187
);
188188

189+
let source_trait = ImplSubject::Trait(source_trait_ref);
190+
189191
let selcx = &mut SelectionContext::new(&infcx);
190192
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
191-
let (target_trait_ref, obligations) =
192-
impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
193+
let (target_trait, obligations) =
194+
util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs);
193195

194196
// do the impls unify? If not, no specialization.
195197
let Ok(InferOk { obligations: more_obligations, .. }) =
196-
infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref)
198+
infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait)
197199
else {
198200
debug!(
199201
"fulfill_implication: {:?} does not unify with {:?}",
200-
source_trait_ref, target_trait_ref
202+
source_trait, target_trait
201203
);
202204
return Err(());
203205
};
@@ -225,7 +227,7 @@ fn fulfill_implication<'a, 'tcx>(
225227
[] => {
226228
debug!(
227229
"fulfill_implication: an impl for {:?} specializes {:?}",
228-
source_trait_ref, target_trait_ref
230+
source_trait, target_trait
229231
);
230232

231233
// Now resolve the *substitution* we built for the target earlier, replacing
@@ -237,8 +239,8 @@ fn fulfill_implication<'a, 'tcx>(
237239
debug!(
238240
"fulfill_implication: for impls on {:?} and {:?}, \
239241
could not fulfill: {:?} given {:?}",
240-
source_trait_ref,
241-
target_trait_ref,
242+
source_trait,
243+
target_trait,
242244
errors,
243245
param_env.caller_bounds()
244246
);

compiler/rustc_trait_selection/src/traits/util.rs

+10-38
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use smallvec::SmallVec;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_hir::def_id::DefId;
88
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
9-
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
9+
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeFoldable};
1010

1111
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
1212
pub use rustc_infer::traits::{self, util::*};
@@ -190,19 +190,19 @@ impl Iterator for SupertraitDefIds<'_> {
190190
// Other
191191
///////////////////////////////////////////////////////////////////////////
192192

193-
/// Instantiate all bound parameters of the impl with the given substs,
194-
/// returning the resulting trait ref and all obligations that arise.
193+
/// Instantiate all bound parameters of the impl subject with the given substs,
194+
/// returning the resulting subject and all obligations that arise.
195195
/// The obligations are closed under normalization.
196-
pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
196+
pub fn impl_subject_and_oblig<'a, 'tcx>(
197197
selcx: &mut SelectionContext<'a, 'tcx>,
198198
param_env: ty::ParamEnv<'tcx>,
199199
impl_def_id: DefId,
200200
impl_substs: SubstsRef<'tcx>,
201-
) -> (ty::TraitRef<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
202-
let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
203-
let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
204-
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
205-
super::normalize(selcx, param_env, ObligationCause::dummy(), impl_trait_ref);
201+
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
202+
let subject = selcx.tcx().impl_subject(impl_def_id);
203+
let subject = subject.subst(selcx.tcx(), impl_substs);
204+
let Normalized { value: subject, obligations: normalization_obligations1 } =
205+
super::normalize(selcx, param_env, ObligationCause::dummy(), subject);
206206

207207
let predicates = selcx.tcx().predicates_of(impl_def_id);
208208
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
@@ -215,35 +215,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
215215
.chain(normalization_obligations1.into_iter())
216216
.chain(normalization_obligations2.into_iter());
217217

218-
(impl_trait_ref, impl_obligations)
219-
}
220-
221-
/// Instantiate all bound parameters of the impl with the given substs,
222-
/// returning the resulting trait ref and all obligations that arise.
223-
/// The obligations are closed under normalization.
224-
pub fn inherent_impl_and_oblig<'a, 'tcx>(
225-
selcx: &mut SelectionContext<'a, 'tcx>,
226-
param_env: ty::ParamEnv<'tcx>,
227-
impl_def_id: DefId,
228-
impl_substs: SubstsRef<'tcx>,
229-
) -> (Ty<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
230-
let ty = selcx.tcx().type_of(impl_def_id);
231-
let ty = ty.subst(selcx.tcx(), impl_substs);
232-
let Normalized { value: ty, obligations: normalization_obligations1 } =
233-
super::normalize(selcx, param_env, ObligationCause::dummy(), ty);
234-
235-
let predicates = selcx.tcx().predicates_of(impl_def_id);
236-
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
237-
let Normalized { value: predicates, obligations: normalization_obligations2 } =
238-
super::normalize(selcx, param_env, ObligationCause::dummy(), predicates);
239-
let impl_obligations =
240-
predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
241-
242-
let impl_obligations = impl_obligations
243-
.chain(normalization_obligations1.into_iter())
244-
.chain(normalization_obligations2.into_iter());
245-
246-
(ty, impl_obligations)
218+
(subject, impl_obligations)
247219
}
248220

249221
pub fn predicates_for_generics<'tcx>(

0 commit comments

Comments
 (0)