From 42e986f77ba350f9cb28958d9ef19af06007ac1c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 24 Mar 2022 18:41:30 -0300 Subject: [PATCH] Implement impl_subject_and_oblig instead of repeating the impls --- .../src/traits/coherence.rs | 32 ++----------- .../src/traits/specialize/mod.rs | 20 ++++---- .../rustc_trait_selection/src/traits/util.rs | 48 ++++--------------- 3 files changed, 26 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ed9ddb51834..ec4f8084e21 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -7,7 +7,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{CombinedSnapshot, InferOk, RegionckMode}; 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::{ 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), }; + // 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) = - 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) }) } -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> + '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>( infcx: &InferCtxt<'cx, 'tcx>, impl_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 79471065ccc..328e0d2e0e9 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -20,12 +20,12 @@ use rustc_errors::{struct_span_err, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::lint::LintDiagnosticBuilder; 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::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_span::{Span, DUMMY_SP}; -use super::util::impl_trait_ref_and_oblig; +use super::util; use super::{FulfillmentContext, SelectionContext}; /// Information pertinent to an overlapping impl error. @@ -186,18 +186,20 @@ fn fulfill_implication<'a, 'tcx>( param_env, source_trait_ref, target_impl ); + let source_trait = ImplSubject::Trait(source_trait_ref); + let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); - let (target_trait_ref, obligations) = - impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs); + let (target_trait, obligations) = + util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs); // do the impls unify? If not, no specialization. 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 { debug!( "fulfill_implication: {:?} does not unify with {:?}", - source_trait_ref, target_trait_ref + source_trait, target_trait ); return Err(()); }; @@ -225,7 +227,7 @@ fn fulfill_implication<'a, 'tcx>( [] => { debug!( "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 @@ -237,8 +239,8 @@ fn fulfill_implication<'a, 'tcx>( debug!( "fulfill_implication: for impls on {:?} and {:?}, \ could not fulfill: {:?} given {:?}", - source_trait_ref, - target_trait_ref, + source_trait, + target_trait, errors, param_env.caller_bounds() ); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 7b64deac99d..7543d1f9a7b 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,7 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; 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}; pub use rustc_infer::traits::{self, util::*}; @@ -190,19 +190,19 @@ impl Iterator for SupertraitDefIds<'_> { // Other /////////////////////////////////////////////////////////////////////////// -/// Instantiate all bound parameters of the impl with the given substs, -/// returning the resulting trait ref and all obligations that arise. +/// Instantiate all bound parameters of the impl subject with the given substs, +/// returning the resulting subject and all obligations that arise. /// 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>, param_env: ty::ParamEnv<'tcx>, impl_def_id: DefId, impl_substs: SubstsRef<'tcx>, -) -> (ty::TraitRef<'tcx>, impl Iterator>) { - let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); - let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); - let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = - super::normalize(selcx, param_env, ObligationCause::dummy(), impl_trait_ref); +) -> (ImplSubject<'tcx>, impl Iterator>) { + let subject = selcx.tcx().impl_subject(impl_def_id); + let subject = subject.subst(selcx.tcx(), impl_substs); + let Normalized { value: subject, obligations: normalization_obligations1 } = + super::normalize(selcx, param_env, ObligationCause::dummy(), subject); let predicates = selcx.tcx().predicates_of(impl_def_id); 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_obligations2.into_iter()); - (impl_trait_ref, 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>) { - 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) + (subject, impl_obligations) } pub fn predicates_for_generics<'tcx>(