Implement impl_subject_and_oblig instead of repeating the impls

This commit is contained in:
Santiago Pastorino 2022-03-24 18:41:30 -03:00
parent d96faef913
commit 42e986f77b
No known key found for this signature in database
GPG Key ID: 8131A24E0C79EFAF
3 changed files with 26 additions and 74 deletions

View File

@ -7,7 +7,7 @@
use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{CombinedSnapshot, InferOk, RegionckMode}; use crate::infer::{CombinedSnapshot, InferOk, RegionckMode};
use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::util::{impl_trait_ref_and_oblig, inherent_impl_and_oblig}; use crate::traits::util::impl_subject_and_oblig;
use crate::traits::SkipLeakCheck; use crate::traits::SkipLeakCheck;
use crate::traits::{ use crate::traits::{
self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
@ -316,38 +316,16 @@ fn negative_impl<'cx, 'tcx>(
Err(err) => bug!("failed to fully normalize {:?}: {:?}", impl1_def_id, err), Err(err) => bug!("failed to fully normalize {:?}: {:?}", impl1_def_id, err),
}; };
// Attempt to prove that impl2 applies, given all of the above.
let selcx = &mut SelectionContext::new(&infcx);
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
let (subject2, obligations) = let (subject2, obligations) =
impl_subject_and_obligations(&infcx, impl_env, subject1, impl2_def_id); impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
!equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations) !equate(&infcx, impl_env, impl1_def_id, subject1, subject2, obligations)
}) })
} }
fn impl_subject_and_obligations<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>,
impl_env: ty::ParamEnv<'tcx>,
subject1: ImplSubject<'tcx>,
impl2_def_id: DefId,
) -> (ImplSubject<'tcx>, Box<dyn Iterator<Item = PredicateObligation<'tcx>> + 'tcx>) {
if let ImplSubject::Trait(_) = subject1 {
// Attempt to prove that impl2 applies, given all of the above.
let selcx = &mut SelectionContext::new(&infcx);
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
let (impl2_trait_ref, obligations) =
impl_trait_ref_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
(ImplSubject::Trait(impl2_trait_ref), Box::new(obligations))
} else {
// Attempt to prove that impl2 applies, given all of the above.
let selcx = &mut SelectionContext::new(&infcx);
let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
let (impl2_ty, obligations) =
inherent_impl_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
(ImplSubject::Inherent(impl2_ty), Box::new(obligations))
}
}
fn equate<'cx, 'tcx>( fn equate<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'cx, 'tcx>,
impl_env: ty::ParamEnv<'tcx>, impl_env: ty::ParamEnv<'tcx>,

View File

@ -20,12 +20,12 @@ use rustc_errors::{struct_span_err, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, ImplSubject, TyCtxt};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use super::util::impl_trait_ref_and_oblig; use super::util;
use super::{FulfillmentContext, SelectionContext}; use super::{FulfillmentContext, SelectionContext};
/// Information pertinent to an overlapping impl error. /// Information pertinent to an overlapping impl error.
@ -186,18 +186,20 @@ fn fulfill_implication<'a, 'tcx>(
param_env, source_trait_ref, target_impl param_env, source_trait_ref, target_impl
); );
let source_trait = ImplSubject::Trait(source_trait_ref);
let selcx = &mut SelectionContext::new(&infcx); let selcx = &mut SelectionContext::new(&infcx);
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
let (target_trait_ref, obligations) = let (target_trait, obligations) =
impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs); util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs);
// do the impls unify? If not, no specialization. // do the impls unify? If not, no specialization.
let Ok(InferOk { obligations: more_obligations, .. }) = let Ok(InferOk { obligations: more_obligations, .. }) =
infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait)
else { else {
debug!( debug!(
"fulfill_implication: {:?} does not unify with {:?}", "fulfill_implication: {:?} does not unify with {:?}",
source_trait_ref, target_trait_ref source_trait, target_trait
); );
return Err(()); return Err(());
}; };
@ -225,7 +227,7 @@ fn fulfill_implication<'a, 'tcx>(
[] => { [] => {
debug!( debug!(
"fulfill_implication: an impl for {:?} specializes {:?}", "fulfill_implication: an impl for {:?} specializes {:?}",
source_trait_ref, target_trait_ref source_trait, target_trait
); );
// Now resolve the *substitution* we built for the target earlier, replacing // Now resolve the *substitution* we built for the target earlier, replacing
@ -237,8 +239,8 @@ fn fulfill_implication<'a, 'tcx>(
debug!( debug!(
"fulfill_implication: for impls on {:?} and {:?}, \ "fulfill_implication: for impls on {:?} and {:?}, \
could not fulfill: {:?} given {:?}", could not fulfill: {:?} given {:?}",
source_trait_ref, source_trait,
target_trait_ref, target_trait,
errors, errors,
param_env.caller_bounds() param_env.caller_bounds()
); );

View File

@ -6,7 +6,7 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeFoldable};
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
pub use rustc_infer::traits::{self, util::*}; pub use rustc_infer::traits::{self, util::*};
@ -190,19 +190,19 @@ impl Iterator for SupertraitDefIds<'_> {
// Other // Other
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// Instantiate all bound parameters of the impl with the given substs, /// Instantiate all bound parameters of the impl subject with the given substs,
/// returning the resulting trait ref and all obligations that arise. /// returning the resulting subject and all obligations that arise.
/// The obligations are closed under normalization. /// The obligations are closed under normalization.
pub fn impl_trait_ref_and_oblig<'a, 'tcx>( pub fn impl_subject_and_oblig<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>, selcx: &mut SelectionContext<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
impl_def_id: DefId, impl_def_id: DefId,
impl_substs: SubstsRef<'tcx>, impl_substs: SubstsRef<'tcx>,
) -> (ty::TraitRef<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) { ) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); let subject = selcx.tcx().impl_subject(impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); let subject = subject.subst(selcx.tcx(), impl_substs);
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = let Normalized { value: subject, obligations: normalization_obligations1 } =
super::normalize(selcx, param_env, ObligationCause::dummy(), impl_trait_ref); super::normalize(selcx, param_env, ObligationCause::dummy(), subject);
let predicates = selcx.tcx().predicates_of(impl_def_id); let predicates = selcx.tcx().predicates_of(impl_def_id);
let predicates = predicates.instantiate(selcx.tcx(), impl_substs); let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
@ -215,35 +215,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
.chain(normalization_obligations1.into_iter()) .chain(normalization_obligations1.into_iter())
.chain(normalization_obligations2.into_iter()); .chain(normalization_obligations2.into_iter());
(impl_trait_ref, impl_obligations) (subject, impl_obligations)
}
/// Instantiate all bound parameters of the impl with the given substs,
/// returning the resulting trait ref and all obligations that arise.
/// The obligations are closed under normalization.
pub fn inherent_impl_and_oblig<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: DefId,
impl_substs: SubstsRef<'tcx>,
) -> (Ty<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
let ty = selcx.tcx().type_of(impl_def_id);
let ty = ty.subst(selcx.tcx(), impl_substs);
let Normalized { value: ty, obligations: normalization_obligations1 } =
super::normalize(selcx, param_env, ObligationCause::dummy(), ty);
let predicates = selcx.tcx().predicates_of(impl_def_id);
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
let Normalized { value: predicates, obligations: normalization_obligations2 } =
super::normalize(selcx, param_env, ObligationCause::dummy(), predicates);
let impl_obligations =
predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
let impl_obligations = impl_obligations
.chain(normalization_obligations1.into_iter())
.chain(normalization_obligations2.into_iter());
(ty, impl_obligations)
} }
pub fn predicates_for_generics<'tcx>( pub fn predicates_for_generics<'tcx>(